2014-01-30 37 views
0

我有一張桌子,我想在每行下面添加一個可隱藏/可顯示的面板,以獲得比表格行更合適的更多控件和信息。我首先想到的是爲每個原始TR兄弟TR,並把一個單一的TD內以適當的合併單元格:信息面板下面TRs

<tbody> 
    <tr> 
    <td>...</td> 
    ... 
    <tr> 
    <tr class="tablesorter-childRow"> 
    <td colspan="4">...</td> 
    </tr> 
    ... 
</tbody> 

每個原始行將會有一個按鈕,將隱藏()或顯示()對應的tr,並且子行中的td將包含所有不需要正常顯示的額外控件。

這會變得棘手,因爲我使用d3構建表格,並且d3不喜歡每個數據元素的多個元素(請參閱this stack postthis other thing)。

這也很棘手,因爲我使用的是tablesorter,它使用tds中的值對錶客戶端進行排序,所以原始數據必須保持表格格式。 (它可以使用css類「tablesorter-childRow」保持行對。)我也不相信我可以有多個tbody,因爲它們沒有與行一起排序 - 每個tbody的行都被排序。

我想過使用jquery在每個原始tr之後插入一個tr,但是當某些更改(因爲數據無法正確連接)時,d3不會正確更新表格,以及我使用的原因d3是因爲它使得構建許多dom元素更容易(至少對我而言)。

所以,提問時間:我還能怎麼創造這個面板

  1. 移動與原表中的行
  2. 不影響排序
  3. 可以顯示或隱藏?

回答

0

如果你想讓兩個兄弟元素共享相同的數據,d3中最簡單的方法就是將它們歸爲一個父元素。您爲父元素分配數據,然後當您創建其兩個子元素(不分配數據)時,它們都會繼承父數據。

在SVG中,通常的父元素是<g>。出於您的目的,自然父元素將爲<tbody>,可用於對錶格行進行分組。 但是,您必須修改您正在使用的表格排序代碼,以排序單個<tbody>元素而不是單個行。

唯一的其他選擇是動態設置信息行的內容,並要表現出來,類似工具提示的例子有多少工作,每次將其插入到正確的位置:它是相同的提示,只是隨着新數據移動。如果您使用d3在表格行上附加事件處理程序,它會將點擊行的數據對象傳遞給事件處理函數,因此您可以使用該數據填充信息內容而不創建數據 - 加入。在點擊<tr>元素後插入信息行,可以使用d3's insert()函數,但格式不理想;最好使用plain Javascript或JQuery。在運行排序之前,您還必須刪除信息行。

tableRows.on("click", showInfo); 
/* remember to give your rows a tabIndex, so that keyboard users can 
    trigger the click action */ 

/* Create the persistent info box */ 
var infoRow = d3.select(document.createElement("tr")) 
      //create a new <tr>, unattached to the document 
       .attr("class", "infoBox";//set class to allow unique formatting 

infoRow.append("td") //add a <td> within the <tr> 
     .attr("colspan", colNames.length); //set to fill all columns 


/* Show the info row for a clicked element */ 
function showInfo(d,i) { 

    /* Hide info box if currently shown */ 
    infoRow.style("display", "none"); 

    /* Set content to match clicked row */ 
    infoRow.select("td") //select the <td> element 
      .html(/* create html from the d object 
        you don't need a function(d), just 
        concatenate the string. */) 

    /* Insert the row in the correct place. 
     This will automatically remove it from any current location */ 
    this.parentNode.insertBefore(infoRow, this.nextSibling); 
     //"this" is the tableRow object that received the click event 

    infoRow.style("display", null); 
     //revert to default display setting (i.e. table-row) 
} 

function sort(/*parameters*/) { 
    infoRow.remove(); 
    //remove the infoRow element from the document, 
    //so it only exists as a Javascript object again 

    /* Run your sort code */ 
}