简易表格编辑器
SMMS有個建表工具,嘗試使用HTML模仿出一個簡單的做為練習.
截圖:
?
一.實現SMMS建表工具的操作
二.實現思路:
1.DOM結構使用div(行)span(列) <div><span></span><span></span>...</div>
2.每個span上設置tabindex=0,當獲得焦點時,在其內生成表單元素.input select?textarea等等.失去焦點時,將值取出來寫到span內.
3.給input設定onkeydown事件,方向鍵切換臨近單元格
三.實現過程中:
在實現TAB時費了不少功夫,按tab時,總是不能按預想的那樣移到前一個或者后一個列上.在向span中加入了表單元素后,就更加混亂.后來發現在每個span上tabindex=0這個屬性,由于值一樣,所以tab就按相臨的去找.
當span得到焦點后,會向其內生成一個表單元素.表單元素上綁定失去焦點事件blue和keydown事件.blue用于將表單元素的值取出,然后寫到span中.這里有個細節就是,span得到焦點后,要將tabindex=-1,即按tab時,不能得到焦點.如果不這樣做,那么span處于編輯狀態后,按tab就移動不了.因為它會移動到span上,而span的得到焦點事件又是在其內生成表單.這樣就形成一個死循環.所以當span得到焦點后,需要將tabindex=-1,然后在該 span內的表單元素的失去焦點事件上再tabindex=0.這樣就實現了焦點順序的正確.不會因為新生成了表單元素而亂(表單元素默認能獲得焦點).
按上下方向鍵盤切換到上下行的同列,這個較簡單,取得當前事件span的列索引,然后找到上下行的同列span讓它獲得焦點.注意是否有上下行.
按左右方向鍵切換到同行臨近列.如果是輸入狀態的文本框則判斷光標位置,如果在最左并且按左方向,則移動.同理按右方向鍵也一樣.如果是select框,則直接移動到臨近.取消默認行為.textarea沒做此功能.
四.主要代碼
.field-table-box {border-top: 1px solid #ccc;border-left: 1px solid #ccc; } .field-rows{ height:300px;overflow-y:auto; } .field-form-control {border: none;width: 100%;height: 100%;outline:none;/*用谷歌瀏覽器時:如果元素得到焦點.會默認有個藍色邊框.加這個可以去掉.(EDGE,FF沒這問題)*/ }.field-form-control:focus {background-color: #75e0f5;border:none;}.field-col-title, .field-col {display: inline-block;font-size: 14px;height: 24px;line-height: 24px;text-align: center;vertical-align: top;border-right: 1px solid #ccc;border-bottom: 1px solid #ccc;outline:none; }.field-col {color: #444; } .field-col.editinfo {height: 200px;line-height: 200px; }.field-col.pk {cursor: crosshair;color: orangered;}.field-col-title.pk, .field-col.pk {width: 40px;}.field-col-title.name, .field-col.name {width: 140px;}.field-col-title.type, .field-col.type {width: 140px;}.field-col-title.len, .field-col.len, .field-col-title.len2, .field-col.len2 {width: 60px;}.field-col-title.dval, .field-col.dval {width: 120px;}.field-col-title.info, .field-col.info {width: 180px;}.field-col.info{} .field-form-control.info {width: 100%; }.field-col-title.delrow, .field-col-title.moverow, .field-col-title.moverow, .field-col-title.insertrow {width: 40px; }.field-col.delrow, .field-col.moverow-down, .field-col.moverow-up, .field-col.insertrow {font-size: 0;width: 40px;cursor: pointer; }.field-col.delrow:hover, .field-col.moverow-down:hover, .field-col.moverow-up:hover, .field-col.insertrow:hover {font-size: 16px; font-weight: 600;}.field-col.delrow {color: orangered; } .field-col.delrow:active{color: #fff;background-color: orangered; } .field-col.moverow-up, .field-col.moverow-down {color: #999; }.field-col.moverow-up:active {color: #fff;background-color: blue;}.field-col.moverow-down:active {color: #fff;background-color: green;}.field-col.insertrow {color: #4679ca; }.field-col.insertrow:active {color: #fff;background-color: #000;} 樣式 <div class="field-table-box" id="field_table_box"><div class="field-table-cols"><h5 class="field-col-title pk">PK</h5><h5 class="field-col-title name">列名</h5><h5 class="field-col-title type">數據類型</h5><h5 class="field-col-title len">長度</h5><h5 class="field-col-title len2">精度</h5><h5 class="field-col-title dval">默認值</h5><h5 class="field-col-title info">列說明</h5><h5 class="field-col-title moverow">上移</h5><h5 class="field-col-title moverow">下移</h5><h5 class="field-col-title insertrow">插行</h5><h5 class="field-col-title delrow">刪</h5></div> </div><template id="tpl_fieldrow"><div class="fieldrow"><span class="field-col pk noselect" onclick="onClick_SetPk(this)" onkeyup="onkeyup_SetPk(event,this)" tabindex="0"></span><span class="field-col name" onfocus="fieldCol_focus_toEdit(this)" tabindex="0"></span><span class="field-col type" onfocus="fieldColType_toSelect(this)" tabindex="0" val="1">字符串</span><span class="field-col len" onfocus="fieldCol_focus_toEdit(this)" tabindex="0">20</span><span class="field-col len2" onfocus="fieldCol_focus_toEdit(this)" tabindex="0">2</span><span class="field-col dval" onfocus="fieldCol_focus_toEdit(this)" tabindex="0">NULL</span><span class="field-col info" onfocus="fieldCol_focus_info(this)" tabindex="0"></span><span class="field-col moverow-up noselect" onclick="fieldColOp_click_moveRow(this)">▲</span><span class="field-col moverow-down noselect" onclick="fieldColOp_click_moveRow(this)">▼</span><span class="field-col insertrow noselect" onclick="fieldColOp_click_insertRow(this)">☨</span><span class="field-col delrow noselect" onclick="fieldCopOp_click_delRow(this)">✕</span></div> </template> <template id="tpl_fieldcol_type_select"><select class="field-form-control" onblur="fieldType_select_blur(this)" onkeydown="fieldType_select_keydown(event,this)"><option value="1">字符串</option><option value="2">整數</option><option value="3">小數</option><option value="4">時間</option></select> </template> html /* 關于列的編輯功能模仿了SMMS工具的建表功能 例如:點擊某一個列名,它就會變成可編輯的,實現上是在點擊后,套了一個INPUT框 */ $(function () {refreshEditStatus(); }) // 編輯列之后刷新編輯區域狀態 function refreshEditStatus() {// 自動增加新的編輯行 addRowTpl();// 說明textarea框或處于編輯時的放大狀態,此處還原$('.field-col').removeClass('editinfo'); } // 增加一行到制表工具中:如果沒新行加入(列名為空視為有新行),否則不加入 function addRowTpl() {var hasNewRow = false;$('#field_table_box').find('.field-col.name').each(function (){if (String.IsNullOrWhiteSpace($(this).html())){hasNewRow = true;return false;}})if (hasNewRow == false)$('#field_table_box').append($('#tpl_fieldrow').html()); } // 主鍵列: 按空格時,按上下鍵時 function onkeyup_SetPk(event, thisobj) {var e = event || window.event;//console.log(e.keyCode);if (e.keyCode == 32){onClick_SetPk(thisobj);return;}// 當前編輯對象在fieldrow中的索引位置var colindex = $(thisobj).index();if (e.keyCode == 38){// 上一行var prevrow = $(thisobj).parent('.fieldrow').prev();if (prevrow.length == 1){prevrow.children().eq(colindex).focus();}} else if (e.keyCode == 39){// 移向右一列 不考慮右側無列情況 $(thisobj).next().focus();}else if (e.keyCode == 40){// 下一行var nextrow = $(thisobj).parent('.fieldrow').next();if (nextrow.length == 1){nextrow.children().eq(colindex).focus();}} } // 切換設置 鼠標單擊時切換 function onClick_SetPk(thisobj) {if ($(thisobj).html() == ''){$('.field-col.pk').html('');$(thisobj).html('主鍵');} else{$('.field-col.pk').html('');}return; } // 列名稱,長度,默認值: 獲得焦點后,其內生成input function fieldCol_focus_toEdit(thisobj) {if ($(thisobj).find('input').length == 1)return;var html = '<input class="field-form-control" οnblur="field_input_blur(this)" οnkeydοwn="field_input_updownArrow(event,this)" type="text" />';var val = $(thisobj).html();$(thisobj).html(html).find('input').focus().val(val);$(thisobj).prop('tabindex', '-1'); } // // 列名稱,長度,默認值INPUT框失去焦點事件:框去掉,值寫到父級SPAN中 function field_input_blur(thisobj) {var parent = $(thisobj).parent('.field-col');var val = $(thisobj).val();//console.log(val);parent.html(val).prop('tabindex', '0');// refreshEditStatus();// } // // 列名稱,長度,默認值INPUT框支持上下方向鍵盤切換到上下行同一列 function field_input_updownArrow(event, thisobj) {var e = event || window.event;// 當前編輯對象在其行內的列索引位置var colindex = $(thisobj).parent().index();if (e.keyCode == 38){// 上一行var prevrow = $(thisobj).parent().parent('.fieldrow').prev();if (prevrow.length == 1){prevrow.children().eq(colindex).focus();}} else if (e.keyCode == 40){// 下一行var nextrow = $(thisobj).parent().parent('.fieldrow').next();if (nextrow.length == 1){nextrow.children().eq(colindex).focus();}}// 按左右鍵時,如果光標處在文本最右,再按右,則移到后列.如果在最左,再按左,則移到前列// 光標焦點位置.如果=文本長度則在最后,為0則在最前//console.log($(thisobj).prop('selectionEnd'));var position = $(thisobj).prop('selectionEnd');if (e.keyCode == 37){// 左移動 未考慮左邊沒有列的情況,因為第1列是主鍵設置.有本事件的列,其左邊至少有一列if (position == 0){$(thisobj).parent().prev().focus();}} else if (e.keyCode == 39){// 右 未考慮右邊沒列的情況,有本事件的列不會處于最右邊if (position == $(thisobj).val().length){$(thisobj).parent().next().focus();}} } // 列的類型:獲得焦點后,其內生成SELECT function fieldColType_toSelect(thisobj) {if ($(thisobj).find('select').length == 1)return;var selectedval = $(thisobj).attr('val');var select = $('#tpl_fieldcol_type_select').html();$(thisobj).html(select).prop('tabindex', '-1');if (selectedval){$(thisobj).find('select').focus().find('option[value=' + selectedval + ']').prop('selected', 'selected');//console.log($(thisobj).find('select').prop('tabindex')); } } // // 列類型SELECT框失去焦點后,選擇值寫到val屬性上,標題值寫到html function fieldType_select_blur(thisobj) {var val = $(thisobj).val();var text = $(thisobj).find('option[value=' + val + ']').html();$(thisobj).parent('.field-col').html(text).attr('val', val).prop('tabindex', '0');// refreshEditStatus(); } // // 列類型SELECT框.按左右方向鍵時,移動到左右相應列上 function fieldType_select_keydown(event,thisobj) {// 不考慮左右沒有列的情況 ,因為本事件所在列不會處在最左或最右var e = event || window.event;if (e.keyCode == 37){// 左移動 $(thisobj).parent().prev().focus();} else if (e.keyCode == 39){// 右 $(thisobj).parent().next().focus();}return false; } // 列的說明:獲得焦點后,其內生成textarea function fieldCol_focus_info(thisobj) {if ($(thisobj).find('textarea').length == 1)return;var html = '<textarea class="field-form-control info" οnblur="field_input_blur(this)"></textarea>';var val = $(thisobj).html();$(thisobj).parent('.fieldrow').find('.field-col').addClass('editinfo');$(thisobj).html(html).find('textarea').focus().val(val);$(thisobj).prop('tabindex', '-1'); } // 在當前行的上面插入一行 function fieldColOp_click_insertRow(thisobj) {var row = $(thisobj).parent('.fieldrow');var insertrow = row.before($('#tpl_fieldrow').html()); } // 上移下移操作功能:向上或下移動當前行 function fieldColOp_click_moveRow(thisobj) {var row = $(thisobj).parent();var colindex = row.index();if ($(thisobj).hasClass('moverow-up')){if (colindex > 1){row.insertBefore(row.prev());} } else if ($(thisobj).hasClass('moverow-down')){if (row.next().length == 1)row.insertAfter(row.next());} } // 刪除一個列 // 如果沒有填寫列名,則不提示確認刪除 function fieldCopOp_click_delRow(thisobj) {var row = $(thisobj).parent('.fieldrow');var fieldname = row.find('.field-col').eq(1).html();if (fieldname.length == 0){row.remove();refreshEditStatus();return;}var msg = '確定要刪除字段 ' + fieldname + ' ?不可恢復!';alertbox(msg,function (){row.remove();refreshEditStatus();}) } js轉載于:https://www.cnblogs.com/mirrortom/p/7660577.html
總結
- 上一篇: 数据结构教材推荐
- 下一篇: 计算机会计学ufo报表,计算机会计学 第