jquery.numberedtextarea.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * NumberedTextarea - jQuery Plugin
  3. * Textarea with line numbering
  4. *
  5. * Copyright (c) 2015 Dariusz Arciszewski
  6. *
  7. * Requires: jQuery v2.0+
  8. *
  9. * Licensed under the GPL licenses:
  10. * http://www.gnu.org/licenses/gpl.html
  11. */
  12. (function ($) {
  13. $.fn.numberedtextarea = function(options) {
  14. var settings = $.extend({
  15. color: null, // Font color
  16. borderColor: null, // Border color
  17. class: null, // Add class to the 'numberedtextarea-wrapper'
  18. allowTabChar: false, // If true Tab key creates indentation
  19. }, options);
  20. this.each(function() {
  21. if(this.nodeName.toLowerCase() !== "textarea") {
  22. console.log('This is not a <textarea>, so no way Jose...');
  23. return false;
  24. }
  25. addWrapper(this, settings);
  26. addLineNumbers(this, settings);
  27. if(settings.allowTabChar) {
  28. $(this).allowTabChar();
  29. }
  30. });
  31. return this;
  32. };
  33. $.fn.allowTabChar = function() {
  34. if (this.jquery) {
  35. this.each(function() {
  36. if (this.nodeType == 1) {
  37. var nodeName = this.nodeName.toLowerCase();
  38. if (nodeName == "textarea" || (nodeName == "input" && this.type == "text")) {
  39. allowTabChar(this);
  40. }
  41. }
  42. })
  43. }
  44. return this;
  45. }
  46. function addWrapper(element, settings) {
  47. var wrapper = $('<div class="numberedtextarea-wrapper"></div>').insertAfter(element);
  48. $(element).detach().appendTo(wrapper);
  49. }
  50. function addLineNumbers(element, settings) {
  51. element = $(element);
  52. var wrapper = element.parents('.numberedtextarea-wrapper');
  53. // Get textarea styles to implement it on line numbers div
  54. var paddingLeft = parseFloat(element.css('padding-left'));
  55. var paddingTop = parseFloat(element.css('padding-top'));
  56. var paddingBottom = parseFloat(element.css('padding-bottom'));
  57. var lineNumbers = $('<div class="numberedtextarea-line-numbers"></div>').insertAfter(element);
  58. element.css({
  59. paddingLeft: paddingLeft + lineNumbers.width() + 'px'
  60. }).on('input propertychange change keyup paste', function() {
  61. renderLineNumbers(element, settings);
  62. }).on('scroll', function() {
  63. scrollLineNumbers(element, settings);
  64. });
  65. lineNumbers.css({
  66. paddingLeft: paddingLeft + 'px',
  67. paddingTop: paddingTop + 'px',
  68. lineHeight: element.css('line-height'),
  69. fontFamily: element.css('font-family'),
  70. width: lineNumbers.width() - paddingLeft + 'px',
  71. });
  72. element.trigger('change');
  73. }
  74. function renderLineNumbers(element, settings) {
  75. element = $(element);
  76. var linesDiv = element.parent().find('.numberedtextarea-line-numbers');
  77. var count = element.val().split("\n").length;
  78. var paddingBottom = parseFloat(element.css('padding-bottom'));
  79. linesDiv.find('.numberedtextarea-number').remove();
  80. for(i = 1; i<=count; i++) {
  81. var line = $('<div class="numberedtextarea-number numberedtextarea-number-' + i + '">' + i + '</div>').appendTo(linesDiv);
  82. if(i === count) {
  83. line.css('margin-bottom', paddingBottom + 'px');
  84. }
  85. }
  86. }
  87. function scrollLineNumbers(element, settings) {
  88. element = $(element);
  89. var linesDiv = element.parent().find('.numberedtextarea-line-numbers');
  90. linesDiv.scrollTop(element.scrollTop());
  91. }
  92. function pasteIntoInput(el, text) {
  93. el.focus();
  94. if (typeof el.selectionStart == "number") {
  95. var val = el.value;
  96. var selStart = el.selectionStart;
  97. el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);
  98. el.selectionEnd = el.selectionStart = selStart + text.length;
  99. } else if (typeof document.selection != "undefined") {
  100. var textRange = document.selection.createRange();
  101. textRange.text = text;
  102. textRange.collapse(false);
  103. textRange.select();
  104. }
  105. }
  106. function allowTabChar(el) {
  107. $(el).keydown(function(e) {
  108. if (e.which == 9) {
  109. pasteIntoInput(this, "\t");
  110. return false;
  111. }
  112. });
  113. // For Opera, which only allows suppression of keypress events, not keydown
  114. $(el).keypress(function(e) {
  115. if (e.which == 9) {
  116. return false;
  117. }
  118. });
  119. }
  120. }(jQuery));