Нет описания

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*global $, window*/
  2. $.fn.editableTableWidget = function (options) {
  3. 'use strict';
  4. return $(this).each(function () {
  5. var buildDefaultOptions = function () {
  6. var opts = $.extend({}, $.fn.editableTableWidget.defaultOptions);
  7. opts.editor = opts.editor.clone();
  8. return opts;
  9. },
  10. activeOptions = $.extend(buildDefaultOptions(), options),
  11. ARROW_LEFT = 37, ARROW_UP = 38, ARROW_RIGHT = 39, ARROW_DOWN = 40, ENTER = 13, ESC = 27, TAB = 9,
  12. element = $(this),
  13. editor = activeOptions.editor.css('position', 'absolute').hide().appendTo(element.parent()),
  14. active,
  15. showEditor = function (select) {
  16. active = element.find('td:focus');
  17. if (active.length) {
  18. editor.val(active.text())
  19. .removeClass('error')
  20. .show()
  21. .offset(active.offset())
  22. .css(active.css(activeOptions.cloneProperties))
  23. .width(active.width())
  24. .height(active.height())
  25. .focus();
  26. if (select) {
  27. editor.select();
  28. }
  29. }
  30. },
  31. setActiveText = function () {
  32. var text = editor.val(),
  33. evt = $.Event('change'),
  34. originalContent;
  35. if (active.text() === text || editor.hasClass('error')) {
  36. return true;
  37. }
  38. originalContent = active.html();
  39. active.text(text).trigger(evt, text);
  40. if (evt.result === false) {
  41. active.html(originalContent);
  42. }
  43. },
  44. movement = function (element, keycode) {
  45. if (keycode === ARROW_RIGHT) {
  46. return element.next('td');
  47. } else if (keycode === ARROW_LEFT) {
  48. return element.prev('td');
  49. } else if (keycode === ARROW_UP) {
  50. return element.parent().prev().children().eq(element.index());
  51. } else if (keycode === ARROW_DOWN) {
  52. return element.parent().next().children().eq(element.index());
  53. }
  54. return [];
  55. };
  56. editor.blur(function () {
  57. setActiveText();
  58. editor.hide();
  59. }).keydown(function (e) {
  60. if (e.which === ENTER) {
  61. setActiveText();
  62. editor.hide();
  63. active.focus();
  64. e.preventDefault();
  65. e.stopPropagation();
  66. } else if (e.which === ESC) {
  67. editor.val(active.text());
  68. e.preventDefault();
  69. e.stopPropagation();
  70. editor.hide();
  71. active.focus();
  72. } else if (e.which === TAB) {
  73. active.focus();
  74. } else if (this.selectionEnd - this.selectionStart === this.value.length) {
  75. var possibleMove = movement(active, e.which);
  76. if (possibleMove.length > 0) {
  77. possibleMove.focus();
  78. e.preventDefault();
  79. e.stopPropagation();
  80. }
  81. }
  82. })
  83. .on('input paste', function () {
  84. var evt = $.Event('validate');
  85. active.trigger(evt, editor.val());
  86. if (evt.result === false) {
  87. editor.addClass('error');
  88. } else {
  89. editor.removeClass('error');
  90. }
  91. });
  92. element.on('click keypress dblclick', showEditor)
  93. .css('cursor', 'pointer')
  94. .keydown(function (e) {
  95. var prevent = true,
  96. possibleMove = movement($(e.target), e.which);
  97. if (possibleMove.length > 0) {
  98. possibleMove.focus();
  99. } else if (e.which === ENTER) {
  100. showEditor(false);
  101. } else if (e.which === 17 || e.which === 91 || e.which === 93) {
  102. showEditor(true);
  103. prevent = false;
  104. } else {
  105. prevent = false;
  106. }
  107. if (prevent) {
  108. e.stopPropagation();
  109. e.preventDefault();
  110. }
  111. });
  112. element.find('td').prop('tabindex', 1);
  113. $(window).on('resize', function () {
  114. if (editor.is(':visible')) {
  115. editor.offset(active.offset())
  116. .width(active.width())
  117. .height(active.height());
  118. }
  119. });
  120. });
  121. };
  122. $.fn.editableTableWidget.defaultOptions = {
  123. cloneProperties: ['padding', 'padding-top', 'padding-bottom', 'padding-left', 'padding-right',
  124. 'text-align', 'font', 'font-size', 'font-family', 'font-weight',
  125. 'border', 'border-top', 'border-bottom', 'border-left', 'border-right'],
  126. editor: $('<input>')
  127. };