版本:
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"> {% 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'>
// 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.最后,效果如下:

