Greasy Fork is available in English.

jquery.caret

jquery caret plugin

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greatest.deepsurf.us/scripts/6707/26377/jquerycaret.js

  1. // ==UserScript==
  2. // @name jquery.caret
  3. // @namespace acdvorak
  4. // @description jquery caret plugin
  5. // @source https://github.com/acdvorak/jquery.caret
  6. // @copyright 2012-2014 Andrew C. Dvorak
  7. // @version 1.5.2
  8. // @license MIT
  9. // ==/UserScript==
  10.  
  11.  
  12. /*! jQuery Caret Plugin - v1.5.2 - 2014-03-25
  13. * https://github.com/acdvorak/jquery.caret
  14. * Copyright (c) 2012-2014 Andrew C. Dvorak; Licensed MIT */
  15. function loadjQueryCaret(){
  16. (function($, undefined) {
  17.  
  18. var _input = document.createElement('input');
  19.  
  20. var _support = {
  21. setSelectionRange: ('setSelectionRange' in _input) || ('selectionStart' in _input),
  22. createTextRange: ('createTextRange' in _input) || ('selection' in document)
  23. };
  24.  
  25. var _rNewlineIE = /\r\n/g,
  26. _rCarriageReturn = /\r/g;
  27.  
  28. var _getValue = function(input) {
  29. if (typeof(input.value) !== 'undefined') {
  30. return input.value;
  31. }
  32. return $(input).text();
  33. };
  34.  
  35. var _setValue = function(input, value) {
  36. if (typeof(input.value) !== 'undefined') {
  37. input.value = value;
  38. } else {
  39. $(input).text(value);
  40. }
  41. };
  42.  
  43. var _getIndex = function(input, pos) {
  44. var norm = _getValue(input).replace(_rCarriageReturn, '');
  45. var len = norm.length;
  46.  
  47. if (typeof(pos) === 'undefined') {
  48. pos = len;
  49. }
  50.  
  51. pos = Math.floor(pos);
  52.  
  53. // Negative index counts backward from the end of the input/textarea's value
  54. if (pos < 0) {
  55. pos = len + pos;
  56. }
  57.  
  58. // Enforce boundaries
  59. if (pos < 0) { pos = 0; }
  60. if (pos > len) { pos = len; }
  61.  
  62. return pos;
  63. };
  64.  
  65. var _hasAttr = function(input, attrName) {
  66. return input.hasAttribute ? input.hasAttribute(attrName) : (typeof(input[attrName]) !== 'undefined');
  67. };
  68.  
  69. /**
  70. * @class
  71. * @constructor
  72. */
  73. var Range = function(start, end, length, text) {
  74. this.start = start || 0;
  75. this.end = end || 0;
  76. this.length = length || 0;
  77. this.text = text || '';
  78. };
  79.  
  80. Range.prototype.toString = function() {
  81. return JSON.stringify(this, null, ' ');
  82. };
  83.  
  84. var _getCaretW3 = function(input) {
  85. return input.selectionStart;
  86. };
  87.  
  88. /**
  89. * @see http://stackoverflow.com/q/6943000/467582
  90. */
  91. var _getCaretIE = function(input) {
  92. var caret, range, textInputRange, rawValue, len, endRange;
  93.  
  94. // Yeah, you have to focus twice for IE 7 and 8. *cries*
  95. input.focus();
  96. input.focus();
  97.  
  98. range = document.selection.createRange();
  99.  
  100. if (range && range.parentElement() === input) {
  101. rawValue = _getValue(input);
  102.  
  103. len = rawValue.length;
  104.  
  105. // Create a working TextRange that lives only in the input
  106. textInputRange = input.createTextRange();
  107. textInputRange.moveToBookmark(range.getBookmark());
  108.  
  109. // Check if the start and end of the selection are at the very end
  110. // of the input, since moveStart/moveEnd doesn't return what we want
  111. // in those cases
  112. endRange = input.createTextRange();
  113. endRange.collapse(false);
  114.  
  115. if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
  116. caret = rawValue.replace(_rNewlineIE, '\n').length;
  117. } else {
  118. caret = -textInputRange.moveStart("character", -len);
  119. }
  120.  
  121. return caret;
  122. }
  123.  
  124. // NOTE: This occurs when you highlight part of a textarea and then click in the middle of the highlighted portion in IE 6-10.
  125. // There doesn't appear to be anything we can do about it.
  126. // alert("Your browser is incredibly stupid. I don't know what else to say.");
  127. // alert(range + '\n\n' + range.parentElement().tagName + '#' + range.parentElement().id);
  128.  
  129. return 0;
  130. };
  131.  
  132. /**
  133. * Gets the position of the caret in the given input.
  134. * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
  135. * @returns {Number}
  136. * @see http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea/263796#263796
  137. */
  138. var _getCaret = function(input) {
  139. if (!input) {
  140. return undefined;
  141. }
  142.  
  143. // Mozilla, et al.
  144. if (_support.setSelectionRange) {
  145. return _getCaretW3(input);
  146. }
  147. // IE
  148. else if (_support.createTextRange) {
  149. return _getCaretIE(input);
  150. }
  151.  
  152. return undefined;
  153. };
  154.  
  155. var _setCaretW3 = function(input, pos) {
  156. input.setSelectionRange(pos, pos);
  157. };
  158.  
  159. var _setCaretIE = function(input, pos) {
  160. var range = input.createTextRange();
  161. range.move('character', pos);
  162. range.select();
  163. };
  164.  
  165. /**
  166. * Sets the position of the caret in the given input.
  167. * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
  168. * @param {Number} pos
  169. * @see http://parentnode.org/javascript/working-with-the-cursor-position/
  170. */
  171. var _setCaret = function(input, pos) {
  172. input.focus();
  173.  
  174. pos = _getIndex(input, pos);
  175.  
  176. // Mozilla, et al.
  177. if (_support.setSelectionRange) {
  178. _setCaretW3(input, pos);
  179. }
  180. // IE
  181. else if (_support.createTextRange) {
  182. _setCaretIE(input, pos);
  183. }
  184. };
  185.  
  186. /**
  187. * Inserts the specified text at the current caret position in the given input.
  188. * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
  189. * @param {String} text
  190. * @see http://parentnode.org/javascript/working-with-the-cursor-position/
  191. */
  192. var _insertAtCaret = function(input, text) {
  193. var curPos = _getCaret(input);
  194.  
  195. var oldValueNorm = _getValue(input).replace(_rCarriageReturn, '');
  196.  
  197. var newLength = +(curPos + text.length + (oldValueNorm.length - curPos));
  198. var maxLength = +input.getAttribute('maxlength');
  199.  
  200. if(_hasAttr(input, 'maxlength') && newLength > maxLength) {
  201. var delta = text.length - (newLength - maxLength);
  202. text = text.substr(0, delta);
  203. }
  204.  
  205. _setValue(input, oldValueNorm.substr(0, curPos) + text + oldValueNorm.substr(curPos));
  206.  
  207. _setCaret(input, curPos + text.length);
  208. };
  209.  
  210. var _getInputRangeW3 = function(input) {
  211. var range = new Range();
  212.  
  213. range.start = input.selectionStart;
  214. range.end = input.selectionEnd;
  215.  
  216. var min = Math.min(range.start, range.end);
  217. var max = Math.max(range.start, range.end);
  218.  
  219. range.length = max - min;
  220. range.text = _getValue(input).substring(min, max);
  221.  
  222. return range;
  223. };
  224.  
  225. /** @see http://stackoverflow.com/a/3648244/467582 */
  226. var _getInputRangeIE = function(input) {
  227. var range = new Range();
  228.  
  229. input.focus();
  230.  
  231. var selection = document.selection.createRange();
  232.  
  233. if (selection && selection.parentElement() === input) {
  234. var len, normalizedValue, textInputRange, endRange, start = 0, end = 0;
  235. var rawValue = _getValue(input);
  236.  
  237. len = rawValue.length;
  238. normalizedValue = rawValue.replace(/\r\n/g, "\n");
  239.  
  240. // Create a working TextRange that lives only in the input
  241. textInputRange = input.createTextRange();
  242. textInputRange.moveToBookmark(selection.getBookmark());
  243.  
  244. // Check if the start and end of the selection are at the very end
  245. // of the input, since moveStart/moveEnd doesn't return what we want
  246. // in those cases
  247. endRange = input.createTextRange();
  248. endRange.collapse(false);
  249.  
  250. if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
  251. start = end = len;
  252. } else {
  253. start = -textInputRange.moveStart("character", -len);
  254. start += normalizedValue.slice(0, start).split("\n").length - 1;
  255.  
  256. if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
  257. end = len;
  258. } else {
  259. end = -textInputRange.moveEnd("character", -len);
  260. end += normalizedValue.slice(0, end).split("\n").length - 1;
  261. }
  262. }
  263.  
  264. /// normalize newlines
  265. start -= (rawValue.substring(0, start).split('\r\n').length - 1);
  266. end -= (rawValue.substring(0, end).split('\r\n').length - 1);
  267. /// normalize newlines
  268.  
  269. range.start = start;
  270. range.end = end;
  271. range.length = range.end - range.start;
  272. range.text = normalizedValue.substr(range.start, range.length);
  273. }
  274.  
  275. return range;
  276. };
  277.  
  278. /**
  279. * Gets the selected text range of the given input.
  280. * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
  281. * @returns {Range}
  282. * @see http://stackoverflow.com/a/263796/467582
  283. * @see http://stackoverflow.com/a/2966703/467582
  284. */
  285. var _getInputRange = function(input) {
  286. if (!input) {
  287. return undefined;
  288. }
  289.  
  290. // Mozilla, et al.
  291. if (_support.setSelectionRange) {
  292. return _getInputRangeW3(input);
  293. }
  294. // IE
  295. else if (_support.createTextRange) {
  296. return _getInputRangeIE(input);
  297. }
  298.  
  299. return undefined;
  300. };
  301.  
  302. var _setInputRangeW3 = function(input, startPos, endPos) {
  303. input.setSelectionRange(startPos, endPos);
  304. };
  305.  
  306. var _setInputRangeIE = function(input, startPos, endPos) {
  307. var tr = input.createTextRange();
  308. tr.moveEnd('textedit', -1);
  309. tr.moveStart('character', startPos);
  310. tr.moveEnd('character', endPos - startPos);
  311. tr.select();
  312. };
  313.  
  314. /**
  315. * Sets the selected text range of (i.e., highlights text in) the given input.
  316. * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
  317. * @param {Number} startPos Zero-based index
  318. * @param {Number} endPos Zero-based index
  319. * @see http://parentnode.org/javascript/working-with-the-cursor-position/
  320. * @see http://stackoverflow.com/a/2966703/467582
  321. */
  322. var _setInputRange = function(input, startPos, endPos) {
  323. startPos = _getIndex(input, startPos);
  324. endPos = _getIndex(input, endPos);
  325.  
  326. // Mozilla, et al.
  327. if (_support.setSelectionRange) {
  328. _setInputRangeW3(input, startPos, endPos);
  329. }
  330. // IE
  331. else if (_support.createTextRange) {
  332. _setInputRangeIE(input, startPos, endPos);
  333. }
  334. };
  335.  
  336. /**
  337. * Replaces the currently selected text with the given string.
  338. * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
  339. * @param {String} text New text that will replace the currently selected text.
  340. * @see http://parentnode.org/javascript/working-with-the-cursor-position/
  341. */
  342. var _replaceInputRange = function(input, text) {
  343. var $input = $(input);
  344.  
  345. var oldValue = $input.val();
  346. var selection = _getInputRange(input);
  347.  
  348. var newLength = +(selection.start + text.length + (oldValue.length - selection.end));
  349. var maxLength = +$input.attr('maxlength');
  350.  
  351. if($input.is('[maxlength]') && newLength > maxLength) {
  352. var delta = text.length - (newLength - maxLength);
  353. text = text.substr(0, delta);
  354. }
  355.  
  356. // Now that we know what the user selected, we can replace it
  357. var startText = oldValue.substr(0, selection.start);
  358. var endText = oldValue.substr(selection.end);
  359.  
  360. $input.val(startText + text + endText);
  361.  
  362. // Reset the selection
  363. var startPos = selection.start;
  364. var endPos = startPos + text.length;
  365.  
  366. _setInputRange(input, selection.length ? startPos : endPos, endPos);
  367. };
  368.  
  369. var _selectAllW3 = function(elem) {
  370. var selection = window.getSelection();
  371. var range = document.createRange();
  372. range.selectNodeContents(elem);
  373. selection.removeAllRanges();
  374. selection.addRange(range);
  375. };
  376.  
  377. var _selectAllIE = function(elem) {
  378. var range = document.body.createTextRange();
  379. range.moveToElementText(elem);
  380. range.select();
  381. };
  382.  
  383. /**
  384. * Select all text in the given element.
  385. * @param {HTMLElement} elem Any block or inline element other than a form element.
  386. */
  387. var _selectAll = function(elem) {
  388. var $elem = $(elem);
  389. if ($elem.is('input, textarea') || elem.select) {
  390. $elem.select();
  391. return;
  392. }
  393.  
  394. // Mozilla, et al.
  395. if (_support.setSelectionRange) {
  396. _selectAllW3(elem);
  397. }
  398. // IE
  399. else if (_support.createTextRange) {
  400. _selectAllIE(elem);
  401. }
  402. };
  403.  
  404. var _deselectAll = function() {
  405. if (document.selection) {
  406. document.selection.empty();
  407. }
  408. else if (window.getSelection) {
  409. window.getSelection().removeAllRanges();
  410. }
  411. };
  412.  
  413. $.extend($.fn, {
  414.  
  415. /**
  416. * Gets or sets the position of the caret or inserts text at the current caret position in an input or textarea element.
  417. * @returns {Number|jQuery} The current caret position if invoked as a getter (with no arguments)
  418. * or this jQuery object if invoked as a setter or inserter.
  419. * @see http://web.archive.org/web/20080704185920/http://parentnode.org/javascript/working-with-the-cursor-position/
  420. * @since 1.0.0
  421. * @example
  422. * <pre>
  423. * // Get position
  424. * var pos = $('input:first').caret();
  425. * </pre>
  426. * @example
  427. * <pre>
  428. * // Set position
  429. * $('input:first').caret(15);
  430. * $('input:first').caret(-3);
  431. * </pre>
  432. * @example
  433. * <pre>
  434. * // Insert text at current position
  435. * $('input:first').caret('Some text');
  436. * </pre>
  437. */
  438. caret: function() {
  439. var $inputs = this.filter('input, textarea');
  440.  
  441. // getCaret()
  442. if (arguments.length === 0) {
  443. var input = $inputs.get(0);
  444. return _getCaret(input);
  445. }
  446. // setCaret(position)
  447. else if (typeof arguments[0] === 'number') {
  448. var pos = arguments[0];
  449. $inputs.each(function(_i, input) {
  450. _setCaret(input, pos);
  451. });
  452. }
  453. // insertAtCaret(text)
  454. else {
  455. var text = arguments[0];
  456. $inputs.each(function(_i, input) {
  457. _insertAtCaret(input, text);
  458. });
  459. }
  460.  
  461. return this;
  462. },
  463.  
  464. /**
  465. * Gets or sets the selection range or replaces the currently selected text in an input or textarea element.
  466. * @returns {Range|jQuery} The current selection range if invoked as a getter (with no arguments)
  467. * or this jQuery object if invoked as a setter or replacer.
  468. * @see http://stackoverflow.com/a/2966703/467582
  469. * @since 1.0.0
  470. * @example
  471. * <pre>
  472. * // Get selection range
  473. * var range = $('input:first').range();
  474. * </pre>
  475. * @example
  476. * <pre>
  477. * // Set selection range
  478. * $('input:first').range(15);
  479. * $('input:first').range(15, 20);
  480. * $('input:first').range(-3);
  481. * $('input:first').range(-8, -3);
  482. * </pre>
  483. * @example
  484. * <pre>
  485. * // Replace the currently selected text
  486. * $('input:first').range('Replacement text');
  487. * </pre>
  488. */
  489. range: function() {
  490. var $inputs = this.filter('input, textarea');
  491.  
  492. // getRange() = { start: pos, end: pos }
  493. if (arguments.length === 0) {
  494. var input = $inputs.get(0);
  495. return _getInputRange(input);
  496. }
  497. // setRange(startPos, endPos)
  498. else if (typeof arguments[0] === 'number') {
  499. var startPos = arguments[0];
  500. var endPos = arguments[1];
  501. $inputs.each(function(_i, input) {
  502. _setInputRange(input, startPos, endPos);
  503. });
  504. }
  505. // replaceRange(text)
  506. else {
  507. var text = arguments[0];
  508. $inputs.each(function(_i, input) {
  509. _replaceInputRange(input, text);
  510. });
  511. }
  512.  
  513. return this;
  514. },
  515.  
  516. /**
  517. * Selects all text in each element of this jQuery object.
  518. * @returns {jQuery} This jQuery object
  519. * @see http://stackoverflow.com/a/11128179/467582
  520. * @since 1.5.0
  521. * @example
  522. * <pre>
  523. * // Select the contents of span elements when clicked
  524. * $('span').on('click', function() { $(this).highlight(); });
  525. * </pre>
  526. */
  527. selectAll: function() {
  528. return this.each(function(_i, elem) {
  529. _selectAll(elem);
  530. });
  531. }
  532.  
  533. });
  534.  
  535. $.extend($, {
  536. /**
  537. * Deselects all text on the page.
  538. * @returns {jQuery} The jQuery function
  539. * @since 1.5.0
  540. * @example
  541. * <pre>
  542. * // Select some text
  543. * $('span').selectAll();
  544. *
  545. * // Deselect the text
  546. * $.deselectAll();
  547. * </pre>
  548. */
  549. deselectAll: function() {
  550. _deselectAll();
  551. return this;
  552. }
  553. });
  554.  
  555. }(window.jQuery || window.Zepto || window.$));
  556. }
  557. if (window.document.readyState === 'complete') {
  558. loadjQueryCaret();
  559. } else {
  560. window.addEventListener('load',loadjQueryCaret, false);
  561. }