而輔助這些互動功能的語法均需要使用 CSS 及 Javascript
在 Javascript 方面,由於得到 jQuery 的跨瀏覽器語法,在開發 Javascript 新功能時可以不再考慮瀏覽器的問題
可能不少網頁設計者都會遇過類似狀況
輸入文字欄位數量不夠,需要新加入一定數量的輸入文字爛位,但究竟多少才足夠卻不是設計師可以控制
最理想的狀況是由使用者在需要增加資料,增加輸入文字爛位
1 2 3 4 5 6 7 8 9 10 11 12 | < table > < tbody > < tr > < td >< input type = "text" /></ td > < td >< input type = "button" value = "+" /></ td > < td >< input type = "button" value = "-" /></ td > < td >< input type = "button" value = "▼+" /></ td > < td >< input type = "button" value = "▲" /></ td > < td >< input type = "button" value = "▼" /></ td > </ tr > </ tbody > </ table > |
當 - 被按下後,選定的列會被移除
當 ▼+ 被按下後,複製選定的列於下一列
當 ▲ 被按下後,選定的列向上移
當 ▼ 被按下後,選定的列向下移
網上有不少使用 jQuery 的教學達成這種操作
而這裡則是使用 DOM 的方式達成這種操作
先利用 Javascript 的 Prototype 補充原來的 Javascript 的不足之處
Prototype Javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | // DOM 的 Node 有 nextSibling 及 previousSibling 屬性 // 來獲取 Node 的上一個 Node 及 下一個 Node ,當沒有 Node 時,會得到 null // 但 *Sibling 可能比較難記,可以自行增加 nextNode() 及 previousNode() 功能 // (Java 來說會以功能操作比較熟習) Node.prototype.nextNode = function (){ return this .nextSibling; } Node.prototype.previousNode = function (){ return this .previousSibling; } // 但上一個 Node 或下一個 Node 不一定是 Tag // 對於 DOM Tag 與 Tag 之間的空白字元都是 Node 只是 nodeType 的不同 // Tag 的 nodeType 為 1 Node.prototype.nextTag = function (){ var node = this .nextNode(); while (node != null && node.nodeType != 1){ node = node.nextNode(); } return node; } Node.prototype.previousTag = function (){ var node = this .previousNode(); while (node != null && node.nodeType != 1){ node = node.previousNode(); } return node; } // 獲取第一及最後的 Tag Node.prototype.firstTag = function (){ var node = this .firstChild; while (node != null && node.nodeType != 1){ node = node.nextNode(); } return node; } Node.prototype.lastTag = function (){ var node = this .lastChild; while (node != null && node.nodeType != 1){ node = node.previousNode(); } return node; } // DOM 的 Node 只有 insertBefore 功能卻沒有 insertAfter 功能 // 可以自行編寫 insertAfter 來補足功能 Node.prototype.insertAfter = function (new_node, existing_node){ if (new_node instanceof Node){ existing_node.parentNode.insertBefore(new_node, existing_node.nextNode()); } } // 讓兩個 DOM Node 的位置交換 Node.prototype.swap = function (node){ if (node instanceof Node){ var parent = this .parentNode; parent.insertBefore(node.cloneNode( true ), this ); parent.insertBefore( this .cloneNode( true ), node); parent.removeChild( this ); parent.removeChild(node); } } // 自編 insertRowBefore 及 insertRowAfter 功能 // 將新的 列 新增至 當前列 的 前 或 後 HTMLTableRowElement.prototype.insertRowBefore = function (row){ if (row instanceof HTMLTableRowElement){ this .parentNode.insertBefore(row, this ); } } HTMLTableRowElement.prototype.insertRowAfter = function (row){ if (row instanceof HTMLTableRowElement){ this .parentNode.insertAfter(row, this ); } } |
Javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | function add_row(input){ var td = input.parentNode; var tr = td.parentNode; var tx = tr.parentNode; var t_tr = tx.rows[0].cloneNode( true ); t_tr.removeAttribute( 'style' ); tr.insertRowAfter(t_tr); } function copy_row_input_value(tr1, tr2){ for ( var i = 0; i < tr1.cells.length; i++){ var element = tr1.cells[i].firstChild; if (element instanceof HTMLInputElement){ if (element.type == 'radio' || element.type == 'checkbox' ){ tr2.cells[i].firstChild.checked = element.checked; } else { tr2.cells[i].firstChild.value = element.value; } } else if (element instanceof HTMLSelectElement){ tr2.cells[i].firstChild.selectedIndex = element.selectedIndex; } else if (element instanceof HTMLTextAreaElement){ tr2.cells[i].firstChild.innerHTML = element.innerHTML; } } } function copy_row(input){ var td = input.parentNode; var tr = td.parentNode; var tx = tr.parentNode; var t_tr = tx.rows[0].cloneNode( true ); t_tr.removeAttribute( 'style' ); tr.insertRowAfter(t_tr); copy_row_input_value(tr, t_tr); } function delete_row(input){ var td = input.parentNode; var tr = td.parentNode; var tx = tr.parentNode; if (tx.rows.length <= 2){ add_row(input); } tx.removeChild(tr); } function move(input, direction){ var td = input.parentNode; var tr = td.parentNode; var tx = tr.parentNode; var t_tr = tr.cloneNode( true ); copy_row_input_value(tr, t_tr); if (tr != tx.firstTag().nextTag() && direction == 'up' ){ tx.insertBefore(t_tr, tr.previousTag()); tx.removeChild(tr); } else if (tr != tx.lastTag() && direction == 'down' ){ tx.insertAfter(t_tr, tr.nextTag()); tx.removeChild(tr); } } function move_up(input){ move(input, 'up' ); } function move_down(input){ move(input, 'down' ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | < table > < tbody > < tr style = "display: none;" > < td >< input type = "text" /></ td > < td >< input type = "button" value = "+" onclick = "add_row(this);" /></ td > < td >< input type = "button" value = "-" onclick = "delete_row(this);" /></ td > < td >< input type = "button" value = "▼+" onclick = "copy_row(this);" /></ td > < td >< input type = "button" value = "▲" onclick = "move_down(this);" /></ td > < td >< input type = "button" value = "▼" onclick = "move_up(this);" /></ td > </ tr > < tr > < td >< input type = "text" /></ td > < td >< input type = "button" value = "+" onclick = "add_row(this);" /></ td > < td >< input type = "button" value = "-" onclick = "delete_row(this);" /></ td > < td >< input type = "button" value = "▼+" onclick = "copy_row(this);" /></ td > < td >< input type = "button" value = "▲" onclick = "move_down(this);" /></ td > < td >< input type = "button" value = "▼" onclick = "move_up(this);" /></ td > </ tr > </ tbody > </ table > |
另外由於 input, select, textarea 等 表單元素 不會複製由用戶輸入的 value, checked, selected, innerHTML 等資料
複製列時需要連同 value, checked, selected, innerHTML 等資料一拼複製才能達至複製效果
以下是示範
這種方法的可取之處是不需要使用 id, class 之類的 CSS Selector 達到效果
沒有留言 :
張貼留言