Select text inside a link like Opera

Disable link dragging and select text.

当前为 2014-11-17 提交的版本,查看 最新版本

  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.8
  8. // @grant GM_addStyle
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. "use strict";
  13.  
  14. function caretPositionFromPoint(x, y) {
  15. if (document.caretPositionFromPoint) {
  16. return document.caretPositionFromPoint(x, y);
  17. }
  18. var r = document.caretRangeFromPoint(x, y);
  19. return {
  20. offsetNode: r.startContainer,
  21. offset: r.startOffset
  22. };
  23. }
  24.  
  25. function inSelect(caretPos, selection){
  26. var i, len = selection.rangeCount, range;
  27. for (i = 0; i < len; i++) {
  28. range = selection.getRangeAt(i);
  29. if (range.isPointInRange(caretPos.offsetNode, caretPos.offset)) {
  30. return true;
  31. }
  32. }
  33. return false;
  34. }
  35.  
  36. var force = {
  37. target: null,
  38. select: getSelection(),
  39. currentPos: {
  40. x: null,
  41. y: null
  42. },
  43. startPos: {
  44. x: null,
  45. y: null
  46. },
  47. handleEvent: function(e){
  48. var caretPos, a, movementX, movementY, select;
  49.  
  50. if (e.type == "click") {
  51.  
  52. if (e.ctrlKey || e.shiftKey || e.altKey || e.button) {
  53. return;
  54. }
  55.  
  56. if (this.uninitFlag) {
  57. e.preventDefault();
  58. e.stopImmediatePropagation();
  59. }
  60.  
  61. } else if (e.type == "mousedown") {
  62.  
  63. if (e.ctrlKey || e.shiftKey || e.altKey || e.button) {
  64. return;
  65. }
  66.  
  67. this.uninitFlag = false;
  68.  
  69. if (e.target.nodeName == "IMG") {
  70. this.imgFlag = true;
  71. }
  72.  
  73. select = window.getSelection();
  74. if (!select.isCollapsed) {
  75. caretPos = caretPositionFromPoint(e.pageX - window.scrollX, e.pageY - window.scrollY);
  76. if (!inSelect(caretPos, select)) {
  77. select.collapse(caretPos.offsetNode, caretPos.offset);
  78. }
  79. }
  80.  
  81. } else if (e.type == "mouseup") {
  82.  
  83. this.checkMove = false;
  84. this.imgFlag = false;
  85.  
  86. if (!this.target) {
  87. return;
  88. }
  89.  
  90. this.uninitFlag = true;
  91. this.uninit();
  92.  
  93. } else if (e.type == "mousemove") {
  94.  
  95. this.moveX = e.pageX - this.currentPos.x;
  96. this.moveY = e.pageY - this.currentPos.y;
  97. this.currentPos.x = e.pageX;
  98. this.currentPos.y = e.pageY;
  99.  
  100. if (!this.target) {
  101. return;
  102. }
  103.  
  104. select = window.getSelection();
  105. caretPos = caretPositionFromPoint(this.currentPos.x - window.scrollX, this.currentPos.y - window.scrollY);
  106. if (!this.multiSelect) {
  107. select.extend(caretPos.offsetNode, caretPos.offset);
  108. } else {
  109. this.range.setEnd(caretPos.offsetNode, caretPos.offset);
  110. }
  111.  
  112. } else if (e.type == "dragstart") {
  113.  
  114. if (e.button || e.altKey || e.shiftKey) {
  115. return;
  116. }
  117.  
  118. if (this.imgFlag) {
  119. this.imgFlag = false;
  120. return;
  121. }
  122.  
  123. a = e.target;
  124. while (a.nodeName != "A" && a.nodeName != "HTML") {
  125. a = a.parentNode;
  126. }
  127.  
  128. if (!a.href) {
  129. return;
  130. }
  131.  
  132. movementX = e.pageX - this.currentPos.x;
  133. movementY = e.pageY - this.currentPos.y;
  134.  
  135. if (!movementX && !movementY) {
  136. movementX = this.moveX;
  137. movementY = this.moveY;
  138. }
  139. if (Math.abs(movementX) < Math.abs(movementY)) {
  140. return;
  141. }
  142.  
  143. e.preventDefault();
  144. this.target = a;
  145. this.init(e);
  146. }
  147. },
  148. init: function(e){
  149. var select = window.getSelection();
  150.  
  151. this.startPos.x = e.pageX;
  152. this.startPos.y = e.pageY;
  153.  
  154. this.multiSelect = e.ctrlKey;
  155.  
  156. var caretPos = caretPositionFromPoint(this.startPos.x - window.scrollX, this.startPos.y - window.scrollY);
  157. if (!this.multiSelect) {
  158. select.collapse(caretPos.offsetNode, caretPos.offset);
  159. } else {
  160. this.range = new Range();
  161. this.range.setEnd(caretPos.offsetNode, caretPos.offset);
  162. this.range.collapse();
  163. select.addRange(this.range);
  164. }
  165.  
  166. this.target.classList.add("force-select");
  167.  
  168. },
  169. uninit: function(){
  170.  
  171. this.target.classList.remove("force-select");
  172. this.target = null;
  173. this.range = null;
  174. this.multiSelect = false;
  175.  
  176. }
  177. };
  178.  
  179. document.addEventListener("mousemove", force, false);
  180. document.addEventListener("mouseup", force, false);
  181. document.addEventListener("mousedown", force, false);
  182. document.addEventListener("click", force, true);
  183. document.addEventListener("dragstart", force, true);
  184. document.addEventListener("dragend", force, true);
  185. document.addEventListener("drag", force, true);
  186. document.addEventListener("DOMContentLoaded", function(){
  187. GM_addStyle(".force-select{ -moz-user-select: text!important; }");
  188. }, false);