PageSourceSearch

https://tukyo.org/scripts/contact.js

js tukyo.org collected 2026-10-09 17:43:21 UTC 5,543 bytes, 118 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function () {
2    console.log('Contact details loaded...');
3
4    const linkIcon = '<i class="fa-solid fa-arrow-up-right-from-square"></i>';
5    const copyIcon = '<i class="fa-solid fa-copy"></i>';
6
7    const contactDetails = {
8        Email: { address: "[email protected]", icon: '<i class="fa-solid fa-envelope"></i>', hoverIcon: copyIcon },
9        deSypher: { link: "https://desypher.net/", icon: '<i class="fa-solid fa-globe"></i>', hoverIcon: linkIcon },
10        Github: { link: "https://github.com/tukyo", icon: '<i class="fa-brands fa-github"></i>', hoverIcon: linkIcon  },
11        TwitterX: { link: "https://twitter.com/tukyowave", icon: '<i class="fa-brands fa-twitter"></i>', hoverIcon: linkIcon  },
12        Telegram: { link: "https://t.me/tukyohub", icon: '<i class="fa-brands fa-telegram"></i>', hoverIcon: linkIcon  },
13        Instagram: { link: "https://instagram.com/tukyowave", icon: '<i class="fa-brands fa-instagram"></i>', hoverIcon: linkIcon  },
14        Youtube: { link: "https://www.youtube.com/tukyo", icon: '<i class="fa-brands fa-youtube"></i>', hoverIcon: linkIcon  },
15        Linkedin: { link: "https://linkedin.com/in/tukyo/", icon: '<i class="fa-brands fa-linkedin"></i>', hoverIcon: linkIcon  },
16        // Medium: { link: "https://tukyo.medium.com/", icon: '<i class="fa-brands fa-medium"></i>', hoverIcon: linkIcon  },
17    };
18
19    const contactColors = [
20        { light: "rgba(255,123,123,1)", dark: "rgba(103,25,19,1)" },
21        { light: "rgba(255,214,123,1)", dark: "rgba(103,78,26,1)" },
22        { light: "rgba(123,255,171,1)", dark: "rgba(17,123,23,1)" },
23        { light: "rgba(123,171,255,1)", dark: "rgba(24,40,120,1)" },
24        { light: "rgba(255,123,255,1)", dark: "rgba(146,29,145,1)" }
25    ];
26
27    const contactContent = document.querySelector('.contact-content');
28
29    const hoverRadius = 100;
30    const movementIntensity = 10;
31    const easingSpeed = 0.1;
32
33    if (contactContent) {
34        const bubbles = [];
35    
36        Object.keys(contactDetails).forEach(key => {
37            const contactItem = document.createElement('div');
38            contactItem.className = 'contact-item';
39    
40            const chosen = contactColors[Math.floor(Math.random() * contactColors.length)];
41            contactItem.style.background = `radial-gradient(circle at 30% 30%, ${chosen.light}, ${chosen.dark})`;
42    
43            const linkElement = document.createElement('div');
44            linkElement.innerHTML = contactDetails[key].icon;
45            linkElement.className = 'contact-link';
46    
47            contactItem.appendChild(linkElement);
48    
49            if (key === 'Email') {
50                contactItem.title = "Click to copy email";
51                contactItem.addEventListener('click', () => {
52                    navigator.clipboard.writeText(contactDetails[key].address).then(() => {
53                        alert('Email copied to clipboard!');
54                    });
55                });
56            } else {
57                contactItem.title = `Visit ${key}`;
58                contactItem.addEventListener('click', () => {
59                    window.open(contactDetails[key].link, '_blank');
60                });
61            }
62    
63            contactItem.addEventListener('mouseenter', () => {
64                linkElement.innerHTML = contactDetails[key].hoverIcon;
65            });
66    
67            contactItem.addEventListener('mouseleave', () => {
68                linkElement.innerHTML = contactDetails[key].icon;
69            });
70    
71            contactItem.dataset.targetX = 0;
72            contactItem.dataset.targetY = 0;
73            bubbles.push(contactItem);
74            contactContent.appendChild(contactItem);
75        });
76    
77
78        document.addEventListener('mousemove', (e) => {
79            const mouseX = e.clientX;
80            const mouseY = e.clientY;
81    
82            bubbles.forEach(bubble => {
83                const rect = bubble.getBoundingClientRect();
84                const bubbleX = rect.left + rect.width / 2;
85                const bubbleY = rect.top + rect.height / 2;
86    
87                const distX = mouseX - bubbleX;
88                const distY = mouseY - bubbleY;
89                const distance = Math.sqrt(distX * distX + distY * distY);
90    
91                if (distance < hoverRadius) {
92                    const movementFactor = (hoverRadius - distance) / hoverRadius;
93                    bubble.dataset.targetX = movementIntensity * movementFactor * (distX / distance);
94                    bubble.dataset.targetY = movementIntensity * movementFactor * (distY / distance);
95                } else {
96                    bubble.dataset.targetX = 0;
97                    bubble.dataset.targetY = 0;
98                }
99            });
100        });
101        setInterval(() => {
102            bubbles.forEach(bubble => {
103                const currentTransform = getComputedStyle(bubble).transform;
104                const matrix = new DOMMatrix(currentTransform === 'none' ? '' : currentTransform);
105                const currentX = matrix.m41;
106                const currentY = matrix.m42;
107    
108                const targetX = parseFloat(bubble.dataset.targetX);
109                const targetY = parseFloat(bubble.dataset.targetY);
110    
111                const easedX = currentX + (targetX - currentX) * easingSpeed;
112                const easedY = currentY + (targetY - currentY) * easingSpeed;
113    
114                bubble.style.transform = `translate(${easedX}px, ${easedY}px)`;
115            });
116        }, 16); // ~60 FPS
117    }
118});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.