Select text inside a link like Opera

Disable link dragging and select text.

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

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