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

版本:

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.最后,效果如下:

posted @ 2019-07-13 17:02  Andy_Yin  阅读(3354)  评论(0编辑  收藏  举报