PageSourceSearch

https://amnesia-f.github.io/js/anzhiyu/right_click_menu.js

js amnesia-f.github.io collected 2026-10-03 08:37:14 UTC 15,370 bytes, 479 lines download raw bytes

1// 初始化函数
2let rm = {};
3
4//禁止图片与超链接拖拽
5let aElements = document.getElementsByTagName("a");
6for (let i = 0; i < aElements.length; i++) {
7  aElements[i].setAttribute("draggable", "false");
8  let imgElements = aElements[i].getElementsByTagName("img");
9  for (let j = 0; j < imgElements.length; j++) {
10    imgElements[j].setAttribute("draggable", "false");
11  }
12}
13
14// 显示菜单
15rm.showRightMenu = function (isTrue, x = 0, y = 0) {
16  console.info(x, y);
17  let rightMenu = document.getElementById("rightMenu");
18  rightMenu.style.top = x + "px";
19  rightMenu.style.left = y + "px";
20  if (isTrue) {
21    rightMenu.style.display = "block";
22    stopMaskScroll();
23  } else {
24    rightMenu.style.display = "none";
25  }
26};
27
28// 隐藏菜单
29rm.hideRightMenu = function () {
30  rm.showRightMenu(false);
31  let rightMenuMask = document.querySelector("#rightmenu-mask");
32  rightMenuMask.style.display = "none";
33};
34
35// 尺寸
36let rmWidth = document.getElementById("rightMenu").offsetWidth;
37let rmHeight = document.getElementById("rightMenu").offsetHeight;
38
39// 重新定义尺寸
40rm.reloadrmSize = function () {
41  rightMenu.style.visibility = "hidden";
42  rightMenu.style.display = "block";
43  // 获取宽度和高度
44  rmWidth = document.getElementById("rightMenu").offsetWidth;
45  rmHeight = document.getElementById("rightMenu").offsetHeight;
46  rightMenu.style.visibility = "visible";
47};
48
49// 获取点击的href
50let domhref = "";
51let domImgSrc = "";
52let globalEvent = null;
53
54var oncontextmenuFunction = function (event) {
55  if (document.body.clientWidth > 768) {
56    let pageX = event.clientX + 10; //加10是为了防止显示时鼠标遮在菜单上
57    let pageY = event.clientY;
58
59    //其他额外菜单
60    const $rightMenuOther = document.querySelector(".rightMenuOther");
61    const $rightMenuPlugin = document.querySelector(".rightMenuPlugin");
62    const $rightMenuCopyText = document.querySelector("#menu-copytext");
63    const $rightMenuPasteText = document.querySelector("#menu-pastetext");
64    const $rightMenuCommentText = document.querySelector("#menu-commenttext");
65    const $rightMenuNewWindow = document.querySelector("#menu-newwindow");
66    const $rightMenuNewWindowImg = document.querySelector("#menu-newwindowimg");
67    const $rightMenuCopyLink = document.querySelector("#menu-copylink");
68    const $rightMenuCopyImg = document.querySelector("#menu-copyimg");
69    const $rightMenuDownloadImg = document.querySelector("#menu-downloadimg");
70    const $rightMenuSearch = document.querySelector("#menu-search");
71    const $rightMenuSearchBaidu = document.querySelector("#menu-searchBaidu");
72    const $rightMenuMusicToggle = document.querySelector("#menu-music-toggle");
73    const $rightMenuMusicBack = document.querySelector("#menu-music-back");
74    const $rightMenuMusicForward = document.querySelector("#menu-music-forward");
75    const $rightMenuMusicPlaylist = document.querySelector("#menu-music-playlist");
76    const $rightMenuMusicCopyMusicName = document.querySelector("#menu-music-copyMusicName");
77
78    let href = event.target.href;
79    let imgsrc = event.target.currentSrc;
80
81    // 判断模式 扩展模式为有事件
82    let pluginMode = false;
83    $rightMenuOther.style.display = "block";
84    globalEvent = event;
85
86    // 检查是否需要复制 是否有选中文本
87    if (selectTextNow && window.getSelection()) {
88      pluginMode = true;
89      $rightMenuCopyText.style.display = "block";
90      $rightMenuCommentText.style.display = "block";
91      $rightMenuSearch.style.display = "block";
92      $rightMenuSearchBaidu.style.display = "block";
93    } else {
94      $rightMenuCopyText.style.display = "none";
95      $rightMenuCommentText.style.display = "none";
96      $rightMenuSearchBaidu.style.display = "none";
97      $rightMenuSearch.style.display = "none";
98    }
99
100    //检查是否右键点击了链接a标签
101    if (href) {
102      pluginMode = true;
103      $rightMenuNewWindow.style.display = "block";
104      $rightMenuCopyLink.style.display = "block";
105      domhref = href;
106    } else {
107      $rightMenuNewWindow.style.display = "none";
108      $rightMenuCopyLink.style.display = "none";
109    }
110
111    //检查是否需要复制图片
112    if (imgsrc) {
113      pluginMode = true;
114      $rightMenuCopyImg.style.display = "block";
115      $rightMenuDownloadImg.style.display = "block";
116      $rightMenuNewWindowImg.style.display = "block";
117      document.getElementById("rightMenu").style.width = "12rem";
118      domImgSrc = imgsrc;
119    } else {
120      $rightMenuCopyImg.style.display = "none";
121      $rightMenuDownloadImg.style.display = "none";
122      $rightMenuNewWindowImg.style.display = "none";
123    }
124
125    // 判断是否为输入框
126    if (event.target.tagName.toLowerCase() === "input" || event.target.tagName.toLowerCase() === "textarea") {
127      pluginMode = true;
128      $rightMenuPasteText.style.display = "block";
129    } else {
130      $rightMenuPasteText.style.display = "none";
131    }
132    const navMusicEl = document.querySelector("#nav-music");
133    //判断是否是音乐
134    if (navMusicEl && navMusicEl.contains(event.target)) {
135      pluginMode = true;
136      $rightMenuMusicToggle.style.display = "block";
137      $rightMenuMusicBack.style.display = "block";
138      $rightMenuMusicForward.style.display = "block";
139      $rightMenuMusicPlaylist.style.display = "block";
140      $rightMenuMusicCopyMusicName.style.display = "block";
141    } else {
142      $rightMenuMusicToggle.style.display = "none";
143      $rightMenuMusicBack.style.display = "none";
144      $rightMenuMusicForward.style.display = "none";
145      $rightMenuMusicPlaylist.style.display = "none";
146      $rightMenuMusicCopyMusicName.style.display = "none";
147    }
148
149    // 如果不是扩展模式则隐藏扩展模块
150    if (pluginMode) {
151      $rightMenuOther.style.display = "none";
152      $rightMenuPlugin.style.display = "block";
153    } else {
154      $rightMenuPlugin.style.display = "none";
155    }
156
157    rm.reloadrmSize();
158
159    // 鼠标默认显示在鼠标右下方,当鼠标靠右或靠下时,将菜单显示在鼠标左方\上方
160    if (pageX + rmWidth > window.innerWidth) {
161      pageX -= rmWidth + 10;
162    }
163    if (pageY + rmHeight > window.innerHeight) {
164      pageY -= pageY + rmHeight - window.innerHeight;
165    }
166
167    rm.showRightMenu(true, pageY, pageX);
168    document.getElementById("rightmenu-mask").style.display = "flex";
169    return false;
170  }
171};
172
173// 监听右键初始化
174window.oncontextmenu = oncontextmenuFunction;
175
176// 下载图片状态
177rm.downloadimging = false;
178
179// 复制图片到剪贴板
180rm.writeClipImg = function (imgsrc) {
181  console.log("按下复制");
182  rm.hideRightMenu();
183  anzhiyu.snackbarShow("正在下载中,请稍后", false, 10000);
184  if (rm.downloadimging == false) {
185    rm.downloadimging = true;
186    setTimeout(function () {
187      copyImage(imgsrc);
188      anzhiyu.snackbarShow("复制成功!图片已添加盲水印,请遵守版权协议");
189      rm.downloadimging = false;
190    }, "10000");
191  }
192};
193
194function imageToBlob(imageURL) {
195  const img = new Image();
196  const c = document.createElement("canvas");
197  const ctx = c.getContext("2d");
198  img.crossOrigin = "";
199  img.src = imageURL;
200  return new Promise(resolve => {
201    img.onload = function () {
202      c.width = this.naturalWidth;
203      c.height = this.naturalHeight;
204      ctx.drawImage(this, 0, 0);
205      c.toBlob(
206        blob => {
207          // here the image is a blob
208          resolve(blob);
209        },
210        "image/png",
211        0.75
212      );
213    };
214  });
215}
216
217async function copyImage(imageURL) {
218  const blob = await imageToBlob(imageURL);
219  const item = new ClipboardItem({ "image/png": blob });
220  navigator.clipboard.write([item]);
221}
222
223rm.copyUrl = function (id) {
224  const input = document.createElement("input"); // Create a new <input> element
225  input.id = "copyVal"; // Set the id of the new element to "copyVal"
226  document.body.appendChild(input); // Append the new element to the end of the <body> element
227
228  const text = id;
229  input.value = text;
230  input.select();
231  input.setSelectionRange(0, input.value.length);
232  document.execCommand("copy");
233
234  input.remove(); // Remove the <input> element from the DOM
235};
236
237function stopMaskScroll() {
238  if (document.getElementById("rightmenu-mask")) {
239    let xscroll = document.getElementById("rightmenu-mask");
240    xscroll.addEventListener(
241      "mousewheel",
242      function (e) {
243        //阻止浏览器默认方法
244        rm.hideRightMenu();
245        // e.preventDefault();
246      },
247      { passive: true }
248    );
249  }
250  if (document.getElementById("rightMenu")) {
251    let xscroll = document.getElementById("rightMenu");
252    xscroll.addEventListener(
253      "mousewheel",
254      function (e) {
255        //阻止浏览器默认方法
256        rm.hideRightMenu();
257        // e.preventDefault();
258      },
259      { passive: true }
260    );
261  }
262}
263
264rm.rightmenuCopyText = function (txt) {
265  if (navigator.clipboard) {
266    navigator.clipboard.writeText(txt);
267  }
268  rm.hideRightMenu();
269};
270
271rm.copyPageUrl = function (url) {
272  if (!url) {
273    url = window.location.href;
274  }
275  rm.copyUrl(url);
276  anzhiyu.snackbarShow("复制链接地址成功", false, 2000);
277  rm.hideRightMenu();
278};
279
280// 复制当前选中文本
281var selectTextNow = "";
282document.onmouseup = document.ondblclick = selceText;
283
284function selceText() {
285  var txt;
286  if (document.selection) {
287    txt = document.selection.createRange().text;
288  } else {
289    txt = window.getSelection().toString();
290  }
291  selectTextNow = txt !== "" ? txt : "";
292}
293
294// 读取剪切板
295rm.readClipboard = function () {
296  if (navigator.clipboard) {
297    navigator.clipboard.readText().then(clipText => rm.insertAtCaret(globalEvent.target, clipText));
298  }
299};
300
301// 粘贴文本到焦点
302rm.insertAtCaret = function (elemt, value) {
303  const startPos = elemt.selectionStart,
304    endPos = elemt.selectionEnd;
305  if (document.selection) {
306    elemt.focus();
307    var sel = document.selection.createRange();
308    sel.text = value;
309    elemt.focus();
310  } else {
311    if (startPos || startPos == "0") {
312      var scrollTop = elemt.scrollTop;
313      elemt.value = elemt.value.substring(0, startPos) + value + elemt.value.substring(endPos, elemt.value.length);
314      elemt.focus();
315      elemt.selectionStart = startPos + value.length;
316      elemt.selectionEnd = startPos + value.length;
317      elemt.scrollTop = scrollTop;
318    } else {
319      elemt.value += value;
320      elemt.focus();
321    }
322  }
323};
324
325//粘贴文本
326rm.pasteText = function () {
327  const result = rm.readClipboard() || "";
328  rm.hideRightMenu();
329};
330
331//引用到评论
332rm.rightMenuCommentText = function (txt) {
333  rm.hideRightMenu();
334  const postCommentDom = document.getElementById("post-comment");
335  var domTop = postCommentDom.offsetTop;
336  window.scrollTo(0, domTop - 80);
337  if (txt == "undefined" || txt == "null") txt = "好棒!";
338  function setText() {
339    setTimeout(() => {
340      var input = document.getElementsByClassName("el-textarea__inner")[0];
341      if (!input) setText();
342      let evt = document.createEvent("HTMLEvents");
343      evt.initEvent("input", true, true);
344      let inputValue = replaceAll(txt, "\n", "\n> ");
345      input.value = "> " + inputValue + "\n\n";
346      input.dispatchEvent(evt);
347      input.focus();
348      input.setSelectionRange(-1, -1);
349      if (document.getElementById("comment-tips")) {
350        document.getElementById("comment-tips").classList.add("show");
351      }
352    }, 100);
353  }
354  setText();
355};
356
357//替换所有内容
358function replaceAll(string, search, replace) {
359  return string.split(search).join(replace);
360}
361
362// 百度搜索
363rm.searchBaidu = function () {
364  anzhiyu.snackbarShow("即将跳转到百度搜索", false, 2000);
365  setTimeout(function () {
366    window.open("https://www.baidu.com/s?wd=" + selectTextNow);
367  }, "2000");
368  rm.hideRightMenu();
369};
370
371//分享链接
372rm.copyLink = function () {
373  rm.rightmenuCopyText(domhref);
374  anzhiyu.snackbarShow("已复制链接地址");
375};
376
377function addRightMenuClickEvent() {
378  // 添加点击事件
379  document.getElementById("menu-backward").addEventListener("click", function () {
380    window.history.back();
381    rm.hideRightMenu();
382  });
383
384  document.getElementById("menu-forward").addEventListener("click", function () {
385    window.history.forward();
386    rm.hideRightMenu();
387  });
388
389  document.getElementById("menu-refresh").addEventListener("click", function () {
390    window.location.reload();
391  });
392
393  document.getElementById("menu-top").addEventListener("click", function () {
394    anzhiyu.scrollToDest(0, 500);
395    rm.hideRightMenu();
396  });
397
398  document.getElementById("menu-translate").addEventListener("click", function () {
399    window.translateFn.translatePage();
400    rm.hideRightMenu();
401  });
402
403  const menuLinks = document.querySelectorAll(".menu-link");
404  menuLinks.forEach(function (link) {
405    link.addEventListener("click", rm.hideRightMenu);
406  });
407
408  document.getElementById("menu-home") &&
409    document.getElementById("menu-home").addEventListener("click", function () {
410      window.location.href = window.location.origin;
411    });
412
413  document.getElementById("menu-randomPost").addEventListener("click", function () {
414    toRandomPost();
415  });
416
417  document.getElementById("menu-commentBarrage").addEventListener("click", anzhiyu.switchCommentBarrage);
418
419  document.getElementById("rightmenu-mask").addEventListener("click", rm.hideRightMenu);
420
421  document.getElementById("rightmenu-mask").addEventListener("contextmenu", function (event) {
422    rm.hideRightMenu();
423    event.preventDefault(); // Prevent the default context menu from appearing
424  });
425
426  document.getElementById("menu-copy").addEventListener("click", () => {
427    rm.copyPageUrl();
428  });
429
430  document.getElementById("menu-pastetext").addEventListener("click", rm.pasteText);
431
432  document.getElementById("menu-copytext").addEventListener("click", function () {
433    rm.rightmenuCopyText(selectTextNow);
434    const copyright = GLOBAL_CONFIG.copyright;
435    if (copyright.copy) {
436      anzhiyu.snackbarShow(copyright.languages.copySuccess);
437    }
438  });
439
440  document.getElementById("menu-commenttext").addEventListener("click", function () {
441    rm.rightMenuCommentText(selectTextNow);
442  });
443
444  document.getElementById("menu-newwindow").addEventListener("click", function () {
445    window.open(domhref, "_blank");
446    rm.hideRightMenu();
447  });
448
449  document.getElementById("menu-copylink").addEventListener("click", rm.copyLink);
450
451  document.getElementById("menu-downloadimg").addEventListener("click", function () {
452    anzhiyu.downloadImage(domImgSrc, "anzhiyu");
453  });
454
455  document.getElementById("menu-newwindowimg").addEventListener("click", function () {
456    window.open(domImgSrc, "_blank");
457    rm.hideRightMenu();
458  });
459
460  document.getElementById("menu-copyimg").addEventListener("click", function () {
461    rm.writeClipImg(domImgSrc);
462  });
463
464  document.getElementById("menu-searchBaidu").addEventListener("click", rm.searchBaidu);
465
466  //音乐
467  document.getElementById("menu-music-toggle").addEventListener("click", anzhiyu.musicToggle);
468
469  document.getElementById("menu-music-back").addEventListener("click", anzhiyu.musicSkipBack);
470
471  document.getElementById("menu-music-forward").addEventListener("click", anzhiyu.musicSkipForward);
472
473  document.getElementById("menu-music-copyMusicName").addEventListener("click", function () {
474    rm.rightmenuCopyText(anzhiyu.musicGetName());
475    anzhiyu.snackbarShow("复制歌曲名称成功", false, 3000);
476  });
477}
478
479addRightMenuClickEvent();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.