我使用class='filt'
编写了这个很好的代码用于各种表顶部的输入框,以允许根据这些输入过滤表。当然,大多数输入都超过1个字母,所以我想添加一个计时器或类似的去抖动功能。下面的工作正常,但是当我添加计时器时,我开始得到一个
“e.nodename未定义”
错误。任何想法?
<script>
var typingTimer;
var doneTypingInterval = 1000;
$('.filt').on('keyup', function () {
var children = $(this).parent().parent().find("input");
clearTimeout(typingTimer);
typingTimer = setTimeout(function () {
$("#table1 tbody tr").show();
for (var i = 0; i < children.length; i++) {
var tableChild = children[i];
if (tableChild.value) {
var valarr = tableChild.value.split(",,"); //multiple filter separator
for (var az = 0; az < valarr.length; az++) {
if (valarr[az].charAt(0) == '~') { //negation operator
var val2 = valarr[az].substr(1);
$("#table1 tbody tr:not(:not(:has(td:eq(" + tableChild.id + "):contains('" + val2 + "'),td:eq(" + tableChild.id + ") [value*='" + val2 + "'])))").hide();
} else { //standard filter
$("#table1 tbody tr:not(:has(td:eq(" + tableChild.id + "):contains('" + valarr[az] + "'),td:eq(" + tableChild.id + ") [value*='" + valarr[az] + "']))").hide();
}
}
$("#table1 tbody tr").eq(0).show();
}
}
$(this).focus(); //annoying extra code for MS browsers
var thistext = $(this).val();
$(this).val('').val(thistext);
}, doneTypingInterval);
});
</script>
答案 0 :(得分:1)
在启动计时器之前,只需将this
放入另一个参数中,如下所示。因为setTimeout
拥有自己的范围。
<script>
var typingTimer;
var doneTypingInterval = 1000;
$('.filt').on('keyup', function () {
var children = $(this).parent().parent().find("input");
clearTimeout(typingTimer);
//Get this into self
var self = this;
typingTimer = setTimeout(function () {
$("#table1 tbody tr").show();
for (var i = 0; i < children.length; i++) {
var tableChild = children[i];
if (tableChild.value) {
var valarr = tableChild.value.split(",,"); //multiple filter separator
for (var az = 0; az < valarr.length; az++) {
if (valarr[az].charAt(0) == '~') { //negation operator
var val2 = valarr[az].substr(1);
$("#table1 tbody tr:not(:not(:has(td:eq(" + tableChild.id + "):contains('" + val2 + "'),td:eq(" + tableChild.id + ") [value*='" + val2 + "'])))").hide();
} else { //standard filter
$("#table1 tbody tr:not(:has(td:eq(" + tableChild.id + "):contains('" + valarr[az] + "'),td:eq(" + tableChild.id + ") [value*='" + valarr[az] + "']))").hide();
}
}
$("#table1 tbody tr").eq(0).show();
}
}
$(self).focus(); //annoying extra code for MS browsers
var thistext = $(self).val();
$(self).val('').val(thistext);
}, doneTypingInterval);
});
</script>
答案 1 :(得分:1)
这是一个背景问题。您引用this
,认为它指向.filt
元素,但您没有意识到超时回调会将上下文更改为window
。
$('.foo').on('click', function() {
this; //is the clicked element
setTimeout(function() {
this; //is window
}, 1);
});
有几种方法可以引用不同的this
。 jQuery的.bind()
允许您将callbcak与您喜欢的任何this
进行语境化,即元素。
$('.foo').on('click', function() {
this; //is the clicked element
setTimeout(function() {
this; //is also element
}.bind(this), 1); //<-- note bind()
});
或者,您也可以通过立即执行的函数将外部this作为函数参数传递给超时回调:
$('.foo').on('click', function() {
this; //is the clicked element
setTimeout((function(outer_this) { return function() {
outer_this; //is also element
}; })(this), 1);
});
或者只是在输入超时之前创建一个引用它的变量:
$('.foo').on('click', function() {
var outer_this = this; //<-- cache outer scope
this; //is the clicked element
setTimeout(function() {
outer_this; //is also element
}, 1);
});