使用dataTables组件制作可编辑table单元格时blur、 mouseleave以及mouseenter事件的冲突

32次阅读

共计 2924 个字符,预计需要花费 8 分钟才能阅读完成。

问题出现的场景是:使用 dataTables 组件,但是该组件没有自带的编辑功能,所以需要自己处理 table 在行内编辑的效果。
目标效果是:1. 当 hover 到当前 tr 的时候,该行 tr 中可以编辑的 td 中出现一个 input 框:

2. 当离开当前 tr 的时候,该行退出可编辑的状态,恢复到没有 hover 上去之前的效果。

3. 当 td 变成可编辑状态,即出现了一个 input 输入框的时候,focus 到 input 输入框中,可以输入 number;当 input 框发生 blur 事件的时候,td 恢复到非编辑状态:

由于 blur 和 moseleave 都会让输入框恢复到非编辑的状态,所以,这里的事件会有冲突。
在实际的编码中,在 tr 上绑定了 mouseenter 和 mouseleave 事件;
mouseenter 事件的绑定:
function mouseenterEvt (e) {
var tds = $(this).children(‘td’);
$.each(tds, function (i, val) {
var jqob = $(val);
if (i !== 3) {
return true;
}
// if there is something validate wrong,stay there width no value exchange
var validateSpanDom = jqob.find(‘span’);
var value = validateSpanDom ? validateSpanDom.text() : ”;
var validateTxt = validateInputBox(value);
if(validateTxt) return false;
// open edit mode
jqob.addClass(“edit-btn-display”);
var txt = jqob.text();
txt = txt.replace(‘$’, ”);
txt = txt.replace(/,/g, ”);
var put = $(“<div class=\”money-budget-validate\”><input type=’text’ class=’edit-input-box’><span></span></div>”);
put.children(‘.edit-input-box’).val(txt);
jqob.html(put);

});
}
$(“#table_id_example tbody”).on(“mouseenter”, “tr”,mouseenterEvt);
mouseleave 事件的绑定:
$(“#table_id_example tbody”).on(“mouseleave”, “tr”, function (e) {
var row = tableDom.row($(this));
var tds = $(this).children(‘td’);

$.each(tds, function (i, val) {
var jqob = $(val);
if (jqob.hasClass(‘edit-btn-display’) && jqob.find(‘.edit-input-box’).length > 0) {
// if there is something validate wrong,stay there width no value exchange
var validateSpanDom = jqob.find(‘span’);
var value = validateSpanDom ? validateSpanDom.text() : ”;
var validateTxt = validateInputBox(value);
if(validateTxt) return false;
var txt = jqob.find(‘.edit-input-box’).val();
txt = txt.replace(‘$’, ”);
if(String(txt).indexOf(‘.’) !== -1 ) {
txt = Number(txt).toFixed(2);
}
jqob.html(txt);
tableDom.cell(jqob).data(txt);
// close edit mode
jqob.removeClass(“edit-btn-display”);
}
});

$(“#table_id_example tbody”).off(“mouseenter”, “tr”,mouseenterEvt)
$(“#table_id_example tbody”).on(“mouseenter”, “tr”,mouseenterEvt)
});
在 input 输入框上绑定了 blur 事件:
blur 事件的绑定:
$(“#table_id_example tbody”).on(“blur”, “.edit-input-box”, function (e) {
var value = $(this).val();
var validateTxt = validateInputBox(value)
if (!validateTxt) {
var td = $(this).parents(‘td’);
var row = tableDom.row($(td));
$(this).toggleClass(“edit-btn-being-edit”);
var txt = $(this).val();
txt = txt.replace(‘$’, ”);
if(String(txt).indexOf(‘.’) !== -1 ) {
txt = Number(txt).toFixed(2);
}
td.html(txt);
tableDom.cell(td).data(txt);//change data of DataTables obj
var data = row.data();
//alert(‘save current monthly-budget value’)
$(“#table_id_example tbody”).off(“mouseenter”, “tr”,mouseenterEvt)
}
});
对于事件解绑和重新绑定的解释:

当没有进行事件的解绑和重新绑定的时候,在 input 框中输入结束,点击 input 所在的 td 的时候,会接着触发 mouseenter 事件;但是当点击该 input 所在的 td 之外的 td 的时候,就会发生 blur 事件和 mouseleave 事件。
为了,在点击当前 input 所在的 td 的时候,只发生 blur 事件,需要在 blur 事件结束之后,删除 mouseenter 事件的绑定。这样,tr 的 mouseenter 事件被删除了就不会触发了。
但是,在当前行 blur 之后,再进入其他的行依旧需要能够编辑,又由于编辑完一行之后,肯定是会 mouseleave 该行的,因此,在 tr 的 mouseleave 事件中又将 tr 的 mouseenter 事件加回去。
需要注意一点,我们在使用 jq 绑定事件的时候,重复的事件是不会被清除的,而是会累加,所以,在 mouseleave 中重新添加事件之前,需要将之前的先清除。在这里就是:在 mousenter 之后根本没有对 input 进行编辑就 mouseleave 了,此时在 mouseleave 中若不先清除原有的事件,那么 tr 上的 mouseenter 事件就会被添加两次。

正文完
 0