/*! CellEdit 1.0.19
* ©2016 Elliott Beaty - datatables.net/license
*/
/**
* @summary CellEdit
* @description Make a cell editable when clicked upon
* @version 1.0.19
* @file dataTables.editCell.js
* @author Elliott Beaty
* @contact elliott@elliottbeaty.com
* @copyright Copyright 2016 Elliott Beaty
*
* This source file is free software, available under the following license:
* MIT license - http://datatables.net/license/mit
*
* This source file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
*
* For details please refer to: http://www.datatables.net
*/
jQuery.fn.dataTable.Api.register('MakeCellsEditable()', function (settings) {
var table = this.table();
jQuery.fn.extend({
// UPDATE
updateEditableCell: function (callingElement) {
// Need to redeclare table here for situations where we have more than one datatable on the page. See issue6 on github
var table = $(callingElement).closest("table").DataTable().table();
var row = table.row($(callingElement).parents('tr'));
var cell = table.cell($(callingElement).parents('td, th'));
var columnIndex = cell.index().column;
var inputField =getInputField(callingElement);
// Update
var newValue = inputField.val();
if (!newValue && ((settings.allowNulls) && settings.allowNulls != true)) {
// If columns specified
if (settings.allowNulls.columns) {
// If current column allows nulls
if (settings.allowNulls.columns.indexOf(columnIndex) > -1) {
_update(newValue);
} else {
_addValidationCss();
}
// No columns allow null
} else if (!newValue) {
_addValidationCss();
}
//All columns allow null
} else if (newValue && settings.onValidate) {
if (settings.onValidate(cell, row, newValue)) {
_update(newValue);
} else {
_addValidationCss();
}
}
else {
_update(newValue);
}
function _addValidationCss() {
// Show validation error
if (settings.allowNulls.errorClass) {
$(inputField).addClass(settings.allowNulls.errorClass);
} else {
$(inputField).css({ "border": "red solid 1px" });
}
}
function _update(newValue) {
var oldValue = cell.data();
cell.data(newValue);
//Return cell & row.
settings.onUpdate(cell, row, oldValue);
}
// Get current page
var currentPageIndex = table.page.info().page;
//Redraw table
table.page(currentPageIndex).draw(false);
},
// CANCEL
cancelEditableCell: function (callingElement) {
var table = $(callingElement.closest("table")).DataTable().table();
var cell = table.cell($(callingElement).parents('td, th'));
// Set cell to it's original value
cell.data(cell.data());
// Redraw table
table.draw();
}
});
// Destroy
if (settings === "destroy") {
$(table.body()).off("click", "td");
table = null;
}
if (table != null) {
// On cell click
$(table.body()).on('click', 'td', function () {
var currentColumnIndex = table.cell(this).index().column;
// DETERMINE WHAT COLUMNS CAN BE EDITED
if ((settings.columns && settings.columns.indexOf(currentColumnIndex) > -1) || (!settings.columns)) {
var row = table.row($(this).parents('tr'));
editableCellsRow = row;
var cell = table.cell(this).node();
var oldValue = table.cell(this).data();
// Sanitize value
oldValue = sanitizeCellValue(oldValue);
// Show input
if (!$(cell).find('input').length && !$(cell).find('select').length && !$(cell).find('textarea').length) {
// Input CSS
var input = getInputHtml(currentColumnIndex, settings, oldValue);
$(cell).html(input.html);
if (input.focus) {
$('#ejbeatycelledit').focus();
}
}
}
});
}
});
function getInputHtml(currentColumnIndex, settings, oldValue) {
var inputSetting, inputType, input, inputCss, confirmCss, cancelCss, startWrapperHtml = '', endWrapperHtml = '', listenToKeys = false;
input = {"focus":true,"html":null};
if(settings.inputTypes){
$.each(settings.inputTypes, function (index, setting) {
if (setting.column == currentColumnIndex) {
inputSetting = setting;
inputType = inputSetting.type.toLowerCase();
}
});
}
if (settings.inputCss) { inputCss = settings.inputCss; }
if (settings.wrapperHtml) {
var elements = settings.wrapperHtml.split('{content}');
if (elements.length === 2) {
startWrapperHtml = elements[0];
endWrapperHtml = elements[1];
}
}
if (settings.confirmationButton) {
if (settings.confirmationButton.listenToKeys) { listenToKeys = settings.confirmationButton.listenToKeys; }
confirmCss = settings.confirmationButton.confirmCss;
cancelCss = settings.confirmationButton.cancelCss;
inputType = inputType + "-confirm";
}
switch (inputType) {
case "list":
input.html = startWrapperHtml + "" + endWrapperHtml;
input.focus = false;
break;
case "list-confirm": // List w/ confirm
input.html = startWrapperHtml + " Confirm Cancel" + endWrapperHtml;
input.focus = false;
break;
case "datepicker": //Both datepicker options work best when confirming the values
case "datepicker-confirm":
// Makesure jQuery UI is loaded on the page
if (typeof jQuery.ui == 'undefined') {
alert("jQuery UI is required for the DatePicker control but it is not loaded on the page!");
break;
}
jQuery(".datepick").datepicker("destroy");
input.html = startWrapperHtml + " Confirm Cancel" + endWrapperHtml;
setTimeout(function () { //Set timeout to allow the script to write the input.html before triggering the datepicker
var icon = "http://jqueryui.com/resources/demos/datepicker/images/calendar.gif";
// Allow the user to provide icon
if (typeof inputSetting.options !== 'undefined' && typeof inputSetting.options.icon !== 'undefined') {
icon = inputSetting.options.icon;
}
var self = jQuery('.datepick').datepicker(
{
showOn: "button",
buttonImage: icon,
buttonImageOnly: true,
buttonText: "Select date"
});
},100);
break;
case "text-confirm": // text input w/ confirm
input.html = startWrapperHtml + " Confirm Cancel" + endWrapperHtml;
break;
case "undefined-confirm": // text input w/ confirm
input.html = startWrapperHtml + " Confirm Cancel" + endWrapperHtml;
break;
case "textarea":
input.html = startWrapperHtml + "" + endWrapperHtml;
break;
case "textarea-confirm":
input.html = startWrapperHtml + "Confirm Cancel" + endWrapperHtml;
break;
case "number-confirm" :
input.html = startWrapperHtml + " Confirm Cancel" + endWrapperHtml;
break;
default: // text input
input.html = startWrapperHtml + "" + endWrapperHtml;
break;
}
return input;
}
function getInputField(callingElement) {
// Update datatables cell value
var inputField;
switch ($(callingElement).prop('nodeName').toLowerCase()) {
case 'a': // This means they're using confirmation buttons
if ($(callingElement).siblings('input').length > 0) {
inputField = $(callingElement).siblings('input');
}
if ($(callingElement).siblings('select').length > 0) {
inputField = $(callingElement).siblings('select');
}
if ($(callingElement).siblings('textarea').length > 0) {
inputField = $(callingElement).siblings('textarea');
}
break;
default:
inputField = $(callingElement);
}
return inputField;
}
function sanitizeCellValue(cellValue) {
if (typeof (cellValue) === 'undefined' || cellValue === null || cellValue.length < 1) {
return "";
}
// If not a number
if (isNaN(cellValue)) {
// escape single quote
cellValue = cellValue.replace(/'/g, "'");
}
return cellValue;
}