2009-09-14 86 views
0

我有一個需要以下內容的項目。JavaScript複雜數組「減少元素」 - 基於數組元素構建HTML表格

四個陣列將在代碼被聲明爲這樣:

var ROW1 = ['module1']; 
var ROW2 = ['module2', 'module3']; 
var ROW3 = ['module4', 'module5', 'module6']; 
var ROW4 = ['module7', 'module8']; 

這些陣列中的每一個元素表示在一個可配置的HTML插件的模塊。根據每個數組中指定的元素,代碼將構建代表這些「模塊」的HTML - 每個「ROWx」數組將作爲錶行(),並且每個模塊將成爲表中的表格單元格()。

ROW1可以爲空(在這種情況下,它不會包含在HTML中)或者有一個模塊「module1」。

ROW2,ROW3和ROW4每個都可以有0到3個模塊(任意的module2 - module8,以任何順序)。

使用上述示例陣列,身份證編程方式生成一個HTML表格是這樣的:

<table> 
    <tr id="row1"> 
    <td colspan="6">[module1]</td> 
    </tr> 
    <tr id="row2"> 
    <td colspan="3">[module2]</td> 
    <td colspan="3">[module3]</td> 
    </tr> 
    <tr id="row3"> 
    <td colspan="2">[module4]</td> 
    <td colspan="2">[module5]</td> 
    <td colspan="2">[module6]</td> 
    </tr> 
    <tr id="row4"> 
    <td colspan="3">[module7]</td> 
    <td colspan="3">[module8]</td> 
    </tr> 
</table> 

(該colspans只是有保持適當的表的佈局;圖6是1之間的最小公倍數, 2和3)

問題是,這些模塊的內容是動態填充的(我從一個AJAX調用獲取它到一個返回JSON對象的URL),並且內容並不總是可用於每個模塊。我沒有爲沒有內容的模塊創建一個空單元格(),而是希望從佈局中完全刪除該單元格,就像從未在原始配置中那樣(即頂部的數組)。

我已經花了很多時間來創建抽象模塊創建的代碼 - 它會根據每行中有多少個模塊創建一個「shell」HTML佈局,然後將內容添加到基於哪個模塊應該在那裏。我希望能夠繼續使用該代碼,所以我認爲最好的方法是在構建「shell」之前遍歷數組中的每個元素,如果我沒有內容,則刪除該元素來自陣列。然後,我可以使用新修改的數組來構建「shell」 - 平常我基本上只是在處理它以檢查每個模塊中的內容,並且如果沒有可用的,那麼像該模塊那樣行事從未在初始數組中設置(通過在新數組中刪除它,然後使用它來構建「shell」)。

例如,假設配置被設置爲這樣:

var ROW1 = ['module1']; 
var ROW2 = ['module4', 'module2']; 
var ROW3 = ['module5']; 
var ROW4 = ['module7', 'module3', 'module8']; 

我想通過每個陣列中的每個元素並檢查模塊中的可用內容。假設沒有可用於「module3」和「module5」的內容。我想,然後用這些陣列結束:

var ROW1 = ['module1']; 
var ROW2 = ['module4', 'module2']; 
var ROW3 = ['module7', 'module8']; 

請注意發生了什麼事行 - 因爲「單詞數」已被刪除,從ROW4數組中的元素被轉移到ROW3,然後ROW4被刪除。此外,在新的ROW3(以前稱爲ROW4)中,「module3」被刪除,將「module8」從位置[2]滑動到位置[1]。

所以:

  • 對於具有去除沒有任何內容模塊後剩下的一個或多個元素的任何行,我想保留該行不變,即使只有一個模塊。
  • 對於任何結束時沒有元素剩餘的行,我想將每個連續的行向上移動到前一個數組中,基本上拉出一行並將較低的行向上移動。從這個例子中的HTML應該是這樣的:BEFORE(由配置的要求)

<table> 
    <tr id="row1"> 
    <td colspan="6">[module1]</td> 
    </tr> 
    <tr id="row2"> 
    <td colspan="3">[module4]</td> 
    <td colspan="3">[module2]</td> 
    </tr> 
    <tr id="row3"> 
    <td colspan="6">[module5]</td> 
    </tr> 
    <tr id="row4"> 
    <td colspan="2">[module7]</td> 
    <td colspan="2">[module3]</td> 
    <td colspan="2">[module8]</td> 
    </tr> 
</table> 

AFTER(基於哪些內容是實際可用)

<table> 
    <tr id="row1"> 
    <td colspan="6">[module1]</td> 
    </tr> 
    <tr id="row2"> 
    <td colspan="3">[module4]</td> 
    <td colspan="3">[module2]</td> 
    </tr> 
    <tr id="row3"> 
    <td colspan="3">[module7]</td> 
    <td colspan="3">[module8]</td> 
    </tr> 
</table> 

回想一下, ROW1是一種特殊情況,因爲它不影響其他行。如果內容可用於「module1」(唯一可以進入ROW1的模塊),則ROW1應該保持不變。如果沒有可用的內容,則ROW1可以被刪除,但仍保持原來的ROW2,ROW3和ROW4(即,不將它們每個向上移動一次)。我真的只需要一個解決方案來處理ROW2,ROW3和ROW4,因爲ROW1的邏輯非常簡單。

我是一個初學者/中級JavaScript程序員,並沒有很多陣列經驗。我一直在努力工作幾個小時,但只是不覺得我想要的是一個強大或優雅/緊湊的方法。

如果任何JavaScript大師可以共享此解決方案,我會非常感激!謝謝一堆。

回答

4

首先,將你的行存儲在一個數組中,你的ROW1-ROW4會給你帶來麻煩。

var ROWS = [ 
['module1'], 
['module4', 'module2'], 
['module5'], 
['module7', 'module3', 'module8'] 
]; 

您還想要一種方法來刪除元素。 .splice()內置於數組中,並且非常適合移除元素。

// lets clear out our disabled modules 

var disabledModules = ['module3', 'module5']; 

// quick sample function - yours might check for empty content or whatever else... 
function isDisabled(module) { 
    for (var i=0, test; test=disabledModules[i]; i++) { 
    if (test === module) return true; 
    } 
    return false; 
} 

for(var i=0,row; row=ROWS[i]; i++) { 
    for (var j=0,module; module=row[j]; j++) { 
    // is this module in our disabled modules list? 

    if (isDisabled(module)) { // the module is disabled 
     row.splice(j,1); 
     j--; // so we recheck this point in the array 
    } 
    } 
    if (row.length < 1) { 
    // all items were deleted 
    ROWS.splice(i,1); 
    i--; // so we recheck this point.. 
    } 
} 

// ROWS === [["module1"], ["module4", "module2"], ["module7", "module8"]] 

您的評論詢問了有關使用的for循環語法。這是一個非常快速的方式來循環你知道不會有「假」值的數組。打破一個開並且開啓詳細日誌記錄:

for(
    // Part 1 of for loop: Setup, create two variables, i=0, and row. 
    var i=0,row; 
    // Part 2: The test - when false, loop will exit, gets executed pre-loop every time 
    // Assignment operator returns the value assigned, so row=ROWS[i] will be undefined 
    // (false) when we reach then end of the array. 
    row=ROWS[i]; 
    // Part 3: Post loop - increment i 
    i++) { 

使用這種方法的危險不存在,雖然,如果它的例如數字數組,並且這些數字中的一個是0,則循環將提前退出。另一種方法是這樣寫:

for(var i=0; i<ROWS.length; i++) { 
    var row = ROWS[i]; 
} 
+0

你可以在這裏搶陣列原型的indexOf方法用在瀏覽器中不實現它:https://developer.mozilla.org/Talk:en/Core_JavaScript_1.5_Reference/Global_Objects/Array –

+0

感謝您提醒我(我的全局包含腳本的一部分) - 重寫了使用不同的功能。 – gnarf

+0

非常感謝,gnarf - 這非常有幫助。我感謝你抽出時間。我認爲我處在正確的軌道上 - 我已經開始實現一對嵌套循環,但是如果考慮到刪除數組元素時循環內計數器遞減的影響,我會感到緊張。看起來這畢竟不是問題,但是。 我現在要在我的項目中實現它,如果卡住了,我會添加另一條評論。 順便提一句,它可能是JavaScript 101,但我還沒有看到過用於設置for循環的語法 - 這些操作究竟是什麼? – Bungle