Select text inside a link like Opera

Disable link dragging and select text.

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

  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.4
  8. // @grant GM_addStyle
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. function inSelect(caretPos, selection){
  13. var i, len = selection.rangeCount, range;
  14. for (i = 0; i < len; i++) {
  15. range = selection.getRangeAt(i);
  16. if (range.isPointInRange(caretPos.offsetNode, caretPos.offset)) {
  17. return true;
  18. }
  19. }
  20. return false;
  21. }
  22.  
  23. var force = {
  24. target: null,
  25. select: getSelection(),
  26. currentPos: {
  27. x: null,
  28. y: null
  29. },
  30. startPos: {
  31. x: null,
  32. y: null
  33. },
  34. handleEvent: function(e){
  35. if (e.type == "click") {
  36. if (e.ctrlKey || e.shiftKey || e.altKey || e.button) {
  37. return;
  38. }
  39. if (!this.select.isCollapsed) {
  40. e.preventDefault();
  41. e.stopPropagation();
  42. }
  43. } else if (e.type == "mousedown") {
  44. if (e.ctrlKey || e.shiftKey || e.altKey || e.button) {
  45. return;
  46. }
  47. if (!this.select.isCollapsed) {
  48. var caretPos = document.caretPositionFromPoint(e.pageX - window.scrollX, e.pageY - window.scrollY);
  49. if (!inSelect(caretPos, this.select)) {
  50. this.select.collapse(caretPos.offsetNode, caretPos.offset);
  51. }
  52. }
  53. } else if (e.type == "mouseup") {
  54. this.checkMove = false;
  55. if (!this.target) {
  56. return;
  57. }
  58.  
  59. this.uninit();
  60. } else if (e.type == "mousemove") {
  61.  
  62. this.moveX = e.pageX - this.currentPos.x;
  63. this.moveY = e.pageY - this.currentPos.y;
  64. this.currentPos.x = e.pageX;
  65. this.currentPos.y = e.pageY;
  66. if (!this.target) {
  67. return;
  68. }
  69. var caretPos = document.caretPositionFromPoint(this.currentPos.x - window.scrollX, this.currentPos.y - window.scrollY);
  70. if (!this.multiSelect) {
  71. this.select.extend(caretPos.offsetNode, caretPos.offset);
  72. } else {
  73. this.range.setEnd(caretPos.offsetNode, caretPos.offset);
  74. }
  75. } else if (e.type == "dragstart") {
  76. if (e.button || e.altKey || e.shiftKey) {
  77. return;
  78. }
  79. if (e.target.nodeName == "IMG") {
  80. return;
  81. }
  82. var a = e.target;
  83. while (a.nodeName != "A" && a.nodeName != "HTML") {
  84. a = a.parentNode;
  85. }
  86. if (!a.href) {
  87. return;
  88. }
  89. var movementX = e.pageX - this.currentPos.x;
  90. var movementY = e.pageY - this.currentPos.y;
  91. if (!movementX && !movementY) {
  92. movementX = this.moveX;
  93. movementY = this.moveY;
  94. }
  95. if (Math.abs(movementX) < Math.abs(movementY)) {
  96. return;
  97. }
  98. e.preventDefault();
  99. this.target = a;
  100. this.init(e);
  101. }
  102. },
  103. init: function(e){
  104. this.startPos.x = e.pageX;
  105. this.startPos.y = e.pageY;
  106. this.multiSelect = e.ctrlKey;
  107. var caretPos = document.caretPositionFromPoint(this.startPos.x - window.scrollX, this.startPos.y - window.scrollY);
  108. if (!this.multiSelect) {
  109. this.select.collapse(caretPos.offsetNode, caretPos.offset);
  110. } else {
  111. this.range = new Range();
  112. this.range.setEnd(caretPos.offsetNode, caretPos.offset);
  113. this.range.collapse();
  114. this.select.addRange(this.range);
  115. }
  116. this.target.classList.add("force-select");
  117. },
  118. uninit: function(){
  119. this.target.classList.remove("force-select");
  120. this.target = null;
  121. this.range = null;
  122. this.multiSelect = false;
  123. }
  124. };
  125.  
  126. document.addEventListener("mousemove", force, false);
  127. document.addEventListener("mouseup", force, false);
  128. document.addEventListener("mousedown", force, false);
  129. document.addEventListener("click", force, true);
  130. document.addEventListener("dragstart", force, true);
  131. document.addEventListener("dragend", force, true);
  132. document.addEventListener("drag", force, true);
  133. document.addEventListener("DOMContentLoaded", function(){
  134. GM_addStyle(".force-select{ -moz-user-select: text!important; }");
  135. }, false);