zoukankan      html  css  js  c++  java
  • JavaScript实战笔记(四) 选中文本高亮

    以下代码可以实现用户选中文本之后点击高亮按钮,高亮选中文本,支持多种颜色高亮

    由于博主最近事情比较多,所以只是稍微写了个例子,有不足之处,请多多见谅

    <!DOCTYPE html>
    <html>
    <head>
        <title>选中文本高亮</title>
        <style>
            button {
                margin: 10px;
                padding: 5px;
            }
            span {
                word-wrap: break-word;
                word-break: break-all;
            }
        </style>
        <script>
            function createRandomNumber(start, end) {
                return (end >= start) ? Math.floor(Math.random() * (end - start) + start) : null
            }
    
            function createRandomString(length, source) {
                var length = length || 52
                var source = source || 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
                var result = []
                for (let i = 1; i <= length; i += 1) result.push(source.charAt(createRandomNumber(0, source.length)))
                return result.join('')
            }
    
            function initDom() {
                let bId = ['redHighlight', 'greenHighlight', 'blueHighlight']
                let bFragment = document.createDocumentFragment()
                for (let i = 0, ii = bId.length; i < ii; i += 1) {
                    let button = document.createElement('button')
                    let string = bId[i]
                    button.id = string
                    button.innerHTML = string.substring(string.length - 9)
                    button.style.color = string.substring(0, string.length - 9)
                    bFragment.appendChild(button)
                }
                document.body.appendChild(bFragment)
    
                let div = document.createElement('div')
                div.id = 'article'
                document.body.appendChild(div)
    
                let sCount = 10
                let sFragment = document.createDocumentFragment()
                for (let i = 0, ii = sCount; i < ii; i += 1) {
                    let span = document.createElement('span')
                    span.id = 'highlightable-' + i.toString()
                    span.innerHTML = createRandomString()
                    sFragment.appendChild(span)
                }
                document.getElementById('article').appendChild(sFragment)
    
                return bId
            }
    
            function initData() {
                let result = {}
                let collection = document.getElementById('article').getElementsByTagName('span')
                Array.prototype.forEach.call(collection, (item) => {
                    result[item.id] = {}
                    result[item.id]['htmlString'] = item.innerHTML
                    result[item.id]['infoArray'] = []
                })
                return result
            }
    
            function updateInfo(data, id, newInfo) {
                let infoArray = data[id]['infoArray']
                let result = []
                let [newStartIdx, newEndIdx, newColor] = newInfo
                for (let orgInfo of infoArray) {
                    let [orgStartIdx, orgEndIdx, orgColor] = orgInfo
                    if (orgStartIdx >= newStartIdx && orgStartIdx <= newEndIdx) {
                        if (orgEndIdx >= newStartIdx && orgEndIdx <= newEndIdx) continue
                        else result.push([newEndIdx, orgEndIdx, orgColor])
                    }
                    else if (orgEndIdx >= newStartIdx && orgEndIdx <= newEndIdx) {
                        if (orgStartIdx >= newStartIdx && orgStartIdx <= newEndIdx) continue
                        else result.push([orgStartIdx, newStartIdx, orgColor])
                    }
                    else if (orgStartIdx <= newStartIdx && orgEndIdx >= newEndIdx) {
                        result.push([orgStartIdx, newStartIdx, orgColor])
                        result.push([newEndIdx, orgEndIdx, orgColor])
                    }
                    else {
                        result.push([orgStartIdx, orgEndIdx, orgColor])
                    }
                }
                result.push(newInfo)
                result.sort((a, b) => { return a[0] <= b[0] ? a[0] == b[0] ? 0 : 1 : -1 })
                data[id]['infoArray'] = result
            }
    
            function highlightHelper(data, id) {
                let htmlString = data[id]['htmlString']
                let infoArray = data[id]['infoArray']
                let result = htmlString
                for (let info of infoArray) {
                    let [startIdx, endIdx, color] = info
                    let startHtml = result.substring(0, startIdx)
                    let middleHtml = result.substring(startIdx, endIdx)
                    let endHtml = result.substring(endIdx)
                    result = startHtml + `<span style="color:${color}">` + middleHtml + '</span>' + endHtml
                }
                return result
            }
    
            function highlightSelection(data, color) {
                let selection = document.getSelection()
                if (selection.type !== 'Range') return
                let range = selection.getRangeAt(0)
                if (range.length === 0) return
                let startContainer = range.startContainer
                let endContainer = range.endContainer
                let startOffset = range.startOffset
                let endOffset = range.endOffset
                let startNode = startContainer.parentElement
                while (startNode.id.search(/highlightable-[0-9]+/) === -1) startNode = startNode.parentElement
                let endNode = endContainer.parentElement
                while (endNode.id.search(/highlightable-[0-9]+/) === -1) endNode = endNode.parentElement
                let currNode = startNode
                while (true) {
                    let startIdx = 0
                    let endIdx = 0
                    let isStartNode = (currNode === startNode)
                    let isEndNode = (currNode === endNode)
                    if (isStartNode && isEndNode) {
                        let isFinishStart = false
                        let isFinishEnd = false
                        for (let child of currNode.childNodes) {
                            let isTextNode = (child.tagName == null)
                            let isStartContainer = (child === startContainer || child === startContainer.parentElement)
                            let isEndContainer = (child === endContainer || child === endContainer.parentElement)
                            let childLength = isTextNode ? child.length : child.innerHTML.length
                            if (!isFinishStart && !isStartContainer) {
                                startIdx += childLength
                                endIdx += childLength
                            } else if (!isFinishStart && isStartContainer && !isEndContainer) {
                                startIdx += startOffset
                                endIdx += childLength
                                isFinishStart = true
                            } else if (!isFinishStart && isStartContainer && isEndContainer) {
                                startIdx += startOffset
                                endIdx += endOffset
                                isFinishStart = true
                                isFinishEnd = true
                            } else if (isFinishStart && !isFinishEnd && !isEndContainer) {
                                endIdx += childLength
                            } else if (isFinishStart && !isFinishEnd && isEndContainer) {
                                endIdx += endOffset
                                isFinishEnd = true
                            } else if (isFinishEnd) {
    
                            }
                        }
                    } else {
                        if (isStartNode) {
                            let isFinishStart = false
                            for (let child of currNode.childNodes) {
                                let isTextNode = (child.tagName == null)
                                let childLength = isTextNode ? child.length : child.innerHTML.length
                                let isStartContainer = (child === startContainer || child === startContainer.parentElement)
                                endIdx += childLength
                                if (!isFinishStart && !isStartContainer) {
                                    startIdx += childLength
                                } else if (!isFinishStart && isStartContainer) {
                                    startIdx += startOffset
                                    isFinishStart = true
                                } else if (isFinishStart) {
                                    
                                }
                            }
                        } else if (isEndNode) {
                            let isFinishEnd = false
                            for (let child of currNode.childNodes) {
                                let isTextNode = (child.tagName == null)
                                let childLength = isTextNode ? child.length : child.innerHTML.length
                                let isEndContainer = (child === endContainer || child === endContainer.parentElement)
                                if (!isFinishEnd && !isEndContainer) {
                                    endIdx += childLength
                                } else if (!isFinishEnd && isEndContainer) {
                                    endIdx += endOffset
                                    isFinishEnd = true
                                } else if (isFinishEnd) {
                                    
                                }
                            }
                        } else {
                            for (let child of currNode.childNodes) {
                                let isTextNode = (child.tagName == null)
                                let childLength = isTextNode ? child.length : child.innerHTML.length
                                endIdx += childLength
                            }
                        }
                    }
                    updateInfo(data, currNode.id, [startIdx, endIdx, color])
                    currNode.innerHTML = highlightHelper(data, currNode.id)
                    if (currNode === endNode) break
                    currNode = currNode.nextElementSibling
                }
                document.getSelection().empty()
            }
    
            window.onload = function() {
                let buttonId = initDom()
                let globalData = initData()
                for (let button of buttonId) {
                    document.getElementById(button).addEventListener('click', () => {
                        highlightSelection(globalData, button.substring(0, button.length - 9))
                    })
                }
            }
        </script>
    </head>
    <body>
    
    </body>
    </html>
    

    实现的效果如下:

    【 阅读更多 JavaScript 系列文章,请看 JavaScript学习笔记

  • 相关阅读:
    使用dbms_metadata.get_ddl遇到ORA-31603
    oracle得到建表语句
    Linux性能优化和监控系列(一)——top工具
    Oracle在Linux下的性能优化
    地址跳转问题
    无法对 数据库'UDS' 执行 删除,因为它正用于复制
    [.net 多线程]SpinWait
    [.net 多线程 ]ReaderWriterLock
    [.net 多线程]Barrier
    [.net 多线程]CountdownEvent
  • 原文地址:https://www.cnblogs.com/wsmrzx/p/12439530.html
Copyright © 2011-2022 走看看