2012-11-13 78 views
2

標題不是很具描述性,但我找不到更好的。隨意編輯它。如何在JavaScript中實現「添加新項目」功能?

基本上就是我要找的是做的最好方法如下:

add new item

當用戶點擊「添加新項」,新行被加上張玉峯,文本框,像上面一樣下降。我能想到的選項如下:

  • 在JavaScript代碼中對HTML進行硬編碼。這顯然是一個可怕的醜陋解決方案。
  • 從DOM節點(或jQuery對象)組裝HTML。這也非常醜陋。
  • 使用客戶端模板系統。我曾經使用過其中之一,這很奇怪(它使用<script language="html">標籤來定義模板)。
  • 製作臨時的客戶端「模板」並用CSS以某種方式隱藏它。
  • 發出一個AJAX請求來獲取HTML。這很慢並且不必要地使用服務器資源。

你有什麼建議?我對上述任何解決方案都不完全滿意。

+0

如果使用jQuery,或者你想要一個純粹的JavaScript解決方案,這有什麼關係嗎? –

+0

克隆最後一行,修改'id's(如果有)並追加到當前最後一行的父級。 –

+0

@BradChristie:我更喜歡jQuery。 –

回答

1

假設超級簡單的方法,並且您的格式是一個表:

<table> 
    <tr> 
     <td><input type="text" name="item_name" placeholder="item name" /></td> 
     <td><select name="item_type"><option value="" selected="selected">Type</option></select></td> 
    </tr> 
    <tr> 
     <td><input type="text" name="item_name" placeholder="item name" /></td> 
     <td><select name="item_type"><option value="" selected="selected">Type</option></select></td> 
    </tr> 
    <tr> 
     <td colspan="2" id="add">+ Add new item</td> 
    </tr> 
</table> 

您可以使用以下方法:

$('#add').on('click',function(e){ 
    var $this = $(this); 
    var $newRow = $this.closest('table').find('tr:first').clone(); 
    $newRow.find(':input').val(''); 
    $newRow.insertBefore($this.parent()); 
}); 

拆毀了

  1. 我們給最後一個項目的ID,以便更容易綁定點擊事件。
  2. 使用jQuery和綁定click事件到ID其中:
    • 抓鬥我們中單擊當前表($this.closest('table')
    • 將查找表和副本中的第一排它(.clone()
    • 除去任何填充值可以存在(.find(':input').val('')
    • 追加略高於這個新克隆的行表中的「添加新的項目」行($newRow.insertBefore(...)

您也可以採用模板方法,但這真的取決於您以及您對輸出的控制程度。

+0

謝謝。這是非常可維護的(HTML在打破之前可能會發生很多變化),並且也是輕量級的。 –

+1

雖然我認爲我會使用包裝div而不是表格:) –

+0

我也喜歡如何在包含jQuery對象的變量前添加'$'。這是一件普通的事情嗎? –

0

從字符串中插入HTML到DOM是最有效的方法。除非你一次插入數百個,否則它並不重要。

+0

也許它是有效的,但我不會在一秒鐘內完成數千次插入,因此可讀性和可維護性對我來說更爲重要。不過謝謝。 –

1

如果您已經在頁面上使用了像jQuery或sencha這樣的框架,那麼您也可以使用它。

否則,我會保持儘可能簡單。這看起來不像是一個非常重要的核心功能,所以不要創建需要額外的https請求甚至整個庫的東西。克隆或生成HTML可能看起來不優雅,但它會是:

  • 快速實現
  • 容易閱讀,因此,易於調試
  • 浪費資源很少,並且速度極快
  • 穩定
  • 不需要服務器端代碼或額外的HTTP請求
  • 如果需要
這將是很容易改變以後實施

不要創造一些過分矯枉過正的東西,因爲這很瑣碎。

1

雖然我知道你已經有一個公認的答案,我想我會提供一個簡單的實現相同的JavaScript的方式:

function closest(el, tag) { 
    if (!el || !tag) { 
     return false; 
    } 
    else { 
     var curTag = el.tagName.toLowerCase(); 
     return curTag == tag.toLowerCase() && curTag !== 'body' ? el : closest(el.parentNode, tag); 
    } 
} 

function addRow(el) { 
    if (!el) { 
     return false; 
    } 
    else { 
     var tr = closest(el, 'tr').previousElementSibling, 
      newRow = tr.cloneNode(true); 
     tr.parentNode.insertBefore(newRow, tr.nextSibling); 
    } 
} 

document.getElementById('add').onclick = function() { 
    addRow(this); 
}​ 

JS Fiddle demo

修訂上述一點,添加一個簡單的墊片,以應付不實現previousElementSibling這些瀏覽器:

function closest(el, tag) { 
    if (!el || !tag) { 
     return false; 
    } 
    else { 
     var curTag = el.tagName.toLowerCase(); 
     return curTag == tag.toLowerCase() && curTag !== 'body' ? el : closest(el.parentNode, tag); 
    } 
} 

function prevElementSiblingShim(el) { 
    if (!el) { 
     return false; 
    } 
    else { 
     var prevSibling = el.previousSibling; 
     return prevSibling.nodeType == 1 ? prevSibling : prevElementSiblingShim(prevSibling); 
    } 
} 

function addRow(el) { 
    if (!el) { 
     return false; 
    } 
    else { 
     var par = closest(el, 'tr'), 
      tr = par.previousElementSibling || prevElementSiblingShim(par), 
      newRow = tr.cloneNode(true); 
     tr.parentNode.insertBefore(newRow, tr.nextSibling); 
    } 
} 

document.getElementById('add').onclick = function() { 
    addRow(this); 
}​ 

參考文獻:

+0

真棒,謝謝! –

相關問題