Jump to content

MediaWiki:Common.js: Difference between revisions

The comprehensive free global encyclopedia of CEOs, corporate leadership, and business excellence
Updated 3D cloud to show CEO articles with traffic-based sizing and Wikipedia fonts
Fix 3D CEO cloud rendering - proper centering, Fibonacci sphere distribution, Wikipedia font, better visibility
Line 16: Line 16:
$(document).ready(function() {
$(document).ready(function() {
     var placeholder = document.getElementById('ceocloud-placeholder');
     var placeholder = document.getElementById('ceocloud-placeholder');
     if (!placeholder) return;
     if (!placeholder) {
        console.log('CEO Cloud: placeholder not found');
        return;
    }


     // Get CEO data from the parser function
     // Get CEO data from the parser function
     var ceoDataEl = document.getElementById('ceo-data');
     var ceoDataEl = document.getElementById('ceo-data');
     if (!ceoDataEl) return;
     if (!ceoDataEl) {
        console.log('CEO Cloud: ceo-data element not found');
        return;
    }


     var ceoDataJson = ceoDataEl.getAttribute('data-ceos');
     var ceoDataJson = ceoDataEl.getAttribute('data-ceos');
     if (!ceoDataJson) return;
     if (!ceoDataJson) {
        console.log('CEO Cloud: data-ceos attribute empty');
        return;
    }


     var tags = JSON.parse(ceoDataJson);
     var tags = JSON.parse(ceoDataJson);
     if (!tags || tags.length === 0) return;
     if (!tags || tags.length === 0) {
        console.log('CEO Cloud: no tags found');
        return;
    }
 
    console.log('CEO Cloud: Initializing with ' + tags.length + ' CEOs');


     // Create cloud container
     // Create cloud container with proper centering
     var cloud = document.createElement('div');
     var cloud = document.createElement('div');
     cloud.style.position = 'relative';
     cloud.style.position = 'relative';
     cloud.style.width = '100%';
     cloud.style.width = '100%';
     cloud.style.height = '400px';
     cloud.style.height = '400px';
     cloud.style.perspective = '1000px';
     cloud.style.overflow = 'hidden';


    // Create inner sphere container
     var sphere = document.createElement('div');
     var sphere = document.createElement('div');
     sphere.style.position = 'absolute';
     sphere.style.position = 'absolute';
     sphere.style.width = '100%';
    sphere.style.left = '50%';
     sphere.style.height = '100%';
    sphere.style.top = '50%';
     sphere.style.width = '1px';
     sphere.style.height = '1px';
     sphere.style.transformStyle = 'preserve-3d';
     sphere.style.transformStyle = 'preserve-3d';
     sphere.style.transition = 'transform 0.1s';
     sphere.style.transition = 'transform 0.5s ease-out';


     // Create tags in 3D space
     // Distribute tags in 3D sphere using Fibonacci spiral
     var radius = 180;
     var radius = 200;
     var angleStep = (Math.PI * 2) / tags.length;
     var phi = Math.PI * (3 - Math.sqrt(5)); // Golden angle in radians


     tags.forEach(function(tag, i) {
     tags.forEach(function(tag, i) {
         var angle = angleStep * i;
        // Fibonacci sphere distribution
         var vAngle = (Math.random() - 0.5) * Math.PI;
         var y = 1 - (i / (tags.length - 1)) * 2; // y goes from 1 to -1
         var radiusAtY = Math.sqrt(1 - y * y); // radius at y
        var theta = phi * i; // golden angle increment
 
        var x = Math.cos(theta) * radiusAtY;
        var z = Math.sin(theta) * radiusAtY;
 
        // Scale to our radius
        var posX = x * radius;
        var posY = y * radius;
        var posZ = z * radius;


        // Create link element
         var link = document.createElement('a');
         var link = document.createElement('a');
         link.href = tag.url;
         link.href = tag.url;
         link.textContent = tag.text;
         link.textContent = tag.text;
         link.style.position = 'absolute';
         link.style.position = 'absolute';
        link.style.left = '0';
        link.style.top = '0';
         link.style.color = '#ffffff';
         link.style.color = '#ffffff';
         link.style.textDecoration = 'none';
         link.style.textDecoration = 'none';
         link.style.fontSize = tag.size + 'px';
         link.style.fontSize = tag.size + 'px';
         link.style.fontWeight = '400';
         link.style.fontWeight = '400';
         link.style.fontFamily = 'Georgia, "Times New Roman", Times, serif'; // Wikipedia-style serif font
         link.style.fontFamily = '"Linux Libertine", Georgia, "Times New Roman", Times, serif';
         link.style.whiteSpace = 'nowrap';
         link.style.whiteSpace = 'nowrap';
         link.style.transition = 'all 0.3s';
         link.style.transition = 'all 0.3s ease';
         link.style.textShadow = '0 2px 4px rgba(0,0,0,0.5)';
         link.style.textShadow = '0 2px 8px rgba(0,0,0,0.8), 0 0 20px rgba(0,0,0,0.5)';
        link.style.cursor = 'pointer';
        link.style.transformStyle = 'preserve-3d';
        link.style.transform = 'translate3d(' + posX + 'px, ' + posY + 'px, ' + posZ + 'px) translate(-50%, -50%)';
        link.style.backfaceVisibility = 'hidden';


         var x = radius * Math.cos(angle) * Math.cos(vAngle);
         // Store original position for hover effects
         var y = radius * Math.sin(vAngle);
         link.dataset.x = posX;
        var z = radius * Math.sin(angle) * Math.cos(vAngle);
         link.dataset.y = posY;
 
         link.dataset.z = posZ;
         link.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)';
         link.dataset.originalSize = tag.size;
         link.style.left = '50%';
         link.style.top = '50%';


        // Hover effects
         link.addEventListener('mouseenter', function() {
         link.addEventListener('mouseenter', function() {
             this.style.color = '#fbbf24';
             this.style.color = '#fbbf24';
             this.style.fontWeight = '700';
             this.style.fontWeight = '700';
             this.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px) scale(1.2)';
            var scale = 1.3;
             this.style.fontSize = (parseFloat(this.dataset.originalSize) * scale) + 'px';
            this.style.textShadow = '0 2px 12px rgba(251, 191, 36, 0.8), 0 0 30px rgba(251, 191, 36, 0.5)';
            this.style.zIndex = '1000';
         });
         });


Line 80: Line 116:
             this.style.color = '#ffffff';
             this.style.color = '#ffffff';
             this.style.fontWeight = '400';
             this.style.fontWeight = '400';
             this.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)';
             this.style.fontSize = this.dataset.originalSize + 'px';
            this.style.textShadow = '0 2px 8px rgba(0,0,0,0.8), 0 0 20px rgba(0,0,0,0.5)';
            this.style.zIndex = 'auto';
         });
         });


Line 87: Line 125:


     cloud.appendChild(sphere);
     cloud.appendChild(sphere);
    placeholder.innerHTML = ''; // Clear placeholder
     placeholder.appendChild(cloud);
     placeholder.appendChild(cloud);


     // Rotation animation
     // Rotation animation
     var angleX = 0;
     var angleX = 15; // Start with slight tilt
     var angleY = 0;
     var angleY = 0;
     var autoRotate = true;
     var autoRotate = true;
    var targetAngleX = 15;
    var targetAngleY = 0;


     function animate() {
     function animate() {
         if (autoRotate) {
         if (autoRotate) {
             angleY += 0.3;
             targetAngleY += 0.2;
            angleX += 0.1;
         }
         }
        // Smooth interpolation
        angleX += (targetAngleX - angleX) * 0.05;
        angleY += (targetAngleY - angleY) * 0.05;
         sphere.style.transform = 'rotateX(' + angleX + 'deg) rotateY(' + angleY + 'deg)';
         sphere.style.transform = 'rotateX(' + angleX + 'deg) rotateY(' + angleY + 'deg)';
         requestAnimationFrame(animate);
         requestAnimationFrame(animate);
Line 105: Line 150:
     animate();
     animate();


     // Pause rotation on hover
     // Interactive controls
     cloud.addEventListener('mouseenter', function() {
    var isDragging = false;
    var previousMouseX = 0;
    var previousMouseY = 0;
 
     cloud.addEventListener('mousedown', function(e) {
        isDragging = true;
         autoRotate = false;
         autoRotate = false;
        previousMouseX = e.clientX;
        previousMouseY = e.clientY;
        e.preventDefault();
    });
    document.addEventListener('mousemove', function(e) {
        if (isDragging) {
            var deltaX = e.clientX - previousMouseX;
            var deltaY = e.clientY - previousMouseY;
            targetAngleY += deltaX * 0.5;
            targetAngleX -= deltaY * 0.5;
            // Limit vertical rotation
            targetAngleX = Math.max(-60, Math.min(60, targetAngleX));
            previousMouseX = e.clientX;
            previousMouseY = e.clientY;
        }
    });
    document.addEventListener('mouseup', function() {
        if (isDragging) {
            isDragging = false;
            setTimeout(function() {
                autoRotate = true;
            }, 2000); // Resume auto-rotation after 2 seconds
        }
     });
     });


     cloud.addEventListener('mouseleave', function() {
    // Touch support for mobile
         autoRotate = true;
     cloud.addEventListener('touchstart', function(e) {
         if (e.touches.length === 1) {
            isDragging = true;
            autoRotate = false;
            previousMouseX = e.touches[0].clientX;
            previousMouseY = e.touches[0].clientY;
            e.preventDefault();
        }
     });
     });
    document.addEventListener('touchmove', function(e) {
        if (isDragging && e.touches.length === 1) {
            var deltaX = e.touches[0].clientX - previousMouseX;
            var deltaY = e.touches[0].clientY - previousMouseY;
            targetAngleY += deltaX * 0.5;
            targetAngleX -= deltaY * 0.5;
            targetAngleX = Math.max(-60, Math.min(60, targetAngleX));
            previousMouseX = e.touches[0].clientX;
            previousMouseY = e.touches[0].clientY;
        }
    });
    document.addEventListener('touchend', function() {
        if (isDragging) {
            isDragging = false;
            setTimeout(function() {
                autoRotate = true;
            }, 2000);
        }
    });
    console.log('CEO Cloud: Successfully initialized');
});
});

Revision as of 04:41, 22 October 2025

/* Common.js - Site-wide JavaScript */

/* Add copyright footer at the very bottom of page - single occurrence only */
$(document).ready(function() {
    // Remove any existing copyright footers first to prevent duplicates
    $('#footer-info-copyright, .ceo-copyright-footer').remove();

    // Create the copyright footer
    var copyright = '<div class="ceo-copyright-footer" id="footer-info-copyright" style="text-align: center; padding: 20px; background: #f8f9fa; border-top: 1px solid #ddd; margin-top: 40px; font-size: 0.85em; line-height: 1.6;">Text is available under the <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="nofollow">Creative Commons Attribution-ShareAlike 4.0 License</a>; additional terms may apply. By using this site, you agree to the <a href="/wiki/CEO.wiki:Terms_of_Use">Terms of Use</a>, <a href="/wiki/CEO.wiki:Privacy_Policy">Privacy Policy</a>, and all <a href="/wiki/CEO.wiki:General_disclaimer">disclaimers</a>. CEO.wiki is operated as an independent collaborative encyclopedia project and is not affiliated with Wikipedia or the Wikimedia Foundation. See our <a href="/wiki/CEO.wiki:Takedown_Request_Policy">Takedown Request Policy</a> for content concerns.</div>';

    // Append to the very bottom of the body
    $('body').append(copyright);
});

/* 3D CEO Tag Cloud for Main Page - Wikipedia Style */
$(document).ready(function() {
    var placeholder = document.getElementById('ceocloud-placeholder');
    if (!placeholder) {
        console.log('CEO Cloud: placeholder not found');
        return;
    }

    // Get CEO data from the parser function
    var ceoDataEl = document.getElementById('ceo-data');
    if (!ceoDataEl) {
        console.log('CEO Cloud: ceo-data element not found');
        return;
    }

    var ceoDataJson = ceoDataEl.getAttribute('data-ceos');
    if (!ceoDataJson) {
        console.log('CEO Cloud: data-ceos attribute empty');
        return;
    }

    var tags = JSON.parse(ceoDataJson);
    if (!tags || tags.length === 0) {
        console.log('CEO Cloud: no tags found');
        return;
    }

    console.log('CEO Cloud: Initializing with ' + tags.length + ' CEOs');

    // Create cloud container with proper centering
    var cloud = document.createElement('div');
    cloud.style.position = 'relative';
    cloud.style.width = '100%';
    cloud.style.height = '400px';
    cloud.style.overflow = 'hidden';

    // Create inner sphere container
    var sphere = document.createElement('div');
    sphere.style.position = 'absolute';
    sphere.style.left = '50%';
    sphere.style.top = '50%';
    sphere.style.width = '1px';
    sphere.style.height = '1px';
    sphere.style.transformStyle = 'preserve-3d';
    sphere.style.transition = 'transform 0.5s ease-out';

    // Distribute tags in 3D sphere using Fibonacci spiral
    var radius = 200;
    var phi = Math.PI * (3 - Math.sqrt(5)); // Golden angle in radians

    tags.forEach(function(tag, i) {
        // Fibonacci sphere distribution
        var y = 1 - (i / (tags.length - 1)) * 2; // y goes from 1 to -1
        var radiusAtY = Math.sqrt(1 - y * y); // radius at y
        var theta = phi * i; // golden angle increment

        var x = Math.cos(theta) * radiusAtY;
        var z = Math.sin(theta) * radiusAtY;

        // Scale to our radius
        var posX = x * radius;
        var posY = y * radius;
        var posZ = z * radius;

        // Create link element
        var link = document.createElement('a');
        link.href = tag.url;
        link.textContent = tag.text;
        link.style.position = 'absolute';
        link.style.left = '0';
        link.style.top = '0';
        link.style.color = '#ffffff';
        link.style.textDecoration = 'none';
        link.style.fontSize = tag.size + 'px';
        link.style.fontWeight = '400';
        link.style.fontFamily = '"Linux Libertine", Georgia, "Times New Roman", Times, serif';
        link.style.whiteSpace = 'nowrap';
        link.style.transition = 'all 0.3s ease';
        link.style.textShadow = '0 2px 8px rgba(0,0,0,0.8), 0 0 20px rgba(0,0,0,0.5)';
        link.style.cursor = 'pointer';
        link.style.transformStyle = 'preserve-3d';
        link.style.transform = 'translate3d(' + posX + 'px, ' + posY + 'px, ' + posZ + 'px) translate(-50%, -50%)';
        link.style.backfaceVisibility = 'hidden';

        // Store original position for hover effects
        link.dataset.x = posX;
        link.dataset.y = posY;
        link.dataset.z = posZ;
        link.dataset.originalSize = tag.size;

        // Hover effects
        link.addEventListener('mouseenter', function() {
            this.style.color = '#fbbf24';
            this.style.fontWeight = '700';
            var scale = 1.3;
            this.style.fontSize = (parseFloat(this.dataset.originalSize) * scale) + 'px';
            this.style.textShadow = '0 2px 12px rgba(251, 191, 36, 0.8), 0 0 30px rgba(251, 191, 36, 0.5)';
            this.style.zIndex = '1000';
        });

        link.addEventListener('mouseleave', function() {
            this.style.color = '#ffffff';
            this.style.fontWeight = '400';
            this.style.fontSize = this.dataset.originalSize + 'px';
            this.style.textShadow = '0 2px 8px rgba(0,0,0,0.8), 0 0 20px rgba(0,0,0,0.5)';
            this.style.zIndex = 'auto';
        });

        sphere.appendChild(link);
    });

    cloud.appendChild(sphere);
    placeholder.innerHTML = ''; // Clear placeholder
    placeholder.appendChild(cloud);

    // Rotation animation
    var angleX = 15; // Start with slight tilt
    var angleY = 0;
    var autoRotate = true;
    var targetAngleX = 15;
    var targetAngleY = 0;

    function animate() {
        if (autoRotate) {
            targetAngleY += 0.2;
        }

        // Smooth interpolation
        angleX += (targetAngleX - angleX) * 0.05;
        angleY += (targetAngleY - angleY) * 0.05;

        sphere.style.transform = 'rotateX(' + angleX + 'deg) rotateY(' + angleY + 'deg)';
        requestAnimationFrame(animate);
    }

    animate();

    // Interactive controls
    var isDragging = false;
    var previousMouseX = 0;
    var previousMouseY = 0;

    cloud.addEventListener('mousedown', function(e) {
        isDragging = true;
        autoRotate = false;
        previousMouseX = e.clientX;
        previousMouseY = e.clientY;
        e.preventDefault();
    });

    document.addEventListener('mousemove', function(e) {
        if (isDragging) {
            var deltaX = e.clientX - previousMouseX;
            var deltaY = e.clientY - previousMouseY;

            targetAngleY += deltaX * 0.5;
            targetAngleX -= deltaY * 0.5;

            // Limit vertical rotation
            targetAngleX = Math.max(-60, Math.min(60, targetAngleX));

            previousMouseX = e.clientX;
            previousMouseY = e.clientY;
        }
    });

    document.addEventListener('mouseup', function() {
        if (isDragging) {
            isDragging = false;
            setTimeout(function() {
                autoRotate = true;
            }, 2000); // Resume auto-rotation after 2 seconds
        }
    });

    // Touch support for mobile
    cloud.addEventListener('touchstart', function(e) {
        if (e.touches.length === 1) {
            isDragging = true;
            autoRotate = false;
            previousMouseX = e.touches[0].clientX;
            previousMouseY = e.touches[0].clientY;
            e.preventDefault();
        }
    });

    document.addEventListener('touchmove', function(e) {
        if (isDragging && e.touches.length === 1) {
            var deltaX = e.touches[0].clientX - previousMouseX;
            var deltaY = e.touches[0].clientY - previousMouseY;

            targetAngleY += deltaX * 0.5;
            targetAngleX -= deltaY * 0.5;
            targetAngleX = Math.max(-60, Math.min(60, targetAngleX));

            previousMouseX = e.touches[0].clientX;
            previousMouseY = e.touches[0].clientY;
        }
    });

    document.addEventListener('touchend', function() {
        if (isDragging) {
            isDragging = false;
            setTimeout(function() {
                autoRotate = true;
            }, 2000);
        }
    });

    console.log('CEO Cloud: Successfully initialized');
});