socket.on('new_link', (data) => {
    const linkElement = createLinkElement(data);
    document.getElementById('board').appendChild(linkElement);
});

function createLinkElement(data) {
    const link = document.createElement('div');
    link.className = 'link';
    link.dataset.id = data.id;
    link.dataset.url = data.url; // Сохраняем URL в дата-атрибуте
    link.style.left = `${data.x}px`;
    link.style.top = `${data.y}px`;
    link.style.width = `${data.width}px`;
    link.style.height = `${data.height}px`;

    // Создаем иконку
    const icon = document.createElement('div');
    icon.className = 'link-icon';
    // Используем Unicode символ или иконку из библиотеки иконок
    icon.innerHTML = '🔗';

    // Создаем элемент текста
    const text = document.createElement('div');
    text.className = 'link-text';
    text.textContent = data.name;

    // Добавляем иконку и текст в элемент ссылки
    link.appendChild(icon);
    link.appendChild(text);

    // Добавляем слушатели событий
    addLinkEventListeners(link, data.id);

    return link;
}

// Добавление слушателей событий для элемента ссылки
function addLinkEventListeners(link, id) {
    // Переменные для отслеживания перетаскивания
    let isDragging = false;
    let startX, startY, startLeft, startTop;

    link.addEventListener('mouseenter', () => {
        link.style.backgroundColor = '#f0f0f0';
    });

    link.addEventListener('mouseleave', () => {
        link.style.backgroundColor = '#fff';
    });

    link.addEventListener('mousedown', (e) => {
        if (e.button !== 0) return; // Только левая кнопка мыши
        e.preventDefault();
        e.stopPropagation();
        isDragging = false;
        startX = e.clientX;
        startY = e.clientY;
        startLeft = parseFloat(link.style.left) || 0;
        startTop = parseFloat(link.style.top) || 0;

        function moveLink(e) {
            const deltaX = (e.clientX - startX) / scale;
            const deltaY = (e.clientY - startY) / scale;

            if (!isDragging && (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5)) {
                isDragging = true;
            }

            if (isDragging) {
                link.style.left = `${startLeft + deltaX}px`;
                link.style.top = `${startTop + deltaY}px`;
                const x = parseFloat(link.style.left) || 0;
                const y = parseFloat(link.style.top) || 0;
                const width = link.offsetWidth;
                const height = link.offsetHeight;
                socket.emit('update_link', {
                    id,
                    name: link.querySelector('.link-text').textContent,
                    url: link.dataset.url,
                    x,
                    y,
                    width,
                    height
                });
            }
        }

        document.addEventListener('mousemove', moveLink);

        document.addEventListener('mouseup', (e) => {
            document.removeEventListener('mousemove', moveLink);
            if (!isDragging) {
                // Если не было перетаскивания, считаем как клик
                window.open(link.dataset.url, '_blank');
            }
        }, { once: true });
    });

    // Обработка двойного клика для контекстного меню
    link.addEventListener('dblclick', (e) => {
        e.preventDefault();
        e.stopPropagation();
        showContextMenu(link, id, e.clientX, e.clientY);
    });

    addResizeListeners(link, id);
}

//function addResizeListeners(element, id) {
//    const resizeHandle = document.createElement('div');
//    resizeHandle.className = 'resize-handle';
//
//    element.appendChild(resizeHandle);
//
//    resizeHandle.addEventListener('mousedown', function(e) {
//        e.preventDefault();
//        e.stopPropagation();
//
//        const startX = e.clientX;
//        const startY = e.clientY;
//        const startWidth = element.offsetWidth;
//        const startHeight = element.offsetHeight;
//
//        function resizeElement(e) {
//            const newWidth = startWidth + (e.clientX - startX) / scale;
//            const newHeight = startHeight + (e.clientY - startY) / scale;
//            element.style.width = `${newWidth}px`;
//            element.style.height = `${newHeight}px`;
//            socket.emit('update_link', {
//                id,
//                name: element.querySelector('.link-text').textContent,
//                url: element.dataset.url,
//                x: element.offsetLeft,
//                y: element.offsetTop,
//                width: newWidth,
//                height: newHeight
//            });
//        }
//
//        document.addEventListener('mousemove', resizeElement);
//
//        document.addEventListener('mouseup', () => {
//            document.removeEventListener('mousemove', resizeElement);
//        }, { once: true });
//    });
//}

// Добавление нового элемента-ссылки на доску
document.getElementById('add-link').addEventListener('click', showLinkForm);

function showLinkForm() {
    const formHtml = `
        <div id="link-form" style="position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); background:white; padding:20px; border-radius:8px; box-shadow:0 0 10px rgba(0,0,0,0.1); z-index: 1000;">
            <label for="link-name" style="display:block; margin-bottom:8px;">Название ссылки:</label>
            <input type="text" id="link-name" placeholder="Введите имя ссылки" style="width: calc(100% - 22px); padding:10px; margin-bottom:12px; border:1px solid #ccc; border-radius:4px;"><br>
            <label for="link-url" style="display:block; margin-bottom:8px;">URL:</label>
            <input type="text" id="link-url" placeholder="Введите URL" style="width: calc(100% - 22px); padding:10px; margin-bottom:12px; border:1px solid #ccc; border-radius:4px;"><br>
            <button id="add-link-submit" style="padding:10px 20px; background-color:#007bff; color:white; border:none; border-radius:4px; cursor:pointer; margin-right:8px;">Добавить ссылку</button>
            <button id="cancel-link" style="padding:10px 20px; background-color:#ccc; color:white; border:none; border-radius:4px; cursor:pointer;">Отмена</button>
        </div>
    `;
    document.body.insertAdjacentHTML('beforeend', formHtml);

    document.getElementById('add-link-submit').addEventListener('click', submitLinkForm);
    document.getElementById('cancel-link').addEventListener('click', closeModal);
}

function submitLinkForm() {
    const name = document.getElementById('link-name').value;
    const url = document.getElementById('link-url').value;

    if (name && url) {
        const rect = boardWrapper.getBoundingClientRect();
        const width = 350;
        const height = 140;
        const centerX = ((rect.width / 2 - translateX) / scale) - width / 2;
        const centerY = ((rect.height / 2 - translateY) / scale) - height / 2;

        socket.emit('create_link', {
            name: name,
            url: url,
            x: centerX,
            y: centerY,
            width,
            height,
            board_id: currentBoardId
        });
        closeModal();
    }
}

function closeModal() {
    const form = document.getElementById('link-form');
    if (form) {
        form.remove();
    }
}

// Функция для обработки существующих ссылок на доске
function handleExistingLinks() {
    document.querySelectorAll('.link').forEach(link => {
        const id = link.dataset.id;
        addLinkEventListeners(link, id);
    });
}

Что за код?