Select text inside a link like Opera

Disable link dragging and select text.

当前为 2014-10-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Select text inside a link like Opera
  3. // @namespace eight04.blogspot.com
  4. // @description Disable link dragging and select text.
  5. // @include http://*
  6. // @include https://*
  7. // @version 4.0.2
  8. // @grant GM_addStyle
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. var force = {
  13. target: null,
  14. select: getSelection(),
  15. preventClick: false,
  16. currentPos: {
  17. x: null,
  18. y: null
  19. },
  20. startPos: {
  21. x: null,
  22. y: null
  23. },
  24. handleEvent: function(e){
  25. if (e.type == "click") {
  26. if (this.preventClick || !this.select.isCollapsed) {
  27. e.preventDefault();
  28. e.stopPropagation();
  29. this.preventClick = false;
  30. }
  31. } else if (e.type == "mouseup") {
  32. if (!this.target) {
  33. return;
  34. }
  35.  
  36. if (this.select.toString()) {
  37. this.preventClick = true;
  38. }
  39. this.uninit();
  40. } else if (e.type == "mousemove") {
  41. this.currentPos.x = e.pageX;
  42. this.currentPos.y = e.pageY;
  43. if (!this.target) {
  44. return;
  45. }
  46.  
  47. var caretPos = document.caretPositionFromPoint(this.currentPos.x - window.scrollX, this.currentPos.y - window.scrollY);
  48. if (!this.multiSelect) {
  49. this.select.extend(caretPos.offsetNode, caretPos.offset);
  50. } else {
  51. this.range.setEnd(caretPos.offsetNode, caretPos.offset);
  52. }
  53. } else if (e.type == "dragstart") {
  54. if (e.button || e.altKey || e.shiftKey) {
  55. return;
  56. }
  57. if (e.target.nodeName == "IMG") {
  58. return;
  59. }
  60. var a = e.target;
  61. while (a.nodeName != "A" && a.nodeName != "HTML") {
  62. a = a.parentNode;
  63. }
  64. if (!a.href) {
  65. return;
  66. }
  67. if (Math.abs(e.pageX - this.currentPos.x) <= Math.abs(e.pageY - this.currentPos.y)) {
  68. return;
  69. }
  70. e.preventDefault();
  71. this.target = a;
  72. this.init(e);
  73. }
  74. },
  75. init: function(e){
  76. this.startPos.x = e.pageX;
  77. this.startPos.y = e.pageY;
  78. this.multiSelect = e.ctrlKey;
  79. var caretPos = document.caretPositionFromPoint(this.startPos.x - window.scrollX, this.startPos.y - window.scrollY);
  80. if (!this.multiSelect) {
  81. this.select.collapse(caretPos.offsetNode, caretPos.offset);
  82. } else {
  83. this.range = new Range();
  84. this.range.setEnd(caretPos.offsetNode, caretPos.offset);
  85. this.range.collapse();
  86. this.select.addRange(this.range);
  87. }
  88. this.target.classList.add("force-select");
  89. },
  90. uninit: function(){
  91. this.target.classList.remove("force-select");
  92. this.target = null;
  93. this.range = null;
  94. this.multiSelect = false;
  95. }
  96. };
  97.  
  98. document.addEventListener("mousemove", force, false);
  99. document.addEventListener("mouseup", force, false);
  100. document.addEventListener("click", force, true);
  101. document.addEventListener("dragstart", force, true);
  102. document.addEventListener("DOMContentLoaded", function(){
  103. GM_addStyle(".force-select{ -moz-user-select: text!important; }");
  104. }, false);