Brak opisu

dataTables.cellEdit.js 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*! CellEdit 1.0.19
  2. * ©2016 Elliott Beaty - datatables.net/license
  3. */
  4. /**
  5. * @summary CellEdit
  6. * @description Make a cell editable when clicked upon
  7. * @version 1.0.19
  8. * @file dataTables.editCell.js
  9. * @author Elliott Beaty
  10. * @contact elliott@elliottbeaty.com
  11. * @copyright Copyright 2016 Elliott Beaty
  12. *
  13. * This source file is free software, available under the following license:
  14. * MIT license - http://datatables.net/license/mit
  15. *
  16. * This source file is distributed in the hope that it will be useful, but
  17. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  18. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  19. *
  20. * For details please refer to: http://www.datatables.net
  21. */
  22. jQuery.fn.dataTable.Api.register('MakeCellsEditable()', function (settings) {
  23. var table = this.table();
  24. jQuery.fn.extend({
  25. // UPDATE
  26. updateEditableCell: function (callingElement) {
  27. // Need to redeclare table here for situations where we have more than one datatable on the page. See issue6 on github
  28. var table = $(callingElement).closest("table").DataTable().table();
  29. var row = table.row($(callingElement).parents('tr'));
  30. var cell = table.cell($(callingElement).parents('td, th'));
  31. var columnIndex = cell.index().column;
  32. var inputField =getInputField(callingElement);
  33. // Update
  34. var newValue = inputField.val();
  35. if (!newValue && ((settings.allowNulls) && settings.allowNulls != true)) {
  36. // If columns specified
  37. if (settings.allowNulls.columns) {
  38. // If current column allows nulls
  39. if (settings.allowNulls.columns.indexOf(columnIndex) > -1) {
  40. _update(newValue);
  41. } else {
  42. _addValidationCss();
  43. }
  44. // No columns allow null
  45. } else if (!newValue) {
  46. _addValidationCss();
  47. }
  48. //All columns allow null
  49. } else if (newValue && settings.onValidate) {
  50. if (settings.onValidate(cell, row, newValue)) {
  51. _update(newValue);
  52. } else {
  53. _addValidationCss();
  54. }
  55. }
  56. else {
  57. _update(newValue);
  58. }
  59. function _addValidationCss() {
  60. // Show validation error
  61. if (settings.allowNulls.errorClass) {
  62. $(inputField).addClass(settings.allowNulls.errorClass);
  63. } else {
  64. $(inputField).css({ "border": "red solid 1px" });
  65. }
  66. }
  67. function _update(newValue) {
  68. var oldValue = cell.data();
  69. cell.data(newValue);
  70. //Return cell & row.
  71. settings.onUpdate(cell, row, oldValue);
  72. }
  73. // Get current page
  74. var currentPageIndex = table.page.info().page;
  75. //Redraw table
  76. table.page(currentPageIndex).draw(false);
  77. },
  78. // CANCEL
  79. cancelEditableCell: function (callingElement) {
  80. var table = $(callingElement.closest("table")).DataTable().table();
  81. var cell = table.cell($(callingElement).parents('td, th'));
  82. // Set cell to it's original value
  83. cell.data(cell.data());
  84. // Redraw table
  85. table.draw();
  86. }
  87. });
  88. // Destroy
  89. if (settings === "destroy") {
  90. $(table.body()).off("click", "td");
  91. table = null;
  92. }
  93. if (table != null) {
  94. // On cell click
  95. $(table.body()).on('click', 'td', function () {
  96. var currentColumnIndex = table.cell(this).index().column;
  97. // DETERMINE WHAT COLUMNS CAN BE EDITED
  98. if ((settings.columns && settings.columns.indexOf(currentColumnIndex) > -1) || (!settings.columns)) {
  99. var row = table.row($(this).parents('tr'));
  100. editableCellsRow = row;
  101. var cell = table.cell(this).node();
  102. var oldValue = table.cell(this).data();
  103. // Sanitize value
  104. oldValue = sanitizeCellValue(oldValue);
  105. // Show input
  106. if (!$(cell).find('input').length && !$(cell).find('select').length && !$(cell).find('textarea').length) {
  107. // Input CSS
  108. var input = getInputHtml(currentColumnIndex, settings, oldValue);
  109. $(cell).html(input.html);
  110. if (input.focus) {
  111. $('#ejbeatycelledit').focus();
  112. }
  113. }
  114. }
  115. });
  116. }
  117. });
  118. function getInputHtml(currentColumnIndex, settings, oldValue) {
  119. var inputSetting, inputType, input, inputCss, confirmCss, cancelCss, startWrapperHtml = '', endWrapperHtml = '', listenToKeys = false;
  120. input = {"focus":true,"html":null};
  121. if(settings.inputTypes){
  122. $.each(settings.inputTypes, function (index, setting) {
  123. if (setting.column == currentColumnIndex) {
  124. inputSetting = setting;
  125. inputType = inputSetting.type.toLowerCase();
  126. }
  127. });
  128. }
  129. if (settings.inputCss) { inputCss = settings.inputCss; }
  130. if (settings.wrapperHtml) {
  131. var elements = settings.wrapperHtml.split('{content}');
  132. if (elements.length === 2) {
  133. startWrapperHtml = elements[0];
  134. endWrapperHtml = elements[1];
  135. }
  136. }
  137. if (settings.confirmationButton) {
  138. if (settings.confirmationButton.listenToKeys) { listenToKeys = settings.confirmationButton.listenToKeys; }
  139. confirmCss = settings.confirmationButton.confirmCss;
  140. cancelCss = settings.confirmationButton.cancelCss;
  141. inputType = inputType + "-confirm";
  142. }
  143. switch (inputType) {
  144. case "list":
  145. input.html = startWrapperHtml + "<select class='" + inputCss + "' onchange='$(this).updateEditableCell(this);'>";
  146. $.each(inputSetting.options, function (index, option) {
  147. if (oldValue == option.value) {
  148. input.html = input.html + "<option value='" + option.value + "' selected>" + option.display + "</option>"
  149. } else {
  150. input.html = input.html + "<option value='" + option.value + "' >" + option.display + "</option>"
  151. }
  152. });
  153. input.html = input.html + "</select>" + endWrapperHtml;
  154. input.focus = false;
  155. break;
  156. case "list-confirm": // List w/ confirm
  157. input.html = startWrapperHtml + "<select class='" + inputCss + "'>";
  158. $.each(inputSetting.options, function (index, option) {
  159. if (oldValue == option.value) {
  160. input.html = input.html + "<option value='" + option.value + "' selected>" + option.display + "</option>"
  161. } else {
  162. input.html = input.html + "<option value='" + option.value + "' >" + option.display + "</option>"
  163. }
  164. });
  165. input.html = input.html + "</select>&nbsp;<a href='javascript:void(0);' class='" + confirmCss + "' onclick='$(this).updateEditableCell(this);'>Confirm</a> <a href='javascript:void(0);' class='" + cancelCss + "' onclick='$(this).cancelEditableCell(this)'>Cancel</a>" + endWrapperHtml;
  166. input.focus = false;
  167. break;
  168. case "datepicker": //Both datepicker options work best when confirming the values
  169. case "datepicker-confirm":
  170. // Makesure jQuery UI is loaded on the page
  171. if (typeof jQuery.ui == 'undefined') {
  172. alert("jQuery UI is required for the DatePicker control but it is not loaded on the page!");
  173. break;
  174. }
  175. jQuery(".datepick").datepicker("destroy");
  176. input.html = startWrapperHtml + "<input id='ejbeatycelledit' type='text' name='date' class='datepick " + inputCss + "' value='" + oldValue + "'></input> &nbsp;<a href='javascript:void(0);' class='" + confirmCss + "' onclick='$(this).updateEditableCell(this)'>Confirm</a> <a href='javascript:void(0);' class='" + cancelCss + "' onclick='$(this).cancelEditableCell(this)'>Cancel</a>" + endWrapperHtml;
  177. setTimeout(function () { //Set timeout to allow the script to write the input.html before triggering the datepicker
  178. var icon = "http://jqueryui.com/resources/demos/datepicker/images/calendar.gif";
  179. // Allow the user to provide icon
  180. if (typeof inputSetting.options !== 'undefined' && typeof inputSetting.options.icon !== 'undefined') {
  181. icon = inputSetting.options.icon;
  182. }
  183. var self = jQuery('.datepick').datepicker(
  184. {
  185. showOn: "button",
  186. buttonImage: icon,
  187. buttonImageOnly: true,
  188. buttonText: "Select date"
  189. });
  190. },100);
  191. break;
  192. case "text-confirm": // text input w/ confirm
  193. input.html = startWrapperHtml + "<input id='ejbeatycelledit' class='" + inputCss + "' value='"+oldValue+"'" + (listenToKeys ? " onkeyup='if(event.keyCode==13) {$(this).updateEditableCell(this);} else if (event.keyCode===27) {$(this).cancelEditableCell(this);}'" : "") + "></input>&nbsp;<a href='javascript:void(0);' class='" + confirmCss + "' onclick='$(this).updateEditableCell(this)'>Confirm</a> <a href='javascript:void(0);' class='" + cancelCss + "' onclick='$(this).cancelEditableCell(this)'>Cancel</a>" + endWrapperHtml;
  194. break;
  195. case "undefined-confirm": // text input w/ confirm
  196. input.html = startWrapperHtml + "<input id='ejbeatycelledit' class='" + inputCss + "' value='" + oldValue + "'" + (listenToKeys ? " onkeyup='if(event.keyCode==13) {$(this).updateEditableCell(this);} else if (event.keyCode===27) {$(this).cancelEditableCell(this);}'" : "") + "></input>&nbsp;<a href='javascript:void(0);' class='" + confirmCss + "' onclick='$(this).updateEditableCell(this)'>Confirm</a> <a href='javascript:void(0);' class='" + cancelCss + "' onclick='$(this).cancelEditableCell(this)'>Cancel</a>" + endWrapperHtml;
  197. break;
  198. case "textarea":
  199. case "textarea-confirm":
  200. input.html = startWrapperHtml + "<textarea id='ejbeatycelledit' class='" + inputCss + "'>"+oldValue+"</textarea><a href='javascript:void(0);' class='" + confirmCss + "' onclick='$(this).updateEditableCell(this)'>Confirm</a> <a href='javascript:void(0);' class='" + cancelCss + "' onclick='$(this).cancelEditableCell(this)'>Cancel</a>" + endWrapperHtml;
  201. break;
  202. case "number-confirm" :
  203. input.html = startWrapperHtml + "<input id='ejbeatycelledit' type='number' class='" + inputCss + "' value='"+oldValue+"'" + (listenToKeys ? " onkeyup='if(event.keyCode==13) {$(this).updateEditableCell(this);} else if (event.keyCode===27) {$(this).cancelEditableCell(this);}'" : "") + "></input>&nbsp;<a href='javascript:void(0);' class='" + confirmCss + "' onclick='$(this).updateEditableCell(this)'>Confirm</a> <a href='javascript:void(0);' class='" + cancelCss + "' onclick='$(this).cancelEditableCell(this)'>Cancel</a>" + endWrapperHtml;
  204. break;
  205. default: // text input
  206. input.html = startWrapperHtml + "<input id='ejbeatycelledit' class='" + inputCss + "' onfocusout='$(this).updateEditableCell(this)' value='" + oldValue + "'></input>" + endWrapperHtml;
  207. break;
  208. }
  209. return input;
  210. }
  211. function getInputField(callingElement) {
  212. // Update datatables cell value
  213. var inputField;
  214. switch ($(callingElement).prop('nodeName').toLowerCase()) {
  215. case 'a': // This means they're using confirmation buttons
  216. if ($(callingElement).siblings('input').length > 0) {
  217. inputField = $(callingElement).siblings('input');
  218. }
  219. if ($(callingElement).siblings('select').length > 0) {
  220. inputField = $(callingElement).siblings('select');
  221. }
  222. if ($(callingElement).siblings('textarea').length > 0) {
  223. inputField = $(callingElement).siblings('textarea');
  224. }
  225. break;
  226. default:
  227. inputField = $(callingElement);
  228. }
  229. return inputField;
  230. }
  231. function sanitizeCellValue(cellValue) {
  232. if (typeof (cellValue) === 'undefined' || cellValue === null || cellValue.length < 1) {
  233. return "";
  234. }
  235. // If not a number
  236. if (isNaN(cellValue)) {
  237. // escape single quote
  238. cellValue = cellValue.replace(/'/g, "&#39;");
  239. }
  240. return cellValue;
  241. }