2013-07-13 35 views
0

我從一個json對象加載數據到我的頁面上的一個表。然後我允許用戶通過輸入過濾數據並僅顯示匹配。我這樣做的方法肯定不是很好,但它確實有效。如何最好地顯示來自大型json對象的匹配?

現在我想做一個完全相同的事情與機場列表和他們的代碼。問題是機場列表要長得多,並且當用數據加載表格以及在表格中搜索用戶的輸入時,頁面顯着下降。

以下是可以工作的頁面的信息,因此您可以選擇我在做什麼。

當我有更大的數據集進行搜索時,我可以採取什麼不同的操作來達到相同的效果?

頁顯示的數據:(類型 「美國航空公司」 或 「AA」 作爲例子) https://pnrbuilder.com/_popups/dataDecoder.php

JSON對象包含航空公司信息: https://pnrbuilder.com/_java/airlineDecoder.js

Sript加載數據到頁面和過濾器它基於用戶輸入: https://pnrbuilder.com/_java/decodeData.js


這裏是最標誌意義我的代碼NT部分:

// This function is called by a for loop on dom ready 
// It basically prints data stored in a json object to a table on the page 



function fillInfo(line) { 

    var table = document.getElementById('decodeTable'); 

    var row = document.createElement('tr'); 
    table.appendChild(row); 

    var col1 = document.createElement('td'); 
    row.appendChild(col1); 
    var curCode = document.createTextNode(arlnInfo.d[line].IATA); 
    col1.appendChild(curCode); 

    var col2 = document.createElement('td'); 
    row.appendChild(col2); 
    var curArln = document.createTextNode(arlnInfo.d[line].Airline); 
    col2.appendChild(curArln); 

    var col3 = document.createElement('td'); 
    row.appendChild(col3); 
    var curPre = document.createTextNode(arlnInfo.d[line].Prefix); 
    col3.appendChild(curPre); 

    var col4 = document.createElement('td'); 
    row.appendChild(col4); 
    var curIcao = document.createTextNode(arlnInfo.d[line].ICAO); 
    col4.appendChild(curIcao); 

    var col5 = document.createElement('td'); 
    row.appendChild(col5); 
    var curCnty = document.createTextNode(arlnInfo.d[line].Country); 
    col5.appendChild(curCnty); 


} 


// This function checks user input against data in the table 
// If a match is found whitin a row, the row containing the match is shown 
// If a match is not found that row is hidden 



function filterTable(input) { 

    var decodeTable = document.getElementById('decodeTable'); 
    var inputLength = input.length; 


// THis first part makes sure that all rows of the generated table are hidden when no input is present 

    if (inputLength == 0) {    

     for (var r = 1; r < decodeTable.rows.length; r++) { 

      decodeTable.rows[r].style.display = "none"; 

     } 

    } 


// This part checks just the airline codes "column" of the table when input is only one or two characters 


    else if (inputLength < 3) { 

     for (var r = 1; r < decodeTable.rows.length; r++) { 

      var celVal = $(decodeTable.rows[r].cells[0]) 
       .text() 
       .slice(0, inputLength) 
       .toLowerCase(); 
      if (celVal == input) { 
       decodeTable.rows[r].style.display = ""; 
      } else { 
       decodeTable.rows[r].style.display = "none"; 
      } 

     } 
    } 

// This part checks several "columns" of the table when input is more than two characters 

    else if (inputLength > 2) { 

     for (var r = 1; r < decodeTable.rows.length; r++) { 

      var celVal = $(decodeTable.rows[r].cells[2]) 
       .text() 
       .slice(0, inputLength) 
       .toLowerCase(); 
      var celVal2 = $(decodeTable.rows[r].cells[1]) 
       .text(); 
      if (celVal == input || celVal2 == input) { 
       decodeTable.rows[r].style.display = ""; 
      } else if (celVal2.replace(/<[^>]+>/g, "") 
       .toLowerCase() 
       .indexOf(input) >= 0) { 
       decodeTable.rows[r].style.display = ""; 
      } else { 
       decodeTable.rows[r].style.display = "none"; 
      } 

     } 
    } 

} 
+1

難道您不是檢查針對JSON數據的輸入嗎?併爲每個對象添加一個屬性,如isVisible:true/false。當所有設置,循環通過JSON數組和:if(!isVisible){... hide table row} – eosterberg

+0

我確定我可以。這會更快嗎?輸入的每個鍵入事件都會調用「過濾器函數」。通過JSON對象分配/刪除isVisible循環,然後循環通過JSON數組再次加載可見的插槽到表中,這比我現在做的要少得多嗎?不要拒絕它,只是想明白。 – DelightedD0D

回答

1

你可以申請的第一個小優化不是做每個鍵的整個過濾器了,等到用戶打完所以推遲稱之爲半秒:

var timeOut = 0; 
$("#deCode").keyup(function() { 
    // cancel looking, the user typed another character 
    clearTimeout(timeOut); 
    // set a timeout, when user doesn't type another key 
    // within half a second the filter will run 
    var input = $("#deCode").val().toLowerCase().trim(); 
    timeOut=setTimeout(function(){ 
     filterTable(input) 
    },500); 
}); 

接下來就是比較您的JSON數據,而不是jQuery對象和創建表後您的JSON數據轉換爲小寫,所以你不必檢查toLowerCase每一次的每一行:

function filterTable(input) { 
    var decodeTable = document.getElementById('decodeTable'); 
    var inputLength = input.length; 
    if (inputLength ==0) { 
     for (var r = 1; r < decodeTable.rows.length; r++) { 
      decodeTable.rows[r].style.display = "none"; 
     } 
    } 
    else if (inputLength <3) { 
     for (var r = 0; r < arlnInfo.d.length; r++) { 
      if (arlnInfo.d[r].IATA.indexOf(input)===0) { 
       decodeTable.rows[r+1].style.display = ""; 
      } 
      else { 
       decodeTable.rows[r+1].style.display = "none"; 
      } 

     } 
    } 
    else if (inputLength > 2) { 
     for (var r = 0; r < arlnInfo.d.length; r++) { 
      if (arlnInfo.d[r].Prefix.indexOf(input)===0) { 
       decodeTable.rows[r].style.display = ""; 
      } 
      else if (arlnInfo.d[r].Airline.indexOf(input) >= 0) { 
       decodeTable.rows[r + 1].style.display = ""; 
      } 
      else { 
       decodeTable.rows[r + 1].style.display = "none"; 
      } 

     } 
    } 
}  

問題出在您的JSON數據上:"Prefix": 430導致arlnInfo.d[r].Prefix.slice(0, inputLength)拋出錯誤,因爲數據不是字符串而是數字。如果你控制了JSON,那麼你應該將這些值轉換爲字符串("Prefix":"430"),如果你不然後將其轉換一次,並重新使用JSON.stringify(arlnInfo);

要轉換的JSON創建airlineDecoder.js您可以複製並粘貼此在Chrome控制檯(按F12)並運行它(按Enter鍵)。它會記錄轉換後的JSON,但你可能需要一個IDE喜歡的NetBeans重新格式:

var i = 0; 
for(i=0;i<arlnInfo.d.length;i++){ 
    arlnInfo.d[i].Prefix=arlnInfo.d[i].Prefix+""; 
} 
console.log("var arlnInfo = " + JSON.stringify(arlnInfo)); 

你可以申請被使用,而不是每一行直接添加到DOM DocumentFragment的最後一個優化,在這裏我們轉換JSON數據爲小寫,因此我們不必爲每次搜索都這樣做:

var decodeTable = document.getElementById('decodeTable'); 
function createTable() { 
    var df = document.createDocumentFragment(); 
    for (var i = 0; i < arlnInfo.d.length; i++) { 
     fillInfo(i, df); 
     arlnInfo.d[i].IATA = arlnInfo.d[i].IATA.toLowerCase() 
     arlnInfo.d[i].Prefix = arlnInfo.d[i].Prefix.toLowerCase(); 
     arlnInfo.d[i].Airline = arlnInfo.d[i].Airline.toLowerCase(); 
    } 
    decodeTable.appendChild(df); 
} 
createTable(); 
.... 
function fillInfo(line,df) { 
    var row = document.createElement('tr'); 
     df.appendChild(row); 
    .... 
    row.style.display = "none"; 
} 
+0

真正的瓶頸是從DOM訪問數據... – eosterberg

+0

啊,我明白了。因此,將isVisible設置爲數組,然後只加載這些數組確實會比循環遍歷錶行更快。我很喜歡這個延遲。但是,如果用戶退格或繼續輸入,如何從表中刪除不再與輸入匹配的行? – DelightedD0D

+0

@eosterberg是的,我已經更新了答案,想要測試並查看是否可以使用JSON數據用於搜索,但它的工作原理,但JSON需要更改 – HMR