This is a table for operations by javascript | ||
---|---|---|
Home >Web Front-end >JS Tutorial >Pure native js realizes the addition and deletion of tables
The company intern asked me about the addition and deletion operations of the table, which was easily implemented using jQuery. He also asked me how to implement it without using jQuery and only using js.
Faced with this situation, my usual approach is 'don't understand, but support'.
JQuery is used a lot, and people are too lazy, but I still use js to implement this operation. I think the difficulty lies in IE compatibility. . .
If you just want to find the code, you can skip the analysis process. The complete code is attached at the bottom of the article.
The following is the coding process:
HTML structure code
A basic table structure, with some simple styles added, three buttons corresponding to create, clear, and a Reserved.
<!DOCTYPE HTML> <html> <head> <title>table</title> <meta charset='utf-8' /> <style type="text/css"> table.base{ border-collapse:collapse; text-align: center; border: 1px solid black; } table, tr, td, th{ border: 1px solid black; } </style> </head> <body> <div id="main-content"> <table id="main-table" class="base"> <thead> <tr> <th colspan="3">This is a table for operations by javascript</th> </tr> <tr> <th> <input type="button" value="CREATE" id="cp_btn" onclick="createTr()" /> </th> <th> <input type="button" value="CLEAR" id="cl_btn" onclick="clearTrs()" /> </th> <th> <input type="button" value="GUESS" id="cl_btn"/> </th> </tr> </thead> <tbody> </tbody> </table> </div> </body> </html>
Constructor (pseudo constructor)
Considered, create a hidden tr, and perform the creation operation based on this tr. In order not to destroy the overall structure of HTML, it was decided to generate the tr object through js and append it to the page.
In order to perform DOM operations after the page is loaded, place 3f1c4e4b6b16bbbd69b2ee476dc4f83a before 36cc49f0c466276486e50c850b7e4956 at the bottom of the code.
To perform addition and deletion operations based on tbody in the table, you can first declare this global variable
var vTbody = document.getElementById('main-table').getElementsByTagName('tbody')[0] ;
To create an object, you can use the document.createElement method.
Programming in an object-oriented way, first write the constructor (in fact, it is not a standard constructor format), starting from the innermost element.
There may be form elements such as text and button in td, so first create an input constructor function myInput(vId, vClass, vType, vValue, vParent){}
Here is one The compatibility problem is that the IE kernel does not support setAttribute(class, value) and needs to use setAttribute(className, value). Therefore, in order to solve the compatibility problem, you can use
setAttribute(class, value) for FF and Chrome. .
setAttribute(className, value) for IE
Here is another way.className, the code is as follows:
function myInput(vId, vClass, vType, vValue, vParent) { var vInput = document.createElement('input'); if(vId) { vInput.setAttribute('id', vId); } vInput.setAttribute('type', vType); vInput.setAttribute('value', vValue); vInput.className = vClass; if(vParent) { vParent.appendChild(vInput); } }
Then the td object and tr object The constructor is similar, the code is as follows
function myTd(vId, vClass, vChild, vParent) { var vTd = document.createElement('td'); if(vId){ vTd.setAttribute('id', vId); } vTd.className = vClass; if(vChild) { vTd.appendChild(vChild); } if(vParent) { vParent.appendChild(vTd); } return vTd; } function myTr(vId, vClass, vChild, vParent) { var vTr = document.createElement('tr'); if(vId){ vTr.setAttribute('id', vId); } vTr.className = vClass; if(vChild) { vTr.appendChild(vChild); } if(vParent) { vParent.appendChild(vTr); } return vTr; }
New row method createTr()
After the constructor is completed, improve the createTr() method.
The expected tr structure is serial number, text box, and operation button.
Create related objects in sequence. The serial number column needs to be refreshed dynamically, so first set the class name and perform the sorting operation through the method.
function createTr() { var vTr = new myTr(null, null, null, vTbody); //序列td var vTdSeq = new myTd(null, 'seq', null, vTr); //文本框td var vTdText = new myTd(null, null, null, vTr); var vInputText = new myInput(null, 'td-inp-txt', 'text', '', vTdText); //操作按钮td var vTdBtn = new myTd(null, null, null, vTr); var vInputBtnCp = new myInput(null, 'td-inp-btn-cp', 'button', 'COPY', vTdBtn); var vInputBtnDel = new myInput(null, 'td-inp-btn-del', 'button', 'DELETE', vTdBtn); }
Sorting method reSequence()
Create a dynamic sorting method reSequence(). There is a compatibility issue. innerText has no effect under Firefox, so innerHTML is used. The code is as follows
function reSequence() { var vObj = vTbody.getElementsByClassName('seq'); for (var i=0, len=vObj.length; i<len; i++) { vObj[i].innerHTML = i+1; } }
There is a compatibility issue. IE8 and below do not support the getElementsByClassName() method. I found a solution online
if(!document.getElementsByClassName){ document.getElementsByClassName = function(className, element){ var children = (element || document).getElementsByTagName('*'); var elements = new Array(); for (var i=0; i<children.length; i++){ var child = children[i]; var classNames = child.className.split(' '); for (var j=0; j<classNames.length; j++){ if (classNames[j] == className){ elements.push(child); break; } } } return elements; }; }
Trying to add this method to the prototype of Object or HTMLTableSectionElement. Such as
HTMLTableSectionElement.prototype.getElementsByClassName = function(){}
Unfortunately, it is not implemented.
The modified code is
function reSequence() { var vObj = vTbody.getElementsByClassName == null?document.getElementsByClassName('seq', vTbody):vTbody.getElementsByClassName('seq'); for (var i=0, len=vObj.length; i<len; i++) { vObj[i].innerHTML = i+1; } }
In addition to sorting, other operations are required, so we create an init() method to centrally manage the reSequence() methods. In the createTr() method At the end, the init() method is called.
Clear row method clearTrs()
To remove/destroy a DOM object, the first thing that comes to mind is the remove() method. Unfortunately, there are IE browser compatibility issues, so use A simpler way is to execute innerHTML="" on the dom object. The code is as follows
function clearTrs() { vTbody.innerHTML = ''; }
IE8 reports an error, 'Unknown running error'. I checked the following, because the table.innerHTML of IE8 is a read-only attribute, damn it! Change again:
function clearTrs() { while(vTbody.rows.length >0) { vTbody.deleteRow(); } }
Delete row method addBtnDelsListener()
Next, bind the method of deleting the current row to the DELETE button.
In order to solve the compatibility problem, the method given on the Internet is to use the addEventListener and attachEvent methods for different browsers (IE, non-IE) respectively.
I use another solution :
obj.onclick = function(){};
The method body of the anonymous function has learned the lessons learned from the clearTrs() method above and directly uses the deleteRow(index) method.
One thing to note is that the number of rows obtained by thisTr.rowIndex is 2 greater than the current row, because there are two rows in thead. So the current number of indexes = thisTr.rowIndex-vThead.rows.length
The code is as follows:
function addBtnDelsListener() { var vBtnDels = vTbody.getElementsByClassName == null?document.getElementsByClassName('td-inp-btn-del', vTbody):vTbody.getElementsByClassName('td-inp-btn-del'); for (var i=0, len=vBtnDels.length; i<len; i++) { vBtnDels[i].onclick = function() { var vTr = this.parentElement.parentElement; vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName('thead')[0].rows.length); reSequence(); }; } }
After performing the deletion operation, reorder through the reSequence() method.
At the same time, add the addBtnDelsListener() method to the init() method.
Copy line method addBtnCpsListener()
Let’s look at the COPY button again. The method of adding event listeners is the same as above.
If innerHTML is not read-only, you can createElement a tr element and then newTr.innerHTML=thisTr.innerHTML,
For compatibility, some changes must be made.
In fact, copying can be regarded as creating a new one. The only difference is that the content of the text input box of the new row must be equal to the copied row.
That’s easy. I can call the createTr() method first, and then set the value of the text box in the last element lastChild to be equal to the copied row.
The idea is there, the code is as follows:
function addBtnCpsListener() { var vBtnCps = vTbody.getElementsByClassName == null?document.getElementsByClassName('td-inp-btn-cp', vTbody):vTbody.getElementsByClassName('td-inp-btn-cp'); for (var i=0, len=vBtnCps.length; i<len; i++) { vBtnCps[i].onclick = function() { createTr(); var vNewTr = vTbody.lastChild; var vTr = this.parentElement.parentElement; vNewTr.getElementsByClassName == null?document.getElementsByClassName('td-inp-txt', vNewTr)[0].value = document.getElementsByClassName('td-inp-txt', vTr)[0].value:vNewTr.getElementsByClassName('td-inp-txt')[0].value = vTr.getElementsByClassName('td-inp-txt')[0].value; } } }
Optimization and modification
Perform some optimization and modification work:
var elements = new Array();
Modify to: var elements = [];
Reason: It is better to use [] for the array
Change vBtnDels[i].onclick = function() {# in the addBtnDelsListener method ##
修改为:vBtnDels[i].onclick = delTr;
外部新创建一个函数
function delTr() { var vTr = this.parentElement.parentElement; vTbody.deleteRow(vTr.rowIndex-vTbody.parentNode.getElementsByTagName('thead')[0].rows.length); reSequence(); }
原因:Don't make functions within a loop.
同理,将addBtnCpsListener中的vBtnCps[i].onclick = function() {
修改为:vBtnCps[i].onclick = copyTr;
外部新创建一个函数
<pre code_snippet_id="139791" snippet_file_name="blog_20140103_15_6784659" name="code" class="javascript"> function copyTr() { createTr(); var vNewTr = vTbody.lastChild; var vTr = this.parentElement.parentElement; vNewTr.getElementsByClassName === null? document.getElementsByClassName('td-inp-txt', vNewTr)[0].value = document.getElementsByClassName('td-inp-txt', vTr)[0].value: vNewTr.getElementsByClassName('td-inp-txt')[0].value = vTr.getElementsByClassName('td-inp-txt')[0].value; }
将copyTr()方法中的?:格式修改为if else函数。
修改为:
function copyTr() { createTr(); var vNewTr = vTbody.lastChild; var vTr = this.parentElement.parentElement; if(vNewTr.getElementsByClassName) { vNewTr.getElementsByClassName('td-inp-txt')[0].value = vTr.getElementsByClassName('td-inp-txt')[0].value; } else { document.getElementsByClassName('td-inp-txt', vNewTr)[0].value = document.getElementsByClassName('td-inp-txt', vTr)[0].value; } }
原因:?:预期返回值应该是一个变量or函数,而不应该是一个表达式操作。
有一点需要注意:js最佳实现经常看到要使用===替换==。但是本示例中的==null,如果替换成===null会在ie8一下版本中出现问题。
完整代码
至此,一个完全基于原生JavaScript,并且兼容至IE6的table增删完成了。
还是想吐槽一下,如果不兼容IE10以下的版本,可以节省50%的代码。如果使用jQuery,又可以节省50%的代码。对于实用主义的我而言,这一过程备受煎熬。不过还是从中有所收益的(违心。。)
以下为完整代码:
table
This is a table for operations by javascript
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持PHP中文网!
更多纯原生js实现table表格的增删相关文章请关注PHP中文网!