背景 我有一个包含小部件的小型jquery应用程序。这个应用程序有两种类型的小部件,它们是计数器小部件和网格小部件。对于网格小部件,我正在使用dataTables。
我的应用程序基本上连接到服务器并接收各种信息,例如小部件名称等。因此,根据收到的信息,我动态地为每个小部件创建页面。目前情况正常,但我遇到了一个小问题。
问题 我现在的问题是使用我的网格小部件,它使用dataTables api。从我的服务器,我收到这种格式的网格信息。
//EXAMPLE INPUT
/*
<?xml version="1.0" encoding="UTF-8"?>
<rows>
<head>
<column width="55" type="ro" align="left" sort="str">Player</column>
<column width="55" type="ro" align="left" sort="str">State</column>
<column width="55" type="ro" align="left" sort="str">Points</column>
</head>
<row id="1">
<cell>Lebron King James</cell>
<cell>Best Mode</cell>
<cell>45</cell>
</row>
</rows>
*/
然后我将其解析为适当的表格式(函数createTableStringFromXML),以便它适用于数据表。
我的桌子每3秒钟重新加载一次。所以这就是问题所在。
尽管我希望我的表更新,但我认为重新加载整个表格是不好的,因为它不仅看起来很奇怪,而且我认为没有必要。我想知道有没有办法可以编写一些函数来比较旧表和新更新的表,只更新需要更新的行?所以这样整个表自己都没有加载?
我的HTML代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>NBA Fanatico</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="themes/tdMobile.min.css" />
<link rel="stylesheet" href="themes/jquery.mobile.icons.min.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0/jquery.mobile.structure-1.4.0.min.css" />
<link rel="stylesheet" type="text/css" href="cssfinal/style.css" />
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js"></script>
<script src="dhtmxSuite/dhtmlxWindows/codebase/dhtmlxcommon.js" type="text/javascript"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>
<script src="jquery.ui.touch-punch.min.js"></script>
<!-- MAIN JS SCRIPT CONTANS CODE FOR COUTNER WIDGETS, TABLES , AJAX REQUEST FOR GETTING DATA-->
<script src="dynamic.js"></script>
<!-- SCRIPTS FOR DATA TABLES -->
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css" />
<!-- DataTables -->
<script type="text/javascript" charset="utf8" src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
</head>
<body>
<!-- PAGE 1 -->
<div data-role="page" data-theme="a" id="page1">
<!-- <div data-role="header" data-position="fixed">
<h1></h1>
</div> -->
<div data-role="content" data-theme="a">
<div class="login-box" id="login">
<div id="loginprompt">
<div id="header">
<h3>Basketball Fanatico</h3>
</div>
</div>
<form method="GET">
<div id="username" data-role="fieldcontain">
<input type="text" name="username" placeholder="Username" />
</div>
<div id="password" data-role="fieldcontain">
<input type="password" name="password" id="txtId" placeholder="Password"/>
</div>
<div id ="loginbtn">
<a data-role="button" id="log" data-theme="a" href="#page2" data-transition="slide">LOGIN</a>
</div>
</form>
<br />
</div>
</div>
</div>
</div>
<!-- PAGE 2 -->
<div data-role="page" id="page2">
<div data-role ="header" data-position="fixed" data-theme="a">
<a data-iconpos="notext" href="#panel" data-role="button" data-icon="bars"></a>
<h1 class="ui-title" role="heading">Basketball Fanatico</h1>
<div class="ui-btn-right" data-type="horizontal">
<a data-iconpos="notext" href="#page2" data-role="button" data-icon="home" ></a>
<a data-iconpos="notext" href="#page1" data-role="button" data-icon="delete" ></a>
</div>
</div>
<div data-role="content" id="page2content">
<ul data-role="listview" data-inset="true">
<li data-role="list-divider" data-theme="a">WELCOME!</li>
<li>Use the menu on the left to navigate <br />and configure the various options.</li>
</ul>
</div>
</div>
<div data-role="panel" id="panel" data-position="left" data-theme="a" data-display="push">
<!-- <div> -->
<div id="nav"><h3>Navigation</h3>
<hr>
<label>
<input id="chkSort" type="checkbox" checked="true" />Allow sorting</input>
</label>
<hr>
</div>
<div id="items" data-role="button">
<!-- Insert Parsed Widget Names Here -->
<a href="#page1" data-transition="fade" data-theme="a" data-role="button">LOG OUT</a>
</div>
<!-- </div> -->
</div>
</body>
</html>
MY JS
var widgetNames = new Array();
var widgetId = new Array();
var pageId = ''
$( document ).on( "pagecreate", function() {
$( "body > [data-role='panel']" ).panel().enhanceWithin();
//Format the grid as required
$('#example2').dataTable( {
"bPaginate": false,
"bFilter": true,
"bAutoWidth": false,
"oLanguage": { "sSearch": "" }
} );
$('.dataTables_filter input').attr("placeholder", "Search");
$('.dataTables_filter').css('float','none');
$('.dataTables_filter').css('padding-right','0px');
$("#example_filter").detach().prependTo('#header1');
});
$(document).on('pagecreate', '#page1', function() {
// $( ":mobile-pagecontainer" ).on( "pagecontainershow", function( event, ui ) {
// pageId = $('body').pagecontainer('getActivePage').prop("id");
// alert( "The page id of this page is: " + pageId );
// });
$("#log").on('click', function(){
$.ajax({
url: "script.login",
type: "GET",
data: { 'page':'create_user', 'access':'user','username':$("input[name='username']").val(), 'password':$("input[name='password']").val()},
dataType: "text",
success: function (html) {
//console.log(html);
widgetNames = new Array();
widgetId = new Array();
var res = html.match(/insertNewChild(.*);/g);
//Get each widget name and ID and assign to values in an array
for(var i =0;i<res.length;i++){
//alert(res[i]);
var temp = res[i].split(',');
if(temp.length >= 3){
widgetNames[i] = (temp[2].replace('");','')).replace('"','');
widgetId[i] = temp[1].replace("'","").replace("'","").replace(/ /g,'');
}
}
var AllWidgets = ''
var testwidget = new Array();
//Loop through the html returned and get the data relevant to each widget... save in temp array
var tempWidgetContent = html.match(/w\d+\.isHidden(.*)\(\) == false\)[\s\S]*?catch\(err\)\{ \}/gm);
for(var i =0;i<tempWidgetContent.length;i++){
var widgetContent = tempWidgetContent[i].substring(tempWidgetContent[i].indexOf('{')+1);
//alert(widgetContent);
//This alone handles coutners...
testwidget[i] = widgetContent.replace("site +","");
//replace the code for a grids...
if(testwidget[i].indexOf('grid') > 0){
testwidget[i] = CreateGridUpdateFunction(testwidget[i],i);
}
}
var widgetPart = new Array();
//Assume we have widget names, ids, and loading data in 3 arrays
//Loop through and create the necessary page.
for(var i = 0; i<widgetNames.length; i++){
if(testwidget[i].indexOf('hi') > -1){
// alert('WORKING');
var pageHeaderPart = "<div data-role= 'page' id='"+widgetId[i]+"' data-pageindex='"+i+"' class='dynPageClass'><div data-role='header' id='header1' data-position='fixed' data-theme='a'><a href='#panel' data-icon='bars' data-iconpos='notext' class='ui-btn-left'></a><a href='#' data-icon='search' id='search' data-iconpos='notext' class='ui-btn-left' style='margin-left: 35px'></a><h1>BASKETBALL FANATICO</h1><a href='#page1' data-icon='delete' data-iconpos='notext' class='ui-btn-right'></a><a href='#page2' data-icon='home' data-iconpos='notext' class='ui-btn-right' style='margin-right: 35px;'></a></div><div data-role='content'>";
}
else{
var pageHeaderPart = "<div data-role='page' id='"+widgetId[i]+"' data-pageindex='"+i+"' class='dynPageClass'><div data-role='header'data-position='fixed' data-theme='a'><a data-iconpos='notext' href='#panel' data-role='button'data-icon='bars'></a><h1 class='ui-title'role='heading'>BASKETBALL FANATICO</h1><div class='ui-btn-right' data-type='horizontal'><a data-iconpos='notext' href='#page2' data-role='button'data-icon='home'style=\" margin-right:5px; \"></a><a data-iconpos='notext' href='#page1' data-role='button'data-icon='delete'></a></div></div><div data-role='content'>";
}
var pageFooterPart = "</div><div data-role='footer' data-position='fixed'><span class='ui-title'><div id='navigator'></div></span></div></div>";
if(testwidget[i].indexOf('hi') > -1){
// alert('i am a grid');
var check = "<div data-role='tbcontent'><ul data-role='listview'data-insert='true'><li data-role='list-divider' data-theme='a'>"+widgetNames[i]+"";
}
var check = "<div data-role='content'><ul data-role='listview'data-insert='true'><li data-role='list-divider' data-theme='a'>"+widgetNames[i]+"</div>";
if(testwidget[i].indexOf('counterValue') > 0){
// alert('i am a counter');
widgetPart[i] = '<DIV style=\" text-align: center; background-color:#EDEDED; padding-bottom: auto; font-size: 55pt;\" id=widgetContainer_'+widgetId[i]+'></DIV><SCRIPT>' + 'function UpdateWidgetDiv'+widgetId[i]+'() {' + testwidget[i] + '$(\"#widgetContainer_'+widgetId[i]+'").html(counterValue);' + '}' + '</SCRIPT>';
}
if(testwidget[i].indexOf('hi') > -1){
// alert('i am a grid');
widgetPart[i] = '<DIV id=widgetContainer_'+widgetId[i]+'></DIV><SCRIPT>' + 'function UpdateWidgetDiv'+widgetId[i]+'() {' + testwidget[i] + '}' + '</SCRIPT>';
}
else {
widgetPart[i] = '<DIV style=\" text-align: center; background-color:#EDEDED; padding-bottom: auto; font-size: 55pt;\" id=widgetContainer_'+widgetId[i]+'>I dont know what I am</DIV>';
}
AllWidgets +='<a href="#'+widgetId[i]+'" class="widgetLink" data-theme="b" data-role="button" >'+widgetNames[i]+'</a>';
var makePage = $(pageHeaderPart + check + widgetPart[i] + pageFooterPart);
makePage.appendTo($.mobile.pageContainer);
}
$('#items').prepend(AllWidgets).trigger('create');
//Widget Update Function
function UpdateActivePage(){
//get active page
pageId = $(":mobile-pagecontainer" ).pagecontainer('getActivePage').prop("id");
//figure out index
var idx;
for (var i=0; i<widgetId.length; i++){
if (widgetId[i] == pageId){
idx = i;
break;
}
}
//alert(pageId);
//run your update
//alert("RUNNING:");
eval(testwidget[idx]);
//alert('Updateing active page');
$("#widgetContainer_" + pageId).html(counterValue);
$('#grid_'+idx).dataTable( {
"bPaginate": false,
"bFilter": true,
"bAutoWidth": false,
"oLanguage": { "sSearch": "" }
} );
$('.dataTables_filter input').attr("placeholder", "Search");
$('.dataTables_filter').css('float','none');
$('.dataTables_filter').css('padding-right','0px');
$("#example_filter").detach().prependTo('#header1');
}
function CreateGridUpdateFunction(oldUpdatefunction,thisWidgetID)
{
var updateLines = oldUpdatefunction.split("\n");
var updateFunctionCode = "";
for (var i=0; i<updateLines.length;i++)
{
if(updateLines[i].indexOf(" var url = ") > 0)
{
var updateURL = updateLines[i];
if(updateURL.indexOf("&windowWidth=") > 0){
updateURL = updateURL.substr(0,updateURL.lastIndexOf("&windowWidth=")) + "';";
}
updateFunctionCode += updateURL;
updateFunctionCode += " var loader = dhtmlxAjax.getSync(url);";
updateFunctionCode += " if(loader.xmlDoc.responseText.length > 0){";
updateFunctionCode += " counterValue = createTableStringFromXML(loader.xmlDoc.responseText,"+thisWidgetID+");";
updateFunctionCode += " } ";
}
}
return "var counterValue = \"hi\"; "+updateFunctionCode ;
}
$(":mobile-pagecontainer" ).on( "pagechange", function() { UpdateActivePage(); } )
setInterval(UpdateActivePage, 3000);
}
});
});
});
//Returns a bool indicated if the (space trimmed) string starts with needle.
function startsWith(searchString,searchVal){
var search = searchString.trim();
return search.indexOf(searchVal) >= 0;
}
function createTableStringFromXML(serverXML,thisWidgetID){
console.log(serverXML);
var xmlLines = serverXML.split("\n");
var returnTable = "";
for (var i=0; i<xmlLines.length;i++)
{
if(startsWith(xmlLines[i],"<rows"))
{
returnTable += "<table cellpadding=\"2\" cellspacing=\"2\" border=\"0\" class=\"display\" id=\"grid_"+thisWidgetID+"\" width=\"100%\">";
}
else if(startsWith(xmlLines[i],"</rows>"))
{
returnTable += "</tbody></table>";
}
else if(startsWith(xmlLines[i],"<head>"))
{
returnTable += "<thead><tr>";
}
else if(startsWith(xmlLines[i],"</head>"))
{
returnTable += "</tr></thead><tbody>";
}
else if(startsWith(xmlLines[i],"<column"))
{
returnTable += "<th>"+xmlLines[i].match(/>(.*?)</i)[1]+"</th>";
}
else if(startsWith(xmlLines[i],"<row"))
{
returnTable += "<tr>";
}
else if(startsWith(xmlLines[i],"</row"))
{
returnTable += "</tr>";
}
else if(startsWith(xmlLines[i],"<cell"))
{
returnTable += "<td>"+xmlLines[i].match(/>(.*?)</i)[1]+"</td>";
}
console.log(returnTable);
}
return returnTable ;
}
请提供建议,了解如何实现这一目标。如果你不明白我的问题,我很抱歉,请再次问我。我只使用HTML和JS几个月,所以我对此不熟悉,这也可能是为什么我的问题对你们中的一些人来说可能听起来很愚蠢。我为我可怜的英语道歉,如果你不明白,请告诉我。感谢。
答案 0 :(得分:2)
每隔3秒更新一次表可能会导致性能问题,特别是如果你有很多行!
如果您想这样做,您可以遍历更新XML中的行,然后将值写入表中的各个单元格。
<强> DEMO 强>
在我的示例中,表已经存在行id作为行元素的数据属性。我在按钮点击时更新一次,而不是在计时器上每3秒更新一次,但解析将是相同的。
$("#update").on("click", function(){
var $trows= $('#example tbody tr');
var xmlDoc = $.parseXML( xmlstring );
var $xml = $( xmlDoc );
$xml.find("row").each(function(index){
var id = $(this).prop("id");
var $cells = $(this).find("cell");
var c1 = $cells.eq(0).text();
var c2 = $cells.eq(1).text();
var c3 = $cells.eq(2).text();
//get row in table with this id
var $rowtd = $('#example tbody [data-id=' + id + '] td');
$rowtd.eq(0).text(c1);
$rowtd.eq(1).text(c2);
$rowtd.eq(2).text(c3);
});
});
代码将XML字符串加载到XmlDocument中,然后从文档中创建一个jQuery对象。接下来,我遍历所有名为“row”的Xml节点,获取id和3个单元格文本。然后我在现有表中找到具有相同Id的行,并将文本写入行中的existind TD。
如果您拥有正常的行数以及您计划支持的设备类型,则需要测试此性能。