zoukankan      html  css  js  c++  java
  • 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.最后,效果如下:

  • 相关阅读:
    this指向问题
    b继承a的函数
    如何解决跨域问题
    事件冒泡和阻止事件冒泡
    Spring5(二)——IOC
    MySQL基础(四)——
    MySQL基础(二)——常用命令
    MySQL基础(一)——入门
    Linux(二)——常用命令
    Linux(一)——简介
  • 原文地址:https://www.cnblogs.com/AndrewYin/p/11181305.html
Copyright © 2011-2022 走看看