Recently due to company demand
You need to write Excel to merge cells, drag and drop to select cells, drag and drop to change cell size and other functions
Because the framework used by the company was written by one of the company’s bigwigs
Therefore, in order to be able to have good adhesion with the company’s project, it needs to use JS or jquery development
And on the net basically can not find the big guy to share the code, more is to ask others to use the plug-in
Although there is a user to share the code, but because the user’s code in many TD table will be stuck, poor performance, so not adopted
Then he decided to develop his own…
The sample
Making the address
Technical difficulties
table
里td
The problem with merging- Drag to select
td
If you encounter the mergedtd
You need to decide if there are other optionstd
Implementation approach
- The first
table
To an array, the merged cells need to be inserted as follows
// Merge represents the tag "< TD colSpan="3" rowSpan="3">123
"
let table_arr = [
[td, td, td, td, td, td, ....],
[td, td, td, td, td, td, ....],
[td, td, merge, merge, merge, td, ....],
[td, td, merge, merge, merge, td, ....],
[td, td, merge, merge, merge, td, ....],
[td, td, td, td, td, td, ....],
....
]
Copy the code
- For each
td
Traversal sets the unique identifier, which I used heredataset
To set the
// Set td unique identifier
function setTdSpan (table_arr) {
setTimeout((a)= > {
table_arr.forEach((row, row_i) = > {
row.forEach((col, col_i) = > {
let row_num = row_i
let col_num = col_i
if (col.rowSpan > 1) row_num = row_i - col.rowSpan + 1
if (col.colSpan > 1) col_num = col_i - col.colSpan + 1
$(col).attr('data-tdspan'.`${row_num}-${col_num}`)
$(col).attr('data-endtdspan'.`${row_i}-${col_i}`)})})})}Copy the code
- Then according to the mouse press, move, bounce position, to obtain the cell
td
The subscript
// Get the TD of the mouse position
function switchTd (params, fn) {
let table = $('table') [0]
let { x, y } = params
table_arr.forEach((tr, tr_ind) = > {
tr.forEach((td, td_ind) = > {
if (tr_ind === 0 || td_ind === 0) return
let td_start_left = td.offsetLeft
let td_start_top = td.offsetTop
let td_end_left = td_start_left + td.offsetWidth
let td_end_top = td_start_top + td.offsetHeight
if ((x >= td_start_left && x <= td_end_left) && (y >= td_start_top && y <= td_end_top)) {
typeof fn === 'function' && fn({
tr_ind, td_ind, td,
end_tr_ind: subStrTdSpan(td.dataset.endtdspan, 'tr'),
end_td_ind: subStrTdSpan(td.dataset.endtdspan, 'td'),
left: table.offsetLeft + td_start_left,
top: table.offsetTop + td_start_top
})
}
})
})
}
Copy the code
// Drag and select
$(document).on('mousedown', (e) => {
$('.select_area').css({'cursor': 'default'})
let start_left = e.clientX + $(document).scrollLeft()
let start_top = e.clientY + $(document).scrollTop()
// It is used to determine whether the td is the same
let tr_td = ' '
// start/end TD subscript
let tr_num = 0
let td_num = 0
switchTd({
x: start_left - $('table').offset().left,
y: start_top - $('table').offset().top
}, (ind_data) => {
tr_num = ind_data.tr_ind
td_num = ind_data.td_ind
if (tr_num === 0 || td_num === 0) return
collisionCell({
tr_num, td_num,
tr_ind: ind_data.end_tr_ind,
td_ind: ind_data.end_td_ind
})
tr_td = ind_data.td.dataset.tdspan
})
$(document).on('mousemove', (e1) => {
e1.preventDefault()
let move_left = e1.clientX + $(document).scrollLeft()
let move_top = e1.clientY + $(document).scrollTop()
switchTd({
x: move_left - $('table').offset().left,
y: move_top - $('table').offset().top
}, (ind_data) => {
if (tr_num === 0 || td_num === 0) return
if (tr_td === ind_data.td.dataset.tdspan) return
collisionCell({
tr_num, td_num,
tr_ind: ind_data.end_tr_ind,
td_ind: ind_data.end_td_ind
})
tr_td = ind_data.td.dataset.tdspan
})
})
})
$(document).on('mouseup', () => {$()document).unbind('mousemove')
setSelectTdArr()
console.log(start_end_data)
console.log(select_td_arr)
})
Copy the code
- And then you compute some subscript
td
To some subscripttd
To calculate the size and position of the selection box
// Collision mechanism 1, calculate the start and end positions
function collisionCell (params) {
let { tr_num, td_num, tr_ind, td_ind } = params
// Determine the start position and end position
let start_tr_ind = tr_num <= tr_ind? tr_num: tr_ind
let end_tr_ind = start_tr_ind === tr_num? tr_ind: tr_num
let start_td_ind = td_num <= td_ind? td_num: td_ind
let end_td_ind = start_td_ind === td_num? td_ind: td_num
start_end_data = {
s_tr: start_tr_ind, s_td: start_td_ind,
e_tr: end_tr_ind, e_td: end_td_ind
}
comElementTdSpan({
s_tr: start_tr_ind, s_td: start_td_ind,
e_tr: end_tr_ind, e_td: end_td_ind
})
}
Copy the code
// Collision mechanism 2, calculate the start and end index after collision mechanism
let select_td_arr2 = [] // Use to judge when selecting
function comElementTdSpan (params) {
let { s_tr, s_td, e_tr, e_td } = params
let std = table_arr[s_tr][s_td]
let etd = table_arr[e_tr][e_td]
let start_tr_ind = subStrTdSpan(std.dataset.tdspan, 'tr')
let start_td_ind = subStrTdSpan(std.dataset.tdspan, 'td')
let end_tr_ind = subStrTdSpan(etd.dataset.endtdspan, 'tr')
let end_td_ind = subStrTdSpan(etd.dataset.endtdspan, 'td')
select_td_arr2 = []
let left = null, top = null, right = null, bottom = null
for (let tr_ind = start_tr_ind; tr_ind <= end_tr_ind; tr_ind++) {
for (let td_ind = start_td_ind; td_ind <= end_td_ind; td_ind++) {
let td = table_arr[tr_ind][td_ind]
select_td_arr2.push(td)
let left_td = td.getBoundingClientRect().left
let top_td = td.getBoundingClientRect().top
let right_td = td.getBoundingClientRect().right
letbottom_td = td.getBoundingClientRect().bottom left = left ! = =null? (left_td < left ? left_td : left) : left_td top = top ! = =null? (top_td < top ? top_td : top) : top_td right = right ! = =null? (right_td > right ? right_td : right) : right_td bottom = bottom ! = =null ? (bottom_td > bottom ? bottom_td : bottom) : bottom_td
}
}
left = left + $(document).scrollLeft()
top = top + $(document).scrollTop()
right = right + $(document).scrollLeft()
bottom = bottom + $(document).scrollTop()
let s_tr2 = null, s_td2 = null, e_tr2 = null, e_td2 = null
select_td_arr2.forEach((td) = > {
let s_tr_ind2 = subStrTdSpan(td.dataset.tdspan, 'tr')
let s_td_ind2 = subStrTdSpan(td.dataset.tdspan, 'td')
let e_tr_ind2 = subStrTdSpan(td.dataset.endtdspan, 'tr')
let e_td_ind2 = subStrTdSpan(td.dataset.endtdspan, 'td') s_tr2 = s_tr2 ! = =null? (s_tr2 < s_tr_ind2 ? s_tr2 : s_tr_ind2) : s_tr_ind2 s_td2 = s_td2 ! = =null? (s_td2 < s_td_ind2 ? s_td2 : s_td_ind2) : s_td_ind2 e_tr2 = e_tr2 ! = =null? (e_tr2 > e_tr_ind2 ? e_tr2 : e_tr_ind2) : e_tr_ind2 e_td2 = e_td2 ! = =null ? (e_td2 > e_td_ind2 ? e_td2 : e_td_ind2) : e_td_ind2
})
setSelectCss({
left: left,
top: top,
width: right - left,
height: bottom - top
})
if(s_tr ! == s_tr2 || s_td ! == s_td2 || e_tr ! == e_tr2 || e_td ! == e_td2) { start_end_data = {s_tr: s_tr2, s_td: s_td2,
e_tr: e_tr2, e_td: e_td2
}
comElementTdSpan({
s_tr: s_tr2, s_td: s_td2,
e_tr: e_tr2, e_td: e_td2
})
}
}
Copy the code
- Then set the selection box
css
attribute
// Styles the marquee
let sel_html = `<div class="select_area"></div>`
$('body').append($(sel_html))
function setSelectCss(params) {
let { width, height, left, top, css_obj } = params
$('.select_area').css(Object.assign({
'width': width + 'px'.'height': height + 'px'.'left': left + 'px'.'top': top + 'px'.'border': '2px solid rgb(47, 137, 220)'.'box-sizing': 'border-box'.'position': 'absolute'.'background-color': 'rgba (23, 133, 231, 0.1)'
}, css_obj))
}
Copy the code
- Finally, the selected box is selected
td
In the array
// Insert the selected TD into select_td_arr array
function setSelectTdArr () {
let select_area = $('.select_area')
select_td_arr = []
$('table').find('td').each(function () {
let t1 = $(this).offset().top
let l1 = $(this).offset().left
let r1 = $(this).offset().left + $(this).innerWidth()
let b1 = $(this).offset().top + $(this).innerHeight()
let t2 = select_area.offset().top
let l2 = select_area.offset().left
let r2 = select_area.offset().left + select_area.innerWidth()
let b2 = select_area.offset().top + select_area.innerHeight()
if (t2 < b1 && l2 < r1 && r2 > l1 && b2 > t1) {
select_td_arr.push($(this) [0])}})}Copy the code
The full code can be viewed on Github
The end of the
Finally, you are welcome to point out the problem and learn together
Feel good can also give me a star, love you brother ^▽^