使用纯 HTML、CSS、JS 在文本区域中创建带下划线和弹出窗口的拼写检查功能

问题描述 投票:0回答:1

我想创建一个具有类似于 Grammarly 的拼写检查功能的文本区域。当输入拼写错误的单词时,应在其下划线。单击下划线应会触发类似 this 的弹出窗口。

检查网站结构后,我发现文本区域内的内容保持不变。下划线是使用 div 元素作为叠加层来实现的。

我尝试过这种方法,但确定每个单词的位置很有挑战性。例如,文本区域的行为包括早期换行以避免切断单词。这是我当前的代码:

function updateOverlay() {
        const textarea = document.getElementById('textarea');
        const overlay = document.getElementById('overlay');

        overlay.innerHTML = '';

        const text = textarea.value;

        const wordsAndSpaces = text.split(/(\s+)/) //.filter(e => e.length > 0)//.map(e => e.replace(" ", " "));
        console.log(wordsAndSpaces)

        let offsetLeft = 0;
        let offsetTop = 0;
        let lineHeight = parseFloat(window.getComputedStyle(textarea).lineHeight);

        for (let item of wordsAndSpaces) {
            const span = document.createElement('span');
            if (item.includes(" ")) {
                span.innerHTML = item.replace(" ", " ");
            } else {
                span.textContent = item;
            }
            span.style.display = 'inline-block';

            overlay.appendChild(span);

            const rect = span.getBoundingClientRect();

            const width = rect.width;
            const height = rect.height;
            const left = offsetLeft + rect.left - 10;
            const top = offsetTop + rect.top;

            const underline = document.createElement('div');
            underline.classList.add('underline');
            underline.style.width = width + 'px';
            underline.style.height = '1px';
            underline.style.left = left + 'px';
            underline.style.top = top + height - 10 + 'px'; 
            overlay.appendChild(underline);

            offsetLeft += span.offsetWidth;
            if (offsetLeft >= textarea.clientWidth) {
                offsetLeft = 0;
                offsetTop += lineHeight;
            }

            overlay.removeChild(span);
        }
    }

    // Initial call to update overlay
    updateOverlay();
#textarea-container {
    position: relative;
    width: 400px;
    font-size: medium;
    font-weight: 500;
    font-family: 'Courier New', Courier, monospace;
    /* margin-bottom: 20px; */
}

#textarea, #overlay-container {
    width: 100%;
    height: 200px;
    box-sizing: border-box;
    padding: 0px;
    font-size: 16px;
    resize: none;
    border: 0px solid #ccc;
    margin: 0;
}

#overlay-container {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none; 
    will-change: transform; 
}

#overlay {
    position: relative;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 0px;
    margin: 0px;
}

.underline {
    position: absolute;
    border-bottom: 1px solid blue;
}
<div id="textarea-container">
        <textarea id="textarea" oninput="updateOverlay()">a b</textarea>
        <div id="overlay-container">
            <div id="overlay"></div>
        </div>
    </div>

如何解决这个问题?有没有办法计算文本区域中每个单词的位置?或者我应该考虑其他方法吗?

谢谢你。

javascript html css popup spell-checking
1个回答
0
投票
<!DOCTYPE html>
<html>

<head>
    <title>Grammarly Style Underline</title>
    <style>
        #editor {
            width: 80%;
            margin: 20px auto;
            padding: 10px;
            font-size: 16px;
            line-height: 1.5;
            border: 1px solid #ccc;
        }

        .grammarly-spelling-error {
            border-bottom: 2px dotted red;
        }

        .popup {
            display: none;
            position: absolute;
            background: #fff;
            border: 1px solid #ccc;
            padding: 10px;
        }

        #popupContent {
            margin: 0;
        }

        .textarea {
            width: 300px;
            height: 200px;
            padding: 10px;
            font-size: 16px;
            border: 1px solid #ccc;
        }

        .error {
            background-color: #ffcfcf;
            border-bottom: 2px solid red;
        }
    </style>
</head>

<body>
    <div class="popup" id="popup">
        <p id="popupContent">Popup Content Here</p>
    </div>
    <div id="editor" contenteditable="true">
        The red underline in a text editor or word processor typically indicates a spelling error. Most modern word
        processors or text editing software, like Microsoft Word or Google Docs, have built-in spell checkers. When you
        type a word that isn't recognized by the spell checker's dictionary, it underlines it with a red squiggly line
        to alert you to a potential spelling mistake.
    </div>
    

    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const editor = document.getElementById('editor');
            const misspelledWords = new Set();
            
            
            editor.addEventListener('keyup', function (e) {
               
                const text = editor.innerText; // Get plain text content
                const words = text.split(' '); // Split text into words


                let newContent = []; // Store the corrected content here

                words.forEach(word => {
                    if (!spellCheck(word) && !misspelledWords.has(word)) {
                        newContent.push(addErrorStyle(word));
                        misspelledWords.add(word);
                    } else {
                        newContent.push(removeErrorStyle(word));
                        misspelledWords.delete(word);
                    }
                });


                editor.innerHTML = newContent.join(" ");
            });


            // Event listener for double-click on textarea
            editor.addEventListener('dblclick', function (event) {
                const selection = window.getSelection();
                const selectedWord = selection.toString().trim();

                if (selectedWord !== '') {
                    const range = selection.getRangeAt(0);
                    const rect = range.getBoundingClientRect();

                    const x = rect.x + window.scrollX;
                    const y = rect.y + window.scrollY + rect.height;

                    showPopup(selectedWord, x, y);
                }
            });

            // Function to show popup with selected word
            function showPopup(word, x, y) {
                const popup = document.getElementById('popup');
                const popupContent = document.getElementById('popupContent');
                popupContent.innerText = `Selected Word: ${word}`;

                popup.style.left = `${x}px`;
                popup.style.top = `${y}px`;
                popup.style.display = 'block';

                // Hide popup after 3 seconds
                setTimeout(function () {
                    popup.style.display = 'none';
                }, 3000);
            }

            function spellCheck(word) {
                const dictionary = ["red", "underline", "text", "editor", "word", "processor", "spelling", "error", 'Moest', 'dsasassthe'];
                return dictionary.includes(word.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "")); // Removing punctuation
            }

            // Function to add error style
            function addErrorStyle(word) {
                return `<span class="grammarly-spelling-error">${word}</span>`;
            }

            // Function to remove error style
            function removeErrorStyle(word) {
                const regex = new RegExp(`<span class="grammarly-spelling-error">${word}</span>`, 'gi');
                return word.replace(regex, "");
            }
        });
    </script>
</body>

</html>`

检查此代码是否对您有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.