您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
选中高亮!
- // ==UserScript==
- // @name web_highlight
- // @namespace http://tampermonkey.net/
- // @version 0.1.4
- // @description 选中高亮!
- // @author You
- // @license MIT
- // @match *://*/*
- // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
- // @grant GM_addStyle
- // ==/UserScript==
- (function() {
- 'use strict';
- // Your code here...
- // 在网页中注入自定义的 CSS 样式
- GM_addStyle(`
- .menu_dialog {
- width: 30px;
- height: 30px;
- border-radius: 5px;
- position: absolute;
- background-color: red;
- cursor: pointer;
- color: white;
- }
- .pale_card {
- position: absolute;
- background-color: white;
- border: 1px solid gray;
- padding: 5px;
- }
- .pale_highlight_color {
- width: 10px;
- height: 10px;
- border-radius: 2px;
- cursor: pointer;
- margin-left: 3px;
- transition: width 0.3s, height 0.3s;
- }
- .pale_highlight_color:first-child {
- margin-left: 0;
- }
- .pale_highlight_color:hover {
- border: 2px solid;
- }
- `);
- const sites = {}
- const href = window.location.href;
- sites[href] = []
- let target = null // 选中的关键词的目标元素
- let currentKeyWord = '' // 当前选中的关键词
- let menuDom = null // 菜单图标元素
- const disabledTagNameList = ['INPUT', 'TEXTAREA', 'IMG'] // 禁用的标签
- const isBreakRow = true // 高亮单词是否与所在行断开,如果为否,选中单词会高亮整个元素(行)
- function findClosestChildWithKeyword(startingElement, keyword) {
- // 找到包含keyword的元素
- const queue = [startingElement];
- while (queue.length > 0) {
- const currentElement = queue.shift();
- if (currentElement.textContent.includes(keyword)) {
- return currentElement;
- }
- if (currentElement.children) {
- queue.push(...currentElement.children);
- }
- }
- return null; // 如果找不到含有关键词的子元素,则返回 null
- }
- function keyHighlight(key, color, keyTarget) {
- if (keyTarget) {
- // 根据元素查关键词
- if (!sites[href].includes(key)) {
- sites[href].push(key)
- }
- } else {
- // 根据关键词找到元素
- keyTarget = findClosestChildWithKeyword(key)
- }
- // 设置背景
- if (isBreakRow) {
- // 将自定义高亮元素替换调关键词
- const keyBackgroundSpan = document.createElement('span')
- keyBackgroundSpan.style.background = color
- keyBackgroundSpan.innerText = key
- const htmlString = keyBackgroundSpan.outerHTML
- console.log(htmlString, '====htmlString=======>')
- keyTarget.innerHTML = keyTarget.innerHTML.replace(key, htmlString)
- } else {
- key = keyTarget.innerText
- const keyBackgroundSpan = document.createElement('span')
- keyBackgroundSpan.style.background = color
- keyBackgroundSpan.innerText = key
- keyTarget.innerHTML = ''
- keyTarget.appendChild(keyBackgroundSpan)
- }
- }
- class ColorPale {
- // 参数
- colorList = ['#faa8a8', 'blue', 'green', 'yellow', 'orange']
- cardWidth = 20
- iconWidth = 30
- palePadding = 5
- colorMargin = 3
- // 以下参数仅供程序使用
- paleWidth = 0
- paleHeight = 0
- paleLeft = 0
- paleTop = 0
- pale = null
- isOnCard = false // 鼠标是否进入色卡
- initColorPale(menuDom) {
- this.paleWidth = this.colorList.length * this.cardWidth + this.palePadding * 2 + (this.colorList.length - 1) * this.colorMargin
- this.paleHeight = this.cardWidth + this.palePadding * 2
- this.paleLeft = parseInt(menuDom.style.left) - ((this.paleWidth - this.iconWidth) / 2)
- this.paleTop = parseInt(menuDom.style.top) + this.iconWidth
- this.pale = document.createElement('div')
- this.pale.className = 'pale_card'
- this.pale.style.width = this.paleWidth + 'px'
- this.pale.style.height = this.paleHeight + 'px'
- this.pale.style.left = this.paleLeft + 'px'
- this.pale.style.top = this.paleTop + 'px'
- this.pale.style.zIndex = '9999';
- this.pale.style.display = 'none' // 隐藏
- this.colorList.forEach(color => {
- const colorCard = document.createElement('div')
- colorCard.className = 'pale_highlight_color'
- colorCard.style.width = this.cardWidth + 'px'
- colorCard.style.height = this.cardWidth + 'px'
- colorCard.style.backgroundColor = color
- colorCard.style.zIndex = '9998';
- colorCard.addEventListener('click', (e) => {
- keyHighlight(currentKeyWord, color, target)
- e.stopPropagation();
- })
- colorCard.addEventListener('mouseup', (e) => {
- // 阻止在设置色卡时触发清除函数
- e.stopPropagation();
- })
- this.pale.appendChild(colorCard)
- })
- this.pale.addEventListener('mouseenter', (e) => {
- this.isOnCard = true
- })
- this.pale.addEventListener('mouseleave', (e) => {
- this.isOnCard = false
- this.closePale()
- })
- document.body.appendChild(this.pale)
- return Promise.resolve(this)
- }
- showPale(menuDom) {
- if (this.pale) {
- if (menuDom) {
- this.paleLeft = parseInt(menuDom.style.left) - ((this.paleWidth - this.iconWidth) / 2)
- this.paleTop = parseInt(menuDom.style.top) + this.iconWidth
- }
- this.pale.style.left = this.paleLeft + 'px'
- this.pale.style.top = this.paleTop + 'px'
- this.pale.style.display = 'flex'
- return Promise.resolve(this)
- } else if (menuDom) {
- return this.initColorPale(menuDom).then(Pale => {
- Pale.pale.style.display = 'flex'
- return Pale
- })
- }
- }
- closePale() {
- // 鼠标在色卡上不能关闭
- if (!this.isOnCard) {
- this.pale.style.display = 'none'
- }
- }
- }
- // 初始化
- const colorPale = new ColorPale
- // 滚动后重新加载高亮关键词
- window.addEventListener('scroll', highlight);
- let selectionTimeout;
- document.addEventListener('selectionchange', function() {
- // 移除之前添加的mouseup监听器
- document.removeEventListener('mouseup', handleMouseUp);
- // 添加新的mouseup监听器
- document.addEventListener('mouseup', handleMouseUp);
- });
- /**document.addEventListener('click', () => {
- // 监听选中消失的事件
- const selection = window.getSelection();
- if (selection.toString().length > 0) {
- // 没有选中
- clearData()
- }
- })*/
- function handleMouseUp(event) {
- // 删除之前的数据
- clearData()
- const selection = window.getSelection();
- currentKeyWord = selection.toString()
- if (currentKeyWord.length > 0 && !disabledTagNameList.includes(event.target.tagName)) {
- // 用户选中了文本,可以在这里处理相应的逻辑
- target = event.target;
- console.dir(target, 'target');
- // 不处理特殊标签 input/textarea
- menuDom = document.createElement('div');
- menuDom.className = 'menu_dialog';
- menuDom.style.top = (event.clientY + 10) + 'px'
- menuDom.style.left = (event.clientX + 10) + 'px'
- menuDom.style.zIndex = '9999';
- menuDom.innerHTML = '色卡';
- menuDom.addEventListener('mouseup', (e) => {
- // 阻止在设置色卡时触发清除函数
- e.stopPropagation();
- })
- // colorPale.showPale(menuDom).then(pale => {
- menuDom.addEventListener('mouseenter', (e) => {
- console.log(e, '数据')
- colorPale.showPale(menuDom).then(pale => {
- // 鼠标移出时删除菜单
- const handleMouseLeave = () => {
- setTimeout(() => {
- pale.closePale();
- menuDom.removeEventListener('mouseleave', handleMouseLeave);
- }, 300)
- };
- menuDom.addEventListener('mouseleave', handleMouseLeave)
- })
- })
- document.body.appendChild(menuDom);
- // })
- }
- }
- function clearData() {
- target = null
- if (menuDom) {
- document.body.removeChild(menuDom)
- menuDom = null
- }
- }
- function highlight() {
- sites[href].forEach(keyword => {
- const { word, color } = keyword
- })
- }
- function getSelectionElement() {
- const selection = window.getSelection();
- if (selection.rangeCount > 0) {
- const range = selection.getRangeAt(0);
- const startContainer = range.startContainer;
- const endContainer = range.endContainer;
- // 找到最接近的包含选中文本的父元素
- const closestParentElement = (startContainer.nodeType === 3) ? startContainer.parentNode : startContainer;
- // closestParentElement 就是包含选中文本的最接近的父元素
- return closestParentElement;
- }
- }
- })();