template.js.plugins.grid.celledit.js Maven / Gradle / Ivy
/**
* jqGrid extension for cellediting Grid Data
* Copyright (c) 2008-2014, Tony Tomov, [email protected], http://trirand.com/blog/
* Copyright (c) 2014-2018, Oleg Kiriljuk, [email protected]
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl-2.0.html
**/
/**
* all events and options here are added anonymous and not in the base grid
* since the array is to big. Here is the order of execution.
* From this point we use jQuery isFunction
* formatCell
* beforeEditCell,
* onSelectCell (used only for non-editable cells)
* afterEditCell,
* beforeSaveCell, (called before validation of values if any)
* beforeSubmitCell (if cellsubmit remote (Ajax))
* afterSubmitCell(if cellsubmit remote (Ajax)),
* afterSaveCell,
* errorCell,
* serializeCellData - new
* Options
* cellsubmit ("remote","clientArray") (added in grid options)
* cellurl
* ajaxCellOptions
**/
/*jshint eqeqeq:false */
/*global jQuery, define, exports, module, require */
/*jslint browser: true, eqeq: true, plusplus: true, vars: true, white: true, todo: true */
(function (factory) {
"use strict";
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define([
"jquery",
"./grid.base",
"./jquery.fmatter",
"./grid.common"
], factory);
} else if (typeof module === "object" && module.exports) {
// Node/CommonJS
module.exports = function (root, $) {
if (!root) {
root = window;
}
if ($ === undefined) {
// require("jquery") returns a factory that requires window to
// build a jQuery instance, we normalize how we use modules
// that require this pattern but the window provided is a noop
// if it's defined (how jquery works)
$ = typeof window !== "undefined" ?
require("jquery") :
require("jquery")(root);
}
require("./grid.base");
require("./jquery.fmatter");
require("./grid.common");
factory($, root);
return $;
};
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
"use strict";
var jgrid = $.jgrid,
feedback = function () {
// short form of $.jgrid.feedback to save usage this.p as the first parameter
var args = $.makeArray(arguments);
args.unshift("");
args.unshift("");
args.unshift(this.p);
return jgrid.feedback.apply(this, args);
};
// begin module grid.celledit
var getTdByColumnIndex = function (tr, iCol) {
var $t = this, frozenRows = $t.grid.fbRows;
tr = frozenRows != null && frozenRows[0].cells.length > iCol ? frozenRows[tr.rowIndex] : tr;
return tr != null && tr.cells != null ? $(tr.cells[iCol]) : $();
},
safeHeightSet = function ($elem, newHeight) {
var height = $elem.height();
if (Math.abs(height - newHeight) >= 1 && newHeight > 0) {
$elem.height(newHeight);
height = $elem.height();
if (Math.abs(newHeight - height) >= 1) {
$elem.height(newHeight + Math.round((newHeight - height)));
}
}
};
jgrid.extend({
editCell: function (iRow, iCol, ed) {
return this.each(function () {
var $t = this, $self = $($t), p = $t.p, nm, tmp, $td, cm, rows = $t.rows;
if (!$t.grid || p.cellEdit !== true || rows == null || rows[iRow] == null) {
return;
}
iRow = parseInt(iRow, 10); // we change iRow and rows[iRow] can be change too
iCol = parseInt(iCol, 10);
if (isNaN(iRow) || isNaN(iCol)) {
return;
}
var tr = rows[iRow], rowid = tr != null ? tr.id : null, $tr = $(tr), edittype,
iColOld = parseInt(p.iCol, 10), iRowOld = parseInt(p.iRow, 10),
$trOld = $(rows[iRowOld]), savedRow = p.savedRow;
// select the row that can be used for other methods
if (rowid == null) {
return;
}
p.selrow = rowid;
if (!p.knv) {
$self.jqGrid("GridNav");
}
// check to see if we have already edited cell
if (savedRow.length > 0 && $trOld.length > 0) {
// prevent second click on that field and enable selects
if (ed === true) {
if (iRow === iRowOld && iCol === iColOld) {
return;
}
}
// save the cell
$self.jqGrid("saveCell", savedRow[0].id, savedRow[0].ic);
} else {
setTimeout(function () {
$("#" + jgrid.jqID(p.knv)).attr("tabindex", "-1").focus();
}, 1);
}
cm = p.colModel[iCol];
nm = cm.name;
if (nm === "subgrid" || nm === "cb" || nm === "rn") {
return;
}
$td = getTdByColumnIndex.call($t, tr, iCol);
var editable = cm.editable, mode = "cell";
if ($.isFunction(editable)) {
editable = editable.call($t, {
rowid: rowid,
iCol: iCol,
iRow: iRow,
cmName: nm,
cm: cm,
mode: mode
});
}
var highlightClasses = $self.jqGrid("getGuiStyles", "states.select", "edit-cell"),
hoverClasses = $self.jqGrid("getGuiStyles", "states.hover", "selected-row");
if (editable === true && ed === true && !$td.hasClass("not-editable-cell")) {
if (!p.noCellSelection) {
if (iColOld >= 0 && iRowOld >= 0) {
getTdByColumnIndex.call($t, $trOld[0], iColOld).removeClass(highlightClasses);
$trOld.removeClass(hoverClasses);
}
$td.addClass(highlightClasses);
$tr.addClass(hoverClasses);
}
if (!cm.edittype) {
cm.edittype = "text";
}
edittype = cm.edittype;
try {
tmp = $.unformat.call($t, $td, { rowId: rowid, colModel: cm }, iCol);
} catch (ex) {
tmp = edittype === "textarea" ? $td.text() : $td.html();
}
if (p.autoEncodeOnEdit) {
tmp = jgrid.oldDecodePostedData(tmp);
}
if (tmp === " " || tmp === " " || (tmp.length === 1 && tmp.charCodeAt(0) === 160)) {
tmp = "";
}
if ($.isFunction(p.formatCell)) {
var tmp2 = p.formatCell.call($t, rowid, nm, tmp, iRow, iCol);
if (tmp2 !== undefined) {
tmp = tmp2;
}
}
feedback.call($t, "beforeEditCell", rowid, nm, tmp, iRow, iCol);
savedRow.push({ id: iRow, ic: iCol, name: nm, v: tmp });
p.editingInfo[rowid] = {
mode: "cellEditing",
savedRow: savedRow[savedRow.length - 1],
editable: {}
};
p.editingInfo[rowid].editable[nm] = editable;
var opt = $.extend({}, cm.editoptions || {},
{ id: iRow + "_" + nm, name: nm, rowId: rowid, mode: mode, cm: cm, iCol: iCol });
var elc = jgrid.createEl.call($t, edittype, opt, tmp, true, $.extend({}, jgrid.ajaxOptions, p.ajaxSelectOptions || {})),
$dataFiled = $td,
editingColumnWithTreeGridIcon = p.treeGrid === true && nm === p.ExpandColumn;
if (editingColumnWithTreeGridIcon) {
$dataFiled = $td.children("span.cell-wrapperleaf,span.cell-wrapper");
}
$dataFiled.html("").append(elc).attr("tabindex", "0");
if (editingColumnWithTreeGridIcon) { // && elc.style.width === "100%"
$(elc).width($td.width() - $td.children("div.tree-wrap").outerWidth());
}
jgrid.bindEv.call($t, elc, opt);
if (p.frozenColumns && iCol < $self.jqGrid("getNumberOfFrozenColumns")) {
safeHeightSet($($t.rows[tr.rowIndex].cells[iCol]), $td.height());
}
setTimeout(function () {
$(elc).focus();
}, 0);
$("input, select, textarea", $td).on("keydown", function (e) {
if (e.keyCode === 27) {
if ($("input.hasDatepicker", $td).length > 0) {
if ($(".ui-datepicker").is(":hidden")) {
$self.jqGrid("restoreCell", iRow, iCol);
} else {
$("input.hasDatepicker", $td).datepicker("hide");
}
} else {
$self.jqGrid("restoreCell", iRow, iCol);
}
} //ESC
if (e.keyCode === 13 && !e.shiftKey) {
$self.jqGrid("saveCell", iRow, iCol);
// Prevent default action
return false;
} //Enter
if (e.keyCode === 9) {
if (!$t.grid.hDiv.loading) {
if (e.shiftKey) {
$self.jqGrid("prevCell", iRow, iCol); //Shift TAb
} else {
$self.jqGrid("nextCell", iRow, iCol); //Tab
}
} else {
return false;
}
}
e.stopPropagation();
});
feedback.call($t, "afterEditCell", rowid, nm, tmp, iRow, iCol);
} else {
if (!p.noCellSelection) {
if (iColOld >= 0 && iRowOld >= 0) {
getTdByColumnIndex.call($t, $trOld[0], iColOld).removeClass(highlightClasses);
$trOld.removeClass(hoverClasses);
}
$td.addClass(highlightClasses);
$tr.addClass(hoverClasses);
}
tmp = $td.html().replace(/ /ig, "");
feedback.call($t, "onSelectCell", rowid, nm, tmp, iRow, iCol);
}
p.iCol = iCol;
p.iRow = iRow;
});
},
saveCell: function (iRow, iCol) {
return this.each(function () {
var $t = this, $self = $($t), p = $t.p, grid = $t.grid, infoDialog = jgrid.info_dialog, jqID = jgrid.jqID;
if (!grid || p.cellEdit !== true) {
return;
}
var errors = $self.jqGrid("getGridRes", "errors"), errcap = errors.errcap,
edit = $self.jqGrid("getGridRes", "edit"), bClose = edit.bClose,
savedRow = p.savedRow, fr = savedRow.length >= 1 ? 0 : null;
if (fr !== null) {
var tr = $t.rows[iRow], rowid = tr != null ? tr.id : null, $tr = tr != null ? $(tr) : $(), cm = p.colModel[iCol], nm = cm.name, vv,
$td = getTdByColumnIndex.call($t, tr, iCol), valueText = {},
v = jgrid.getEditedValue.call($t, $td, cm, valueText);
// The common approach is if nothing changed do not do anything
if (v !== savedRow[fr].v) {
vv = $self.triggerHandler("jqGridBeforeSaveCell", [rowid, nm, v, iRow, iCol]);
if (vv !== undefined) {
v = vv;
}
if ($.isFunction(p.beforeSaveCell)) {
vv = p.beforeSaveCell.call($t, rowid, nm, v, iRow, iCol);
if (vv !== undefined) {
v = vv;
}
}
var cv = jgrid.checkValues.call($t, v, iCol, undefined, undefined, {
oldValue: savedRow[fr].v,
newValue: v,
cmName: nm,
rowid: rowid,
iCol: iCol,
iRow: iRow,
cm: cm,
tr: tr,
td: $td,
mode: "cell"
}),
formatoptions = cm.formatoptions || {};
if (cv == null || cv === true || cv[0] === true) {
var addpost = $self.triggerHandler("jqGridBeforeSubmitCell", [rowid, nm, v, iRow, iCol]) || {};
if ($.isFunction(p.beforeSubmitCell)) {
addpost = p.beforeSubmitCell.call($t, rowid, nm, v, iRow, iCol);
if (!addpost) {
addpost = {};
}
}
if ($("input.hasDatepicker", $td).length > 0) {
$("input.hasDatepicker", $td).datepicker("hide");
}
if (cm.formatter === "date" && formatoptions.sendFormatted !== true) {
// TODO: call all other predefined formatters!!! Not only formatter: "date" have the problem.
// Floating point separator for example
v = $.unformat.date.call($t, v, cm);
}
if (p.cellsubmit === "remote") {
if (p.cellurl) {
var postdata = {};
postdata[nm] = v;
var opers = p.prmNames, idname = opers.id, oper = opers.oper;
postdata[idname] = jgrid.stripPref(p.idPrefix, rowid);
postdata[oper] = opers.editoper;
postdata = $.extend(addpost, postdata);
if (p.autoEncodeOnEdit) {
$.each(postdata, function (n, val) {
if (!$.isFunction(val)) {
postdata[n] = jgrid.oldEncodePostedData(val);
}
});
}
$self.jqGrid("progressBar", { method: "show", loadtype: p.loadui, htmlcontent: $self.jqGrid("getGridRes", "defaults.savetext") || "Saving..." });
grid.hDiv.loading = true;
$.ajax($.extend({
url: $.isFunction(p.cellurl) ? p.cellurl.call($t, p.cellurl, iRow, iCol, rowid, v, nm) : p.cellurl,
//data :$.isFunction(p.serializeCellData) ? p.serializeCellData.call($t, postdata) : postdata,
data: jgrid.serializeFeedback.call($t, p.serializeCellData, "jqGridSerializeCellData", postdata),
type: "POST",
complete: function (jqXHR) {
grid.endReq.call($t);
if ((jqXHR.status < 300 || jqXHR.status === 304) && (jqXHR.status !== 0 || jqXHR.readyState !== 4)) {
var ret = $self.triggerHandler("jqGridAfterSubmitCell", [$t, jqXHR, postdata.id, nm, v, iRow, iCol]) || [true, ""];
if (ret === true || (ret[0] === true && $.isFunction(p.afterSubmitCell))) {
ret = p.afterSubmitCell.call($t, jqXHR, postdata.id, nm, v, iRow, iCol);
}
if (ret == null || ret === true || ret[0] === true) {
$self.jqGrid("setCell", rowid, iCol, v, false, false, true);
$td.addClass("dirty-cell");
$tr.addClass("edited");
feedback.call($t, "afterSaveCell", rowid, nm, v, iRow, iCol);
savedRow.splice(0, 1);
delete p.editingInfo[rowid];
} else {
infoDialog.call($t, errcap, ret[1], bClose);
$self.jqGrid("restoreCell", iRow, iCol);
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
$self.triggerHandler("jqGridErrorCell", [jqXHR, textStatus, errorThrown]);
if ($.isFunction(p.errorCell)) {
p.errorCell.call($t, jqXHR, textStatus, errorThrown);
$self.jqGrid("restoreCell", iRow, iCol);
} else {
infoDialog.call($t, errcap, jqXHR.status + " : " + jqXHR.statusText + "
" + textStatus, bClose);
$self.jqGrid("restoreCell", iRow, iCol);
}
}
}, jgrid.ajaxOptions, p.ajaxCellOptions || {}));
} else {
try {
infoDialog.call($t, errcap, errors.nourl, bClose);
$self.jqGrid("restoreCell", iRow, iCol);
} catch (ignore) { }
}
}
if (p.cellsubmit === "clientArray") {
$self.jqGrid("setCell", rowid, iCol,
cm.edittype === "select" && cm.formatter !== "select" ? valueText.text : v,
false, false, true);
$td.addClass("dirty-cell");
$tr.addClass("edited");
feedback.call($t, "afterSaveCell", rowid, nm, v, iRow, iCol);
if (p.frozenColumns && iCol < $self.jqGrid("getNumberOfFrozenColumns")) {
try {
$t.rows[tr.rowIndex].cells[iCol].style.height = "";
} catch (ignore) { }
}
savedRow.splice(0, 1);
delete p.editingInfo[rowid];
}
} else {
try {
setTimeout(function () {
var relativeRect = jgrid.getRelativeRect.call($t, $td);
infoDialog.call($t, errcap, v + " " + cv[1], bClose, {
top: relativeRect.top,
left: relativeRect.left + $($t).closest(".ui-jqgrid").offset().left
});
}, 50);
$self.jqGrid("restoreCell", iRow, iCol);
} catch (ignore) { }
}
} else {
$self.jqGrid("restoreCell", iRow, iCol);
}
}
setTimeout(function () {
$("#" + jqID(p.knv)).attr("tabindex", "-1").focus();
}, 0);
});
},
restoreCell: function (iRow, iCol) {
return this.each(function () {
var $t = this, p = $t.p, tr = $t.rows[iRow], rowid = tr.id, v, cm, formatoptions;
if (!$t.grid || p.cellEdit !== true) {
return;
}
var savedRow = p.savedRow, $td = getTdByColumnIndex.call($t, tr, iCol);
if (savedRow.length >= 1) {
// datepicker fix
if ($.isFunction($.fn.datepicker)) {
try {
$("input.hasDatepicker", $td).datepicker("hide");
} catch (ignore) { }
}
cm = p.colModel[iCol];
if (p.treeGrid === true && cm != null && cm.name === p.ExpandColumn) {
$td.children("span.cell-wrapperleaf,span.cell-wrapper").empty();
} else {
$td.empty();
}
$td.attr("tabindex", "-1");
v = savedRow[0].v;
if (cm != null) {
formatoptions = cm.formatoptions || {};
if (cm.formatter === "date" && formatoptions.sendFormatted !== true) {
// TODO: call all other predefined formatters!!! Not only formatter: "date" have the problem.
// Floating point separator for example
v = $.unformat.date.call($t, v, cm);
}
$($t).jqGrid("setCell", rowid, iCol, v, false, false, true);
if (p.frozenColumns && iCol < $($t).jqGrid("getNumberOfFrozenColumns")) {
try {
$t.rows[tr.rowIndex].cells[iCol].style.height = "";
} catch (ignore) { }
}
}
feedback.call($t, "afterRestoreCell", rowid, v, iRow, iCol);
savedRow.splice(0, 1);
delete p.editingInfo[rowid];
}
setTimeout(function () {
$("#" + p.knv).attr("tabindex", "-1").focus();
}, 0);
});
},
nextCell: function (iRow, iCol) {
return this.each(function () {
var $t = this, $self = $($t), p = $t.p, nCol = false, i, editable, cm, rows = $t.rows;
if (!$t.grid || p.cellEdit !== true || rows == null || rows[iRow] == null) {
return;
}
// try to find next editable cell
for (i = iCol + 1; i < p.colModel.length; i++) {
cm = p.colModel[i];
editable = cm.editable;
if ($.isFunction(editable)) {
editable = editable.call($t, {
rowid: rows[iRow].id,
iCol: i,
iRow: iRow,
cmName: cm.name,
cm: cm,
mode: "cell"
});
}
if (editable === true) {
nCol = i;
break;
}
}
if (nCol !== false) {
$self.jqGrid("editCell", iRow, nCol, true);
} else {
if (p.savedRow.length > 0) {
$self.jqGrid("saveCell", iRow, iCol);
}
}
});
},
prevCell: function (iRow, iCol) {
return this.each(function () {
var $t = this, $self = $($t), p = $t.p, nCol = false, i, editable, cm, rows = $t.rows;
if (!$t.grid || p.cellEdit !== true || rows == null || rows[iRow] == null) {
return;
}
// try to find next editable cell
for (i = iCol - 1; i >= 0; i--) {
cm = p.colModel[i];
editable = cm.editable;
if ($.isFunction(editable)) {
editable = editable.call($t, {
rowid: rows[iRow].id,
iCol: i,
iRow: iRow,
cmName: cm.name,
cm: cm,
mode: "cell"
});
}
if (editable === true) {
nCol = i;
break;
}
}
if (nCol !== false) {
$self.jqGrid("editCell", iRow, nCol, true);
} else {
if (p.savedRow.length > 0) {
$self.jqGrid("saveCell", iRow, iCol);
}
}
});
},
GridNav: function () {
return this.each(function () {
var $t = this, $self = $($t), p = $t.p, grid = $t.grid, i, kdir;
if (!grid || p.cellEdit !== true) {
return;
}
var bDiv = grid.bDiv;
// trick to process keydown on non input elements
p.knv = p.id + "_kn";
var selection = $("");
function scrollGrid(iR, iC, tp) {
var tr = $t.rows[iR];
if (tp.substr(0, 1) === "v") {
var ch = bDiv.clientHeight,
st = bDiv.scrollTop,
nRot = tr.offsetTop + tr.clientHeight,
pRot = tr.offsetTop;
if (tp === "vd") {
if (nRot >= st + ch) {
bDiv.scrollTop = bDiv.scrollTop + tr.clientHeight;
}
}
if (tp === "vu") {
if (pRot < st) {
bDiv.scrollTop = bDiv.scrollTop - tr.clientHeight;
}
}
}
if (tp === "h") {
var cw = bDiv.clientWidth,
sl = bDiv.scrollLeft,
td = tr.cells[iC],
nCol = td.offsetLeft + td.clientWidth,
pCol = td.offsetLeft;
if (nCol >= cw + parseInt(sl, 10)) {
bDiv.scrollLeft = bDiv.scrollLeft + td.clientWidth;
} else if (pCol < sl) {
bDiv.scrollLeft = bDiv.scrollLeft - td.clientWidth;
}
}
}
function findNextVisible(iC, act) {
var ind = 0, j, colModel = p.colModel;
if (act === "lft") {
ind = iC + 1;
for (j = iC; j >= 0; j--) {
if (colModel[j].hidden !== true) {
ind = j;
break;
}
}
}
if (act === "rgt") {
ind = iC - 1;
for (j = iC; j < colModel.length; j++) {
if (colModel[j].hidden !== true) {
ind = j;
break;
}
}
}
return ind;
}
$(selection).insertBefore(grid.cDiv);
$("#" + p.knv)
.focus()
.keydown(function (e) {
var iRowOld = parseInt(p.iRow, 10), iColOld = parseInt(p.iCol, 10);
kdir = e.keyCode;
if (p.direction === "rtl") {
if (kdir === 37) {
kdir = 39;
} else if (kdir === 39) {
kdir = 37;
}
}
switch (kdir) {
case 38:
if (iRowOld - 1 > 0) {
scrollGrid(iRowOld - 1, iColOld, "vu");
$self.jqGrid("editCell", iRowOld - 1, iColOld, false);
}
break;
case 40:
if (iRowOld + 1 <= $t.rows.length - 1) {
scrollGrid(iRowOld + 1, iColOld, "vd");
$self.jqGrid("editCell", iRowOld + 1, iColOld, false);
}
break;
case 37:
if (iColOld - 1 >= 0) {
i = findNextVisible(iColOld - 1, "lft");
scrollGrid(iRowOld, i, "h");
$self.jqGrid("editCell", iRowOld, i, false);
}
break;
case 39:
if (iColOld + 1 <= p.colModel.length - 1) {
i = findNextVisible(iColOld + 1, "rgt");
scrollGrid(iRowOld, i, "h");
$self.jqGrid("editCell", iRowOld, i, false);
}
break;
case 13:
if (iColOld >= 0 && iRowOld >= 0) {
$self.jqGrid("editCell", iRowOld, iColOld, true);
}
break;
default:
return true;
}
return false;
});
});
},
getChangedCells: function (mthd) {
var ret = [];
if (!mthd) {
mthd = "all";
}
this.each(function () {
var $t = this, p = $t.p, htmlDecode = jgrid.htmlDecode, rows = $t.rows;
if (!$t.grid || p.cellEdit !== true) {
return;
}
$(rows).each(function (j) {
var res = {};
if ($(this).hasClass("edited")) {
var tr = this;
$(this.cells).each(function (i) {
var cm = p.colModel[i], nm = cm.name, $td = getTdByColumnIndex.call($t, tr, i); // $td = $(this);
if (nm !== "cb" && nm !== "subgrid" && nm !== "rn" && (mthd !== "dirty" || $td.hasClass("dirty-cell"))) {
try {
res[nm] = $.unformat.call($t, $td[0], { rowId: rows[j].id, colModel: cm }, i);
} catch (e) {
res[nm] = htmlDecode($td.html());
}
}
});
res.id = this.id;
ret.push(res);
}
});
});
return ret;
}
});
// end module grid.celledit
}));
© 2015 - 2025 Weber Informatics LLC | Privacy Policy