jQuery.selection - jQuery Plugin

Created by IWASAKI Koji

当前为 2016-05-10 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/19569/124890/jQueryselection%20-%20jQuery%20Plugin.js

  1. /*!
  2. * jQuery.selection - jQuery Plugin
  3. *
  4. * Copyright (c) 2010-2012 IWASAKI Koji (@madapaja).
  5. * http://blog.madapaja.net/
  6. * Under The MIT License
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining
  9. * a copy of this software and associated documentation files (the
  10. * "Software"), to deal in the Software without restriction, including
  11. * without limitation the rights to use, copy, modify, merge, publish,
  12. * distribute, sublicense, and/or sell copies of the Software, and to
  13. * permit persons to whom the Software is furnished to do so, subject to
  14. * the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be
  17. * included in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  23. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  24. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  25. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. */
  27. (function($, win, doc) {
  28. /**
  29. * 要素の文字列選択状態を取得します
  30. *
  31. * @param {Element} element 対象要素
  32. * @return {Object} return
  33. * @return {String} return.text 選択されている文字列
  34. * @return {Integer} return.start 選択開始位置
  35. * @return {Integer} return.end 選択終了位置
  36. */
  37. var _getCaretInfo = function(element){
  38. var res = {
  39. text: '',
  40. start: 0,
  41. end: 0
  42. };
  43.  
  44. if (!element.value) {
  45. /* 値がない、もしくは空文字列 */
  46. return res;
  47. }
  48.  
  49. try {
  50. if (win.getSelection) {
  51. /* IE 以外 */
  52. res.start = element.selectionStart;
  53. res.end = element.selectionEnd;
  54. res.text = element.value.slice(res.start, res.end);
  55. } else if (doc.selection) {
  56. /* for IE */
  57. element.focus();
  58.  
  59. var range = doc.selection.createRange(),
  60. range2 = doc.body.createTextRange(),
  61. tmpLength;
  62.  
  63. res.text = range.text;
  64.  
  65. try {
  66. range2.moveToElementText(element);
  67. range2.setEndPoint('StartToStart', range);
  68. } catch (e) {
  69. range2 = element.createTextRange();
  70. range2.setEndPoint('StartToStart', range);
  71. }
  72.  
  73. res.start = element.value.length - range2.text.length;
  74. res.end = res.start + range.text.length;
  75. }
  76. } catch (e) {
  77. /* あきらめる */
  78. }
  79.  
  80. return res;
  81. };
  82.  
  83. /**
  84. * 要素に対するキャレット操作
  85. * @type {Object}
  86. */
  87. var _CaretOperation = {
  88. /**
  89. * 要素のキャレット位置を取得します
  90. *
  91. * @param {Element} element 対象要素
  92. * @return {Object} return
  93. * @return {Integer} return.start 選択開始位置
  94. * @return {Integer} return.end 選択終了位置
  95. */
  96. getPos: function(element) {
  97. var tmp = _getCaretInfo(element);
  98. return {start: tmp.start, end: tmp.end};
  99. },
  100.  
  101. /**
  102. * 要素のキャレット位置を設定します
  103. *
  104. * @param {Element} element 対象要素
  105. * @param {Object} toRange 設定するキャレット位置
  106. * @param {Integer} toRange.start 選択開始位置
  107. * @param {Integer} toRange.end 選択終了位置
  108. * @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
  109. */
  110. setPos: function(element, toRange, caret) {
  111. caret = this._caretMode(caret);
  112.  
  113. if (caret == 'start') {
  114. toRange.end = toRange.start;
  115. } else if (caret == 'end') {
  116. toRange.start = toRange.end;
  117. }
  118.  
  119. element.focus();
  120. try {
  121. if (element.createTextRange) {
  122. var range = element.createTextRange();
  123.  
  124. if (win.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
  125. toRange.start = element.value.substr(0, toRange.start).replace(/\r/g, '').length;
  126. toRange.end = element.value.substr(0, toRange.end).replace(/\r/g, '').length;
  127. }
  128.  
  129. range.collapse(true);
  130. range.moveStart('character', toRange.start);
  131. range.moveEnd('character', toRange.end - toRange.start);
  132.  
  133. range.select();
  134. } else if (element.setSelectionRange) {
  135. element.setSelectionRange(toRange.start, toRange.end);
  136. }
  137. } catch (e) {
  138. /* あきらめる */
  139. }
  140. },
  141.  
  142. /**
  143. * 要素内の選択文字列を取得します
  144. *
  145. * @param {Element} element 対象要素
  146. * @return {String} return 選択文字列
  147. */
  148. getText: function(element) {
  149. return _getCaretInfo(element).text;
  150. },
  151.  
  152. /**
  153. * キャレットモードを選択します
  154. *
  155. * @param {String} caret キャレットモード
  156. * @return {String} return "keep" | "start" | "end" のいずれか
  157. */
  158. _caretMode: function(caret) {
  159. caret = caret || "keep";
  160. if (caret == false) {
  161. caret = 'end';
  162. }
  163.  
  164. switch (caret) {
  165. case 'keep':
  166. case 'start':
  167. case 'end':
  168. break;
  169.  
  170. default:
  171. caret = 'keep';
  172. }
  173.  
  174. return caret;
  175. },
  176.  
  177. /**
  178. * 選択文字列を置き換えます
  179. *
  180. * @param {Element} element 対象要素
  181. * @param {String} text 置き換える文字列
  182. * @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
  183. */
  184. replace: function(element, text, caret) {
  185. var tmp = _getCaretInfo(element),
  186. orig = element.value,
  187. pos = $(element).scrollTop(),
  188. range = {start: tmp.start, end: tmp.start + text.length};
  189.  
  190. element.value = orig.substr(0, tmp.start) + text + orig.substr(tmp.end);
  191.  
  192. $(element).scrollTop(pos);
  193. this.setPos(element, range, caret);
  194. },
  195.  
  196. /**
  197. * 文字列を選択文字列の前に挿入します
  198. *
  199. * @param {Element} element 対象要素
  200. * @param {String} text 挿入文字列
  201. * @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
  202. */
  203. insertBefore: function(element, text, caret) {
  204. var tmp = _getCaretInfo(element),
  205. orig = element.value,
  206. pos = $(element).scrollTop(),
  207. range = {start: tmp.start + text.length, end: tmp.end + text.length};
  208.  
  209. element.value = orig.substr(0, tmp.start) + text + orig.substr(tmp.start);
  210.  
  211. $(element).scrollTop(pos);
  212. this.setPos(element, range, caret);
  213. },
  214.  
  215. /**
  216. * 文字列を選択文字列の後に挿入します
  217. *
  218. * @param {Element} element 対象要素
  219. * @param {String} text 挿入文字列
  220. * @param {String} caret キャレットモード "keep" | "start" | "end" のいずれか
  221. */
  222. insertAfter: function(element, text, caret) {
  223. var tmp = _getCaretInfo(element),
  224. orig = element.value,
  225. pos = $(element).scrollTop(),
  226. range = {start: tmp.start, end: tmp.end};
  227.  
  228. element.value = orig.substr(0, tmp.end) + text + orig.substr(tmp.end);
  229.  
  230. $(element).scrollTop(pos);
  231. this.setPos(element, range, caret);
  232. }
  233. };
  234.  
  235. /* jQuery.selection を追加 */
  236. $.extend({
  237. /**
  238. * ウィンドウの選択されている文字列を取得
  239. *
  240. * @param {String} mode 選択モード "text" | "html" のいずれか
  241. * @return {String} return
  242. */
  243. selection: function(mode) {
  244. var getText = ((mode || 'text').toLowerCase() == 'text');
  245.  
  246. try {
  247. if (win.getSelection) {
  248. if (getText) {
  249. // get text
  250. return win.getSelection().toString();
  251. } else {
  252. // get html
  253. var sel = win.getSelection(), range;
  254.  
  255. if (sel.getRangeAt) {
  256. range = sel.getRangeAt(0);
  257. } else {
  258. range = doc.createRange();
  259. range.setStart(sel.anchorNode, sel.anchorOffset);
  260. range.setEnd(sel.focusNode, sel.focusOffset);
  261. }
  262.  
  263. return $('<div></div>').append(range.cloneContents()).html();
  264. }
  265. } else if (doc.selection) {
  266. if (getText) {
  267. // get text
  268. return doc.selection.createRange().text;
  269. } else {
  270. // get html
  271. return doc.selection.createRange().htmlText;
  272. }
  273. }
  274. } catch (e) {
  275. /* あきらめる */
  276. }
  277.  
  278. return '';
  279. }
  280. });
  281.  
  282. /* selection を追加 */
  283. $.fn.extend({
  284. selection: function(mode, opts) {
  285. opts = opts || {};
  286.  
  287. switch (mode) {
  288. /**
  289. * selection('getPos')
  290. * キャレット位置を取得します
  291. *
  292. * @return {Object} return
  293. * @return {Integer} return.start 選択開始位置
  294. * @return {Integer} return.end 選択終了位置
  295. */
  296. case 'getPos':
  297. return _CaretOperation.getPos(this[0]);
  298. break;
  299.  
  300. /**
  301. * selection('setPos', opts)
  302. * キャレット位置を設定します
  303. *
  304. * @param {Integer} opts.start 選択開始位置
  305. * @param {Integer} opts.end 選択終了位置
  306. */
  307. case 'setPos':
  308. return this.each(function() {
  309. _CaretOperation.setPos(this, opts);
  310. });
  311. break;
  312.  
  313. /**
  314. * selection('replace', opts)
  315. * 選択文字列を置き換えます
  316. *
  317. * @param {String} opts.text 置き換える文字列
  318. * @param {String} opts.caret キャレットモード "keep" | "start" | "end" のいずれか
  319. */
  320. case 'replace':
  321. return this.each(function() {
  322. _CaretOperation.replace(this, opts.text, opts.caret);
  323. });
  324. break;
  325.  
  326. /**
  327. * selection('insert', opts)
  328. * 選択文字列の前、もしくは後に文字列を挿入えます
  329. *
  330. * @param {String} opts.text 挿入文字列
  331. * @param {String} opts.caret キャレットモード "keep" | "start" | "end" のいずれか
  332. * @param {String} opts.mode 挿入モード "before" | "after" のいずれか
  333. */
  334. case 'insert':
  335. return this.each(function() {
  336. if (opts.mode == 'before') {
  337. _CaretOperation.insertBefore(this, opts.text, opts.caret);
  338. } else {
  339. _CaretOperation.insertAfter(this, opts.text, opts.caret);
  340. }
  341. });
  342.  
  343. break;
  344.  
  345. /**
  346. * selection('get')
  347. * 選択されている文字列を取得
  348. *
  349. * @return {String} return
  350. */
  351. case 'get':
  352. default:
  353. return _CaretOperation.getText(this[0]);
  354. break;
  355. }
  356.  
  357. return this;
  358. }
  359. });
  360. })(jQuery, window, window.document);