惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
Jina AI
Jina AI
博客园_首页
M
MIT News - Artificial intelligence
D
DataBreaches.Net
L
LangChain Blog
宝玉的分享
宝玉的分享
F
Fortinet All Blogs
A
About on SuperTechFans
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Y
Y Combinator Blog
腾讯CDC
Vercel News
Vercel News
雷峰网
雷峰网
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
阮一峰的网络日志
阮一峰的网络日志
博客园 - 【当耐特】

爱吃肉的猫

那就,再相逢 Butterfly的魔改教程:最新评论页 离歌不夜天 前端分享 - 滑动阻尼效果 音乐分享 - doi微醺氛围 Butterfly的魔改教程:动态相册页 近况记事 - 11 微信公众号:Ai大模型让回复更具智能化 近况记事 - 10 PWA:让你的网站变成桌面应用APP Healthy Love Butterfly的魔改教程:关于本站 近况记事 - 9 Butterfly的魔改教程:待办清单 TrollStore - 不掉签助手 近况记事 - 8 Twikoo评论回复邮件模版 过一个很特别的七夕 The Young Boy and the Sea
Butterfly的魔改教程:右键菜单
亦小封 · 2024-04-01 · via 爱吃肉的猫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
.js-pjax
#rightMenu
.rightMenu-group.rightMenu-small
.rightMenu-item#menu-backward
i.MeuiCat.icon-arrow-left-line
.rightMenu-item#menu-forward
i.MeuiCat.icon-arrow-right-line
.rightMenu-item#menu-refresh
i.MeuiCat.icon-restart-line
.rightMenu-item#menu-top
i.MeuiCat.icon-arrow-up-line
.rightMenu-group.rightMenuPost
if theme.readmode
.rightMenu-item#menu-reading
i.MeuiCat.icon-read-fill
span= '阅读模式'
//- .rightMenu-item#menu-commentBarrage
//- i.MeuiCat.icon-chat-fill
//- span= '评论弹窗'
.rightMenu-item#menu-postlink
i.MeuiCat.icon-external-link-fill
span= '分享本文'
.rightMenu-group.rightMenuPlugin
if theme.comments.use
.rightMenu-item#menu-commenttext
i.MeuiCat.icon-chat-new-fill
span= '引用评论'
.rightMenu-item#menu-copytext
i.MeuiCat.icon-copy-fill
span= '复制内容'
.rightMenu-item#menu-pastetext
i.MeuiCat.icon-clipboard-fill
span= '粘贴内容'
//- if theme.search.use
//- .rightMenu-item#menu-search
//- i.MeuiCat.icon-search-line
//- span= '站内搜索'
.rightMenu-item#menu-searchBaidu
i.MeuiCat.icon-baidu-fill
span= '百度搜索'
.rightMenu-item#menu-newwindow
i.MeuiCat.icon-window-fill
span= '新建窗口打开'
.rightMenu-item#menu-copylink
i.MeuiCat.icon-link-m-line
span= '复制链接地址'
.rightMenu-item#menu-copyimg
i.MeuiCat.icon-copy-fill
span= '复制此图片'
.rightMenu-item#menu-downloadimg
i.MeuiCat.icon-download-cloud-fill
span= '下载此图片'
.rightMenu-group.rightMenuOther
//- a.rightMenu-item#menu-randomPost
//- i.MeuiCat.icon-dice-fill
//- span= '随便逛逛'
if theme.darkmode.enable
.rightMenu-item#menu-darkmode
i.MeuiCat.icon-moon-clear-fill
span= '显示模式'
if theme.translate.enable
a.rightMenu-item#menu-translate
i.MeuiCat.icon-panben-line
span= '繁简转换'
.rightMenu-item#menu-asidehide
i.MeuiCat.icon-side-bar-fill
span= '边栏控制'
.rightMenu-group
a.rightMenu-item(href="/privacy/")
i.MeuiCat.icon-shield-user-fill
span= '隐私协议'
a.rightMenu-item(href="/cc/")
i.MeuiCat.icon-creative-commons-fill
span= '版权协议'
#rightMenu-mask
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293






class RightMenu {
constructor() {
this.selectTextNow = ""
this.domhref = ""
this.domImgSrc = ""
this.globalEvent = null
this.downloadimging = false
this.rmWidth = 0
this.rmHeight = 0
this.toLocal = btf.saveToLocal.get('rightside-status')
this.isEnabled = !this.toLocal || this.toLocal !== 'off' ? true : false
this.initialize()
window.rightMenu = undefined
}

initialize() {
window.addEventListener('load', () => {
this.addRightMenuClickEvent()
document.onmouseup = document.ondbclick = this.selceText.bind(this)
btf.addGlobalFn('pjaxComplete', () => { this.addRightMenuClickEvent() }, 'addRightMenuClickEvent')
})

window.oncontextmenu = (e) => this.onContextMenu(e)
}

enable() {
this.isEnabled = true
typeof !window.rightMenu && (window.rightMenu = {
getSelectTextNow: () => rightMenu.getSelectTextNow()
})
}

disable() {
this.isEnabled = false
typeof window.rightMenu && (window.rightMenu = undefined)
}

addRightMenuClickEvent() {
const menuItems = {
"rightMenu-mask": [this.hideRightMenu.bind(this)],
"menu-backward": [() => { window.history.back(); this.hideRightMenu() }],
"menu-forward": [() => { window.history.forward(); this.hideRightMenu() }],
"menu-refresh": [() => { this.hideRightMenu(); window.location.reload() }],
"menu-top": [() => { this.hideRightMenu(); btf.scrollToDest(0, 500) }],
"menu-darkmode": [() => { this.hideRightMenu(); document.querySelector('#darkmode').click() }],
"menu-translate": [() => { this.hideRightMenu(); typeof rightSideFn === 'object' && rightSideFn.translateLink() }],
"menu-reading": [() => { this.hideRightMenu(); document.querySelector('#readmode').click() }],
"menu-postlink": [this.copyPostUrl.bind(this)],
"menu-search": [this.hideRightMenu.bind(this)],
"menu-asidehide": [() => { this.hideRightMenu(); document.querySelector('#hide-aside-btn').click() }],
"menu-copytext": [() => { this.rightmenuCopyText(this.selectTextNow); GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("复制成功,复制和转载请标注本文地址") }],
"menu-commenttext": [() => { commentText(this.selectTextNow); this.hideRightMenu() }],
"menu-searchBaidu": [this.searchBaidu.bind(this)],
"menu-newwindow": [() => { window.open(this.domhref); this.hideRightMenu() }],
"menu-copylink": [() => { this.rightmenuCopyText(this.domhref); GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("已复制链接地址") }],
"menu-pastetext": [this.pasteText.bind(this)],
"menu-copylinkimg": [() => { this.rightmenuCopyText(this.domImgSrc); GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("已复制图片链接") }],
"menu-copyimg": [() => { this.copyImage(this.domImgSrc) }],
"menu-downloadimg": [() => { this.downloadImage(this.domImgSrc, "MeuiCat") }],
"menu-commentBarrage": [() => { this.hideRightMenu(); typeof comment === 'object' && comment.closeBarrage() }],
"menu-randomPost": [() => { this.hideRightMenu(); toRandomPost() }]
}

for (let id in menuItems) {
const element = document.getElementById(id)
if (element) menuItems[id].forEach(fn => { element.addEventListener("click", fn) })
}

document.getElementById("rightMenu-mask").addEventListener("contextmenu", () => {
this.hideRightMenu()
return false
})
}

reloadrmSize() {
const menu = document.getElementById("rightMenu")
this.rmWidth = menu.offsetWidth
this.rmHeight = menu.offsetHeight
}

showRightMenu(more, mouseY = 0, mouseX = 0) {
const rightMenu = document.getElementById("rightMenu")

if (more) {
rightMenu.style.display = "block"
this.reloadrmSize()

mouseX + this.rmWidth + 20 > window.innerWidth && (mouseX -= this.rmWidth + 20)
mouseY + this.rmHeight > window.innerHeight && (mouseY -= mouseY + this.rmHeight - window.innerHeight + 20)
rightMenu.style.top = mouseY + "px"
rightMenu.style.left = mouseX + "px"

document.getElementById("rightMenu-mask").style.display = "flex"
this.stopMaskScroll()
} else {
rightMenu.style.display = "none"
}
}

hideRightMenu() {
this.showRightMenu(false)
document.getElementById("rightMenu-mask").style.display = "none"
}

getSelectTextNow() {
return this.selectTextNow
}

stopMaskScroll() {
const elements = ["rightMenu-mask", "rightMenu"]
elements.forEach(id => {
const element = document.getElementById(id)
if (element) element.addEventListener("mousewheel", this.hideRightMenu.bind(this), false)
})
}

selceText() {
this.selectTextNow = window.getSelection ? window.getSelection().toString() : document.selection ? document.selection.createRange().text : ""
}

copyPostUrl() {
this.copyUrl(window.location.href)
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("复制本页链接地址成功", false, 2000)
this.hideRightMenu()
}

searchBaidu() {
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("即将跳转到百度搜索", false, 2000)
setTimeout(() => { window.open("https://www.baidu.com/s?wd=" + this.selectTextNow) }, 2000)
this.hideRightMenu()
}

pasteText() {
if (navigator.clipboard) navigator.clipboard.readText().then((text) => this.insertAtCaret(this.globalEvent.target, text))
this.hideRightMenu()
}

insertAtCaret(input, text) {
const start = input.selectionStart
const end = input.selectionEnd
if (document.selection) {
input.focus()
document.selection.createRange().text = text
input.focus()
} else if (start || start === 0) {
const scrollTop = input.scrollTop
input.value = input.value.substring(0, start) + text + input.value.substring(end, input.value.length)
input.focus()
input.selectionStart = start + text.length
input.selectionEnd = start + text.length
input.scrollTop = scrollTop
} else {
input.value += text
input.focus()
}
}

rightmenuCopyText(text) {
if (navigator.clipboard) navigator.clipboard.writeText(text)
this.hideRightMenu()
}

imageToBlob(imgSrc, options = {}) {
const { fileName, action = "download", callback } = options
const canvas = document.createElement("canvas")
const context = canvas.getContext("2d")
const img = new Image()

img.crossOrigin = 'anonymous'
img.src = imgSrc

return new Promise((resolve, reject) => {
img.onload = function () {
canvas.width = img.width
canvas.height = img.height
context.drawImage(this, 0, 0)

if (action === 'copy') {
canvas.toBlob((blob) => {
const item = new ClipboardItem({ "image/png": blob })
navigator.clipboard.write([item]).then(() => {
callback && callback("复制成功!图片已添加盲水印,请遵守版权协议")
resolve()
})
}, "image/png", 0.75)
} else if (action === 'download') {
const dataURL = canvas.toDataURL("image/png")
const a = document.createElement("a")
const event = new MouseEvent("click")
a.download = fileName || "image.png"
a.href = dataURL
a.dispatchEvent(event)
callback && callback("图片已添加盲水印,请遵守版权协议")
resolve()
}
}

img.onerror = () => {
callback && callback("图片加载失败,请检查跨域或网络连接")
reject(new Error("Image load error"))
}
})
}

copyImage(imgSrc) {
this.hideRightMenu()
const time = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" ? 0 : 5000
if (this.downloadimging) return GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("有正在进行中的任务,请稍后再试", false, time)
this.downloadimging = true

setTimeout(() => {
this.imageToBlob(imgSrc, {
action: "copy",
callback: (msg) => {
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(msg)
this.downloadimging = false
}
})
}, time)
}

downloadImage(imgSrc, fileName) {
this.hideRightMenu()
if (this.downloadimging) return GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("有正在进行中的下载,请稍后再试")
this.downloadimging = true
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow("正在下载中,请稍后", false, 10000)

setTimeout(() => {
this.imageToBlob(imgSrc, {
action: "download",
fileName: fileName,
callback: (msg) => {
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(msg)
this.downloadimging = false
}
})
}, 10000)
}

onContextMenu(e) {
if (this.isEnabled && document.body.clientWidth > 768) {
const mouseX = e.clientX + 12,
mouseY = e.clientY,
target = e.target,
menus = {
rightMenuPost: document.querySelector(".rightMenuPost"),
rightMenuPlugin: document.querySelector(".rightMenuPlugin"),
rightMenuOther: document.querySelector(".rightMenuOther"),
},
menuItems = {
menuCopyText: { element: document.getElementById("menu-copytext"), condition: () => this.selectTextNow && window.getSelection },
menuCommentText: { element: document.getElementById("menu-commenttext"), condition: () => this.selectTextNow && document.getElementById("post-comment") },
menuSearch: { element: document.getElementById("menu-search"), condition: () => this.selectTextNow },
menuSearchBaidu: { element: document.getElementById("menu-searchBaidu"), condition: () => this.selectTextNow },
menuNewWindow: { element: document.getElementById("menu-newwindow"), condition: () => !!target.href },
menuCopyLink: { element: document.getElementById("menu-copylink"), condition: () => !!target.href },
menuCopyImage: { element: document.getElementById("menu-copyimg"), condition: () => !!target.currentSrc },
menuDownloadImage: { element: document.getElementById("menu-downloadimg"), condition: () => !!target.currentSrc },
menuPasteText: { element: document.getElementById("menu-pastetext"), condition: () => ["input", "textarea"].includes(target.tagName.toLowerCase()) },
}

this.domhref = target.href || ""
this.domImgSrc = target.src || ""

Object.values(menuItems).forEach(({ element, condition }) => { if (element) element.style.display = condition() ? "block" : "none" })

const isTextSelected = Object.values(menuItems).some(({ condition }) => condition())
menus.rightMenuPost.style.display = isTextSelected || !!target.href || !!target.currentSrc ? "none" : document.querySelector("#body-wrap.post") ? "block" : "none"
menus.rightMenuPlugin.style.display = isTextSelected ? "block" : "none"
menus.rightMenuOther.style.display = isTextSelected ? "none" : "block"

const isReadMode = document.querySelector(".read-mode");
["menu-commentBarrage", "menu-postlink", "menu-randomPost", "menu-asidehide"].forEach((id) => {
const element = document.getElementById(id)
if (element) element.style.display = isReadMode ? "none" : "block"
})

this.showRightMenu(e, mouseY, mouseX)
e.preventDefault()
return false
} else {
return true
}
}
}

const rightMenu = new RightMenu()

复制图片下载图片 这两个功能都需要浏览器支持ClipboardItemAPI,并且图片服务器正确设置CORS跨域。
如遇错误提示,大概率就是涉及到跨域问题。自行设置解决。