我正在尝试使用表格页脚中的文本框过滤表格。当我在这些页脚中键入一个值时,我希望调用表的过滤。为了能够键入比较运算符,我将比较函数推入了一组数据表过滤器,这些过滤器将在相应的页脚文本框中读取文本(可以有一个比较运算符,如>< =)并比较中的值该列根据比较运算符。
过滤效果完美如预期唯一的问题是我不断收到此错误:
未捕获DOMException:无法在'Node'上执行'appendChild':The 要删除的节点不再是此节点的子节点。也许是这样 移动到'模糊'事件处理程序?
错误之后,表格开始表现得很奇怪:焦点远离页脚中的文本框,页脚有时会移动到页眉下方的位置。
如何使表稳定并消除此错误?
请注意$.fn.dataTableExt.afnFiltering.push(
内的功能:
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>
</title>
<link rel="stylesheet" type="text/css"
href="https://cdn.datatables.net/v/dt/jq-2.2.4/dt-1.10.13/b-1.2.4/b-html5-1.2.4/fh-3.1.2/datatables.min.css"/>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css"/>
<script type="text/javascript"
src="https://cdn.datatables.net/v/dt/jq-2.2.4/dt-1.10.13/b-1.2.4/b-html5-1.2.4/fh-3.1.2/datatables.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/plug-ins/1.10.13/sorting/natural.js"></script>
<script src="http://www.chartjs.org/dist/2.6.0/Chart.bundle.js"></script>
<script src="http://www.chartjs.org/samples/latest/utils.js"></script>
</head>
<body>
<img id="loader"
style="
width:36px;
height:36px;
display: none;
position:absolute;
top:50%;
left:50%;
margin-top:-18px;
margin-left:-18px;"/>
<p><a href="/accounts/logout/">Logout</a> | <a href="/accounts/profile/">Home</a></p>
<div id="title">
<b style="font-size:200%">Optimize proxies<br></b>
</div>
<div id="proxy_history_dialog" title="Proxy history" style="display:none;" font="8">
</div>
<div id="graph_dialog" title="Extraction - daily vs accumulative" style="display:none;" font="8">
</div>
<table id='p_table-id' class="display" cellspacing="0" style="float: left;">
<thead>
<tr>
<th>Site id</th>
<th>Site name</th>
<th>Is optimized</th>
<th>Proxy group</th>
<th>Price level</th>
<th>Duration</th>
<th>Avg extraction score (cached)</th>
<th>Max extraction in last 3 days (cached)</th>
<th>Overlap score</th>
<th>Last status</th>
<th>Actions</th>
<th>Change proxy</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Site id</th>
<th>Site name</th>
<th>Is optimized</th>
<th>Proxy group</th>
<th>Price level</th>
<th>Duration</th>
<th>Avg extraction score (cached)</th>
<th>Max extraction in last 3 days (cached)</th>
<th>Overlap score</th>
<th>Last status</th>
<th>Actions</th>
<th>Change proxy</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>-106</td>
<td>target.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:57</td>
<td>83.18</td>
<td>91.03</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_-106">
</select></option>
</td>
</tr>
<tr>
<td>-105</td>
<td>walmart.com (P)</td>
<td>True</td>
<td>us</td>
<td>2</td>
<td>27 days 23:58:15</td>
<td>96.21</td>
<td>97.28</td>
<td>None</td>
<td>failed_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_-105">
</select></option>
</td>
</tr>
<tr>
<td>-104</td>
<td>bestonix (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:56</td>
<td>64.05</td>
<td>63.91</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_-104">
</select></option>
</td>
</tr>
<tr>
<td>209</td>
<td>rockbottomgolf.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>31 days 00:56:48</td>
<td>95.73</td>
<td>95.02</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_209">
</select></option>
</td>
</tr>
<tr>
<td>210</td>
<td>golfgalaxy.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:54</td>
<td>87.91</td>
<td>90.53</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_210">
</select></option>
</td>
</tr>
<tr>
<td>211</td>
<td>tgw.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:53</td>
<td>60.06</td>
<td>64.00</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_211">
</select></option>
</td>
</tr>
<tr>
<td>244</td>
<td>amazon_golf (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>53 days 18:23:36</td>
<td>92.38</td>
<td>93.20</td>
<td>None</td>
<td>None</td>
<td></td>
<td>
Change proxy:
<select id="proxy_dp_244">
</select></option>
</td>
</tr>
<tr>
<td>246</td>
<td>golfdiscount.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>31 days 00:56:46</td>
<td>85.85</td>
<td>75.90</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_246">
</select></option>
</td>
</tr>
<tr>
<td>248</td>
<td>globalgolf.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>31 days 00:56:45</td>
<td>61.02</td>
<td>65.17</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_248">
</select></option>
</td>
</tr>
<tr>
<td>658</td>
<td>sephora_ulta_new (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>13 days 11:17:48</td>
<td>98.55</td>
<td>99.16</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_658">
</select></option>
</td>
</tr>
</tbody>
</table>
<script>
function natural_compare(a, b, html) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?%?$|^0x[0-9a-f]+$|[0-9]+)/gi,
sre = /(^[ ]*|[ ]*$)/g,
dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
hre = /^0x[0-9a-f]+$/i,
ore = /^0/,
htmre = /(<([^>]+)>)/ig,
// convert all to strings and trim()
x = a.toString().replace(sre, '') || '',
y = b.toString().replace(sre, '') || '';
// remove html from strings if desired
if (!html) {
x = x.replace(htmre, '');
y = y.replace(htmre, '');
}
// chunk/tokenize
var xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'),
yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'),
// numeric, hex or date detection
xD = parseInt(x.match(hre), 10) || (xN.length !== 1 && x.match(dre) && Date.parse(x)),
yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
// first try and sort Hex codes or Dates
if (yD) {
if (xD < yD) {
return -1;
}
else if (xD > yD) {
return 1;
}
}
// natural sorting through split numeric strings and default strings
for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
var oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc], 10) || xN[cLoc] || 0;
var oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc], 10) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
return (isNaN(oFxNcL)) ? 1 : -1;
}
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) {
return -1;
}
if (oFxNcL > oFyNcL) {
return 1;
}
}
return 0;
}
$(document).ready(function () {
///////////////////////////////////////////////////////////////////////////
DURATION_COL_IX = 5;
// Setup column search - add a text input to each footer cell
$('#p_table-id').find('tfoot th').each(function () {
var title = $(this).text();
$(this).html('<input type="text" placeholder="Filter">');
});
// DataTable
var table = $('#p_table-id').DataTable({
"orderClasses": false,
lengthChange: false,
columnDefs: [
{type: 'natural', targets: '_all'}
],
"dom": '<"top" li>lt<"bottom"i><"clear">',
fixedHeader: {
footer: true
},
'iDisplayLength': -1,
"order": [[5, "asc"]]
});
// Apply the search todo: delete
var last_changed_footer_col;
table.columns().every(function () {
var col = this;
$('input', this.footer()).on('keyup change', function () {
last_changed_footer_col = col.footer().cellIndex;
table.draw();
});
});
$.fn.dataTableExt.afnFiltering.push(
function (oSettings, aData, iDataIndex) {
var column = table.column(last_changed_footer_col);
var footer_txt = $('input', column.footer()).val().replace(/\s*/g, '');
var cell_data = aData[last_changed_footer_col];
if (footer_txt.match(/^[<>=].+/)) {
var comparator = footer_txt.match(/^([<>=]).*$/)[1];
var val_regex = new RegExp('^' + comparator + '(.*)');
var val = footer_txt.match(val_regex)[1];
switch (comparator) {
case '<':
return natural_compare(cell_data, val, false) < 0;
case '>':
return natural_compare(cell_data, val, false) > 0;
case '=':
return natural_compare(cell_data, val, false) === 0;
}
} else {
//just filter
return cell_data.search(footer_txt) >= 0;
}
}
);
///////////////////////////////////////////////////////////////////////////////
});
</script>
</body>
</html>
答案 0 :(得分:1)
您的问题在这一行:
$('input', this.footer()).on('keyup change', function () {
通过这种方式,您可以调用两次搜索方法,从而获得错误。
因此,您需要将其更改为:
$('input', this.footer()).on('input', function () {
function natural_compare(a, b, html) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?%?$|^0x[0-9a-f]+$|[0-9]+)/gi,
sre = /(^[ ]*|[ ]*$)/g,
dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
hre = /^0x[0-9a-f]+$/i,
ore = /^0/,
htmre = /(<([^>]+)>)/ig,
// convert all to strings and trim()
x = a.toString().replace(sre, '') || '',
y = b.toString().replace(sre, '') || '';
// remove html from strings if desired
if (!html) {
x = x.replace(htmre, '');
y = y.replace(htmre, '');
}
// chunk/tokenize
var xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'),
yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'),
// numeric, hex or date detection
xD = parseInt(x.match(hre), 10) || (xN.length !== 1 && x.match(dre) && Date.parse(x)),
yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
// first try and sort Hex codes or Dates
if (yD) {
if (xD < yD) {
return -1;
}
else if (xD > yD) {
return 1;
}
}
// natural sorting through split numeric strings and default strings
for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
var oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc], 10) || xN[cLoc] || 0;
var oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc], 10) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
return (isNaN(oFxNcL)) ? 1 : -1;
}
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) {
return -1;
}
if (oFxNcL > oFyNcL) {
return 1;
}
}
return 0;
}
$(document).ready(function () {
///////////////////////////////////////////////////////////////////////////
DURATION_COL_IX = 5;
// Setup column search - add a text input to each footer cell
$('#p_table-id').find('tfoot th').each(function () {
var title = $(this).text();
$(this).html('<input type="text" placeholder="Filter">');
});
// DataTable
var table = $('#p_table-id').DataTable({
"orderClasses": false,
lengthChange: false,
columnDefs: [
{type: 'natural', targets: '_all'}
],
"dom": '<"top" li>lt<"bottom"i><"clear">',
fixedHeader: {
footer: true
},
'iDisplayLength': -1,
"order": [[5, "asc"]]
});
// Apply the search todo: delete
var last_changed_footer_col;
table.columns().every(function () {
var col = this;
$('input', this.footer()).on('input', function (e) {
//substitute input with keyup change events
// and print to the console.....
//console.log(e.type);
last_changed_footer_col = col.footer().cellIndex;
table.draw(false);
});
});
$.fn.dataTableExt.afnFiltering.push(
function (oSettings, aData, iDataIndex) {
var column = table.column(last_changed_footer_col);
var footer_txt = $('input', column.footer()).val().replace(/\s*/g, '');
var cell_data = aData[last_changed_footer_col];
if (footer_txt.match(/^[<>=].+/)) {
var comparator = footer_txt.match(/^([<>=]).*$/)[1];
var val_regex = new RegExp('^' + comparator + '(.*)');
var val = footer_txt.match(val_regex)[1];
switch (comparator) {
case '<':
return natural_compare(cell_data, val, false) < 0;
case '>':
return natural_compare(cell_data, val, false) > 0;
case '=':
return natural_compare(cell_data, val, false) === 0;
}
} else {
//just filter
return cell_data.search(footer_txt) >= 0;
}
}
);
});
<link rel="stylesheet" type="text/css"
href="https://cdn.datatables.net/v/dt/jq-2.2.4/dt-1.10.13/b-1.2.4/b-html5-1.2.4/fh-3.1.2/datatables.min.css"/>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css"/>
<script type="text/javascript"
src="https://cdn.datatables.net/v/dt/jq-2.2.4/dt-1.10.13/b-1.2.4/b-html5-1.2.4/fh-3.1.2/datatables.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/plug-ins/1.10.13/sorting/natural.js"></script>
<img id="loader"
style="
width:36px;
height:36px;
display: none;
position:absolute;
top:50%;
left:50%;
margin-top:-18px;
margin-left:-18px;"/>
<p><a href="/accounts/logout/">Logout</a> | <a href="/accounts/profile/">Home</a></p>
<div id="title">
<b style="font-size:200%">Optimize proxies<br></b>
</div>
<div id="proxy_history_dialog" title="Proxy history" style="display:none;" font="8">
</div>
<div id="graph_dialog" title="Extraction - daily vs accumulative" style="display:none;" font="8">
</div>
<table id='p_table-id' class="display" cellspacing="0" style="float: left;">
<thead>
<tr>
<th>Site id</th>
<th>Site name</th>
<th>Is optimized</th>
<th>Proxy group</th>
<th>Price level</th>
<th>Duration</th>
<th>Avg extraction score (cached)</th>
<th>Max extraction in last 3 days (cached)</th>
<th>Overlap score</th>
<th>Last status</th>
<th>Actions</th>
<th>Change proxy</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Site id</th>
<th>Site name</th>
<th>Is optimized</th>
<th>Proxy group</th>
<th>Price level</th>
<th>Duration</th>
<th>Avg extraction score (cached)</th>
<th>Max extraction in last 3 days (cached)</th>
<th>Overlap score</th>
<th>Last status</th>
<th>Actions</th>
<th>Change proxy</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>-106</td>
<td>target.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:57</td>
<td>83.18</td>
<td>91.03</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_-106">
</select></option>
</td>
</tr>
<tr>
<td>-105</td>
<td>walmart.com (P)</td>
<td>True</td>
<td>us</td>
<td>2</td>
<td>27 days 23:58:15</td>
<td>96.21</td>
<td>97.28</td>
<td>None</td>
<td>failed_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_-105">
</select></option>
</td>
</tr>
<tr>
<td>-104</td>
<td>bestonix (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:56</td>
<td>64.05</td>
<td>63.91</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_-104">
</select></option>
</td>
</tr>
<tr>
<td>209</td>
<td>rockbottomgolf.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>31 days 00:56:48</td>
<td>95.73</td>
<td>95.02</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_209">
</select></option>
</td>
</tr>
<tr>
<td>210</td>
<td>golfgalaxy.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:54</td>
<td>87.91</td>
<td>90.53</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_210">
</select></option>
</td>
</tr>
<tr>
<td>211</td>
<td>tgw.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>14 days 11:17:53</td>
<td>60.06</td>
<td>64.00</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_211">
</select></option>
</td>
</tr>
<tr>
<td>244</td>
<td>amazon_golf (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>53 days 18:23:36</td>
<td>92.38</td>
<td>93.20</td>
<td>None</td>
<td>None</td>
<td></td>
<td>
Change proxy:
<select id="proxy_dp_244">
</select></option>
</td>
</tr>
<tr>
<td>246</td>
<td>golfdiscount.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>31 days 00:56:46</td>
<td>85.85</td>
<td>75.90</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_246">
</select></option>
</td>
</tr>
<tr>
<td>248</td>
<td>globalgolf.com (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>31 days 00:56:45</td>
<td>61.02</td>
<td>65.17</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_248">
</select></option>
</td>
</tr>
<tr>
<td>658</td>
<td>sephora_ulta_new (P)</td>
<td>True</td>
<td>shader_us</td>
<td>1</td>
<td>13 days 11:17:48</td>
<td>98.55</td>
<td>99.16</td>
<td>None</td>
<td>successful_downgrade</td>
<td style="position: relative;">
<td>
Change proxy:
<select id="proxy_dp_658">
</select></option>
</td>
</tr>
</tbody>
</table>