Django前端HTML通过JS实现表格可编辑,动态添加行,回车完成新建文件夹

时间:2021-07-18 13:45:45

版本:

django:2.1.7

python:3.7

功能描述:

点击“新建文件夹”按钮,在table的末尾增加一行;单击页面的新增行,使单元格td变成可编辑状态;输入内容后,当单元格失去焦点时,保存输入的内容;回车后通过AJAX提交后台完成新建文件夹。

HTML部分代码,id="table2"和EditType="TextBox"后面需要用到。

<button class="btn btn-default" type="button" id="create_dir" name="create_dir" value="create_dir" style='margin-left:10px;margin-right:10px;color:rgb(60, 141, 188);' onclick="AddRow($('#table2')[0],1)">新建文件夹</button>

<table id="table2" class="table table-hover" style="overflow: auto;" >
<tr>
<td class='th3' EditType="TextBox">
<img src="/static/img/file4_24.ico">&nbsp;&nbsp;&nbsp;
{% if fileinfo.search_flag == 0 %}
{{ fileinfo.file_name }}
{% else %}
{{ fileinfo.file_path }}
{% endif %}
</td>
</tr>

样式表格td部分,新增行改一下:

{% block style %}
<style>
td{
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #CCCCCC;
}
.EditCell_TextBox {
width: 90%;
border:1px solid #0099CC;
}
.EditCell_DropDownList {
width: 90%;
}
</style>
{% endblock %}

JS部分,也是最关键的一部分:

{% block javascripts %}
<script>
/**
* JS实现可编辑的表格
* 用法:EditTables(tb1,tb2,tb2,......);
**/
//添加行
function AddRow(table, index){
var lastRow = table.rows[table.rows.length-1];
var newRow = lastRow.cloneNode(true);
//计算新增加行的序号,需要引入jquery 的jar包
var startIndex = $.inArray(lastRow,table.rows);
var endIndex = table.rows;
 table.tBodies[0].appendChild(newRow);
// newRow.cells[0].innerHTML=endIndex-startIndex;
newRow.cells[1].innerHTML="新建文件夹";
// <img src='/static/img/folder_24.ico'>&nbsp;&nbsp;&nbsp;
// console.log(newRow.cells[0].innerHTML);
SetRowCanEdit(newRow);
return newRow;
}
function SetRowCanEdit(row){
// console.log(row.cells.length);
for(var j=0;j<row.cells.length; j++){ //如果当前单元格指定了编辑类型,则表示允许编辑
var editType = row.cells[j].getAttribute("EditType");
if(!editType){
//如果当前单元格没有指定,则查看当前列是否指定
editType = row.parentNode.rows[0].cells[j].getAttribute("EditType");
}
if(editType){
//新建后直接处于可编辑状态
EditCell(row.cells[j]);
row.cells[j].onclick = function (){
EditCell(this);
}
}
}
}
//设置指定单元格可编辑
function EditCell(element, editType){
var editType = element.getAttribute("EditType");
if(!editType){
//如果当前单元格没有指定,则查看当前列是否指定
editType = element.parentNode.parentNode.rows[0].cells[element.cellIndex].getAttribute("EditType");
} switch(editType){
case "TextBox":
CreateTextBox(element, element.innerHTML);
break;
default:
break;
}
}
//为单元格创建可编辑输入框
function CreateTextBox(element, value){
//检查编辑状态,如果已经是编辑状态,跳过
var editState = element.getAttribute("EditState");
if(editState != "true"){
//创建文本框
var textBox = document.createElement("INPUT");
textBox.type = "text";
textBox.className="EditCell_TextBox"; // value = "新建文件夹"
//设置文本框当前值
if(!value){
value = element.getAttribute("Value");
}
textBox.value = value; //设置文本框的失去焦点事件
textBox.onblur = function (){
CancelEditCell(this.parentNode, this.value);
}
//向当前单元格添加文本框
ClearChild(element);
element.appendChild(textBox);
textBox.focus();
textBox.select(); //改变状态变量
element.setAttribute("EditState", "true");
element.parentNode.parentNode.setAttribute("CurrentRow", element.parentNode.rowIndex);
//回车事件
textBox.onkeypress = function(event){
// console.log(element.innerHTML);
// console.log(this.value);
if (event.keyCode == "13"){
$.ajax({
url:"/create_dir?dir_name="+this.value,
// url:"{% url 'upload_files' %}",
type:"GET",
data:'', //
processData:false,
contentType:false,
success:function (data) {
// console.log(data)
// alert("创建文件夹完成!");
history.go(0);
}
});
}
} }
}
//取消单元格编辑状态
function CancelEditCell(element, value, text){
element.setAttribute("Value", value);
if(text){
element.innerHTML = text;
}else{
element.innerHTML = value;
}
element.setAttribute("EditState", "false");
//检查是否有公式计算
CheckExpression(element.parentNode);
}
//清空指定对象的所有字节点
function ClearChild(element){
element.innerHTML = "";
}
//提取指定行的数据,JSON格式
function GetRowData(row){
var rowData = {};
for(var j=0;j<row.cells.length; j++){
name = row.parentNode.rows[0].cells[j].getAttribute("Name");
if(name){
var value = row.cells[j].getAttribute("Value");
if(!value){
value = row.cells[j].innerHTML;
}
rowData[name] = value;
}
}
//alert("ProductName:" + rowData.ProductName);
//或者这样:alert("ProductName:" + rowData["ProductName"]);
return rowData;
} //检查当前数据行中需要运行的字段
function CheckExpression(row){
for(var j=0;j<row.cells.length; j++){
expn = row.parentNode.rows[0].cells[j].getAttribute("Expression");
//如指定了公式则要求计算
if(expn){
var result = Expression(row,expn);
var format = row.parentNode.rows[0].cells[j].getAttribute("Format");
if(format){
//如指定了格式,进行字值格式化
row.cells[j].innerHTML = formatNumber(Expression(row,expn), format);
}else{
row.cells[j].innerHTML = Expression(row,expn);
}
}
}
} //计算需要运算的字段
function Expression(row, expn){
var rowData = GetRowData(row);
//循环代值计算
for(var j=0;j<row.cells.length; j++){
name = row.parentNode.rows[0].cells[j].getAttribute("Name");
if(name){
var reg = new RegExp(name, "i");
expn = expn.replace(reg, rowData[name].replace(/\,/g, ""));
}
}
return eval(expn);
} $(function() {
var tabProduct = document.getElementById("table2");
// 设置表格可编辑
// 可一次设置多个,例如:EditTables(tb1,tb2,tb2,......)
// EditTables(tabProduct);
// console.log('test!!!!!!!!!!!!!!');
}); </script>
{% endblock %}

JS部分根据自己的需求优化了一下:

1.EditTables()设置多个表格不要了,我只需要编辑新增行就行了。而且innerHTML会被看到td中代码。

2.tabProduct获取自己table的id。

3.新增按钮onclick="AddRow($('#table2')[0],1)",参数为自己表对象,注意[0]。AddRow中可以改新增行默认内容,我的为“新建文件夹”。

4.SetRowCanEdit()函数中增加如下代码,使新增行后直接处于可编辑状态,也可以单击进入编辑状态。

EditCell(row.cells[j]);

5.CreateTextBox()中获取用户输入的值,增加捕获键盘回车事件后,通过AJAX提交后台:

textBox.onkeypress = function(event){
if (event.keyCode == "13"){
$.ajax({
url:"/create_dir?dir_name="+this.value,
type:"GET",
data:'', //
processData:false,
contentType:false,
success:function (data) {
// alert("创建文件夹完成!");
history.go(0);
}
});
}
}

6.python后台实现新建文件夹,AJAX异步处理后返回直接更新目录,不需要刷新:

def create_dir(request):
if request.method == 'GET':
dir_name = request.GET.get('dir_name')
print('create_dir:'+dir_name)
path = os.path.join(current_path,dir_name)
while os.path.exists(path):
path += '-副本'
os.makedirs(r'%s'%path)
return HttpResponse(path)
else:
return HttpResponse("error")

7.这样空表格的时候新建行还是会出问题,因为是克隆最后一行新建的,所有空表格时需要自己动态的新建一个行,DataTable.js空表格时会有提示“空表格”的一行,所有先deleteRow删除行,再insertRow插入行。最后创建可编辑单元,和单机触发。

代码如下:

  function AddRow(table, index){
var lastRow = table.rows[table.rows.length-1];
var newRow = lastRow.cloneNode(true);
//计算新增加行的序号,需要引入jquery 的jar包
if(newRow.cells.length > 1){
newRow.cells[1].innerHTML="新建文件夹";
  table.tBodies[0].appendChild(newRow);
SetRowCanEdit(newRow);
}else{
table.deleteRow(1);
newRow = table.insertRow(1);
newRow.insertCell(0).innerHTML = "<td><input type='checkbox'/></td>";
newRow.insertCell(1).innerHTML = "<td>新建文件夹</td>";
newRow.insertCell(2).innerHTML = "<td>-</td>";
newRow.insertCell(3).innerHTML = "<td>-</td>";
newRow.insertCell(4).innerHTML = "<td>-</td>";
newRow.insertCell(5).innerHTML = "<td>-</td>";
newRow.insertCell(6).innerHTML = "<td>-</td>";
newRow.insertCell(7).innerHTML = "<td>-</td>";
CreateTextBox(newRow.cells[1],newRow.cells[1].innerHTML);
newRow.cells[1].onclick = function (){
CreateTextBox(this,this.innerHTML);
}
}
return newRow;
}

8.最后,效果如下:

Django前端HTML通过JS实现表格可编辑,动态添加行,回车完成新建文件夹