在自定义日历中自动突出显示"rest of day"



我正在用vanilla JS创建一个事件调度器。我目前正在研究通过将鼠标"拖动"到所需时间上来突出显示时间跨度的功能。我已经让它工作得很好,但如果用户开始将一天(例如星期一(拖到第二天(例如星期二(,我希望一天的其余时间自动突出显示。

换句话说,如果您在星期一凌晨 03 点开始突出显示并拖动到星期二上午 05 点,则突出显示的区域应自动为星期一 03-07 和星期二 00-05。

我几乎让它工作了,但所有这些坐标和计算都让我头晕目眩。欢迎任何帮助或指导。


这是我遇到问题的片段:

if((j >= (startCol-1) && j <= (col-1) && i >= (startRow-1) && i < (row-1))) {
rows[i].children[j].classList.add('selected');
} else if((j > (startCol-1)) && (j <= (col-1)) && (i < (startRow-1))) {
rows[i].children[j].classList.add('selected');
} else if((j < (col-1) && (j >= (startCol-1)) && (i >= (row-1)))) {
rows[i].children[j].classList.add('selected');
} else {
rows[i].children[j].classList.remove('selected');
}

这是一个完整的片段

const table = document.querySelector('.table');
const rows = document.querySelectorAll('.row');
const sqSize = 28;
let selValue = 'p1';
let didMouseMove = false;
let startRow;
let startCol;
const cb = (e) => {
	didMouseMove = true;
	const x = e.clientX - table.offsetLeft;
	const y = e.clientY - table.offsetTop;
const row = Math.round(y / sqSize);
const col = Math.round(x / sqSize);
for(let i=0; i < rows.length; i++) {
	for(let j=0; j < rows[i].children.length; j++) {
	if((j >= (startCol-1) && j <= (col-1) && i >= (startRow-1) && i < (row-1))) {
		rows[i].children[j].classList.add('selected');
} else if((j > (startCol-1)) && (j <= (col-1)) && (i < (startRow-1))) {
	rows[i].children[j].classList.add('selected');
} else if((j < (col-1) && (j >= (startCol-1)) && (i >= (row-1)))) {
	rows[i].children[j].classList.add('selected');
} else {
	rows[i].children[j].classList.remove('selected');
}
}
}
}
table.addEventListener('mousedown', (e) => {
startRow = Math.round((e.clientY - table.offsetTop) / sqSize);
	startCol = Math.round((e.clientX - table.offsetLeft) / sqSize);
table.addEventListener('mousemove', cb);
});
table.addEventListener('mouseup', (e) => {
	const x = table.querySelectorAll('.selected');
for (let i = 0; i < x.length; i++) {
	x[i].className = selValue;
}
	if(!didMouseMove && !e.target.classList.contains('row')) {
	e.target.classList.toggle(selValue);
}
	didMouseMove = false;
table.removeEventListener('mousemove', cb);
});
document.getElementById('sel').addEventListener('change', (e) => {
	selValue = e.target.value;
});
body {
margin: 0;
padding: 0;
}
.head {
font-size: 0;
margin-left: 32px;
}
.head > div {
font-size: 12px;
display: inline-block;
width: 25px;
margin: 0 2px;
text-align: center;
}
.pre {
display: inline-block;
font-size: 0;
vertical-align: top;
width: 32px;
margin-top: -8px;
}
.pre > div {
height: 25px;
margin: 2px 0;
font-size: 12px;
display: inline-block;
}
.table {
display: inline-block;
}
.wrapper {
display: inline-block;
position: relative;
}
.row {
font-size: 0;
}
.row > div {
display: inline-block;
border: 1px solid black;
margin: 1px;
width: 25px;
height: 25px;
}
.p1 {
background: green;
}
.p2 {
background: blue;
}
.p3 {
background: orange;
}
.selected {
background: grey;
}
<div>
<select id="sel">
<option value="p1">Profile 1</option>
<option value="p2">Profile 2</option>
<option value="p3">Profile 3</option>
</select>
</div>

<div class='wrapper'>
<div class='head'>
<div>Mon</div>
<div>Tue</div>
<div>Wed</div>
<div>Thu</div>
<div>Fri</div>
<div>Sat</div>
<div>Sun</div>
</div>
<div>
<div class='pre'>
<div>00:00</div>
<div>00:30</div>
<div>01:00</div>
<div>01:30</div>
<div>02:00</div>
<div>02:30</div>
<div>03:00</div>
<div>03:30</div>
<div>04:00</div>
<div>04:30</div>
<div>05:00</div>
<div>05:30</div>
<div>06:00</div>
<div>06:30</div>
<div>07:00</div>
</div>
<div class='table'>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>

和 JSFIDDLE 叉子:http://jsfiddle.net/a2v9rd50/1/

我写了这个,需要调整和重构,但选择"有效"。

我动态地生成了一个丑陋的时尚日历。每个单元格都有一个像这样构建的 id:day_halfhourday是 x 坐标,halfhour是 y 坐标。星期一 00:00 的单元格具有 id0_0。周日23:30有6_47

每个单元格上有 2 个事件侦听器。

一个用于选择起始 (mousedown(,用于设置起始坐标(天 + 小时(startPoint并举起标志selecting

另一个用于选择 (mouseover(。仅当标志selecting为 true 时,才会执行它。它设置结束坐标(天+小时(coor与当前单元格ID(x_y(

文档 (mouseup( 上有第三个事件,在控制台中显示开始和结束坐标。

由你来使用最终事件来设计所选日期和管理数据。

function changeColor(x, y, state)
{
let cell = document.getElementById(x + '_' + y);
if (cell)
cell.className = state;
}
let tbl = document.createElement('table');
let container = document.getElementById('myTable');
let startPoint = null;
let endPoint = null;
let selecting = false;
for (let i = 0; i < 48; ++i)
{
let tr = document.createElement('tr');
for (let j = 0; j < 7; ++j)
{
let td = document.createElement('td');
td.setAttribute('id', j + "_" + i);
td.innerHTML = "A";
td.addEventListener('mousedown', (e) =>
{
let coortemp = e.srcElement.id.split('_');
startPoint = [coortemp[0], coortemp[1]];
selecting = true;
changeColor(coortemp[0], coortemp[1], "selecting");
});
td.addEventListener('mouseover', (e) =>
{
if (selecting)
{
endPoint = e.srcElement.id.split('_');
for (let x = 0; x < 7; ++x)
{
for (let y = 0; y < 48; ++y)
{
//We're out of range concerning selection. background is white
if (x < startPoint[0]
|| x > endPoint[0])
changeColor(x, y, "deselected");
else
{
//In the case where we're "painting" the first day
//of the selection.
if (x == startPoint[0])
{
/*
* This checks if start and end are the same day.
* to avoid "painting" too much hours
* Or if days are differents, so we can "paint" until midnight
*/
if (y >= startPoint[1]
&& ((startPoint[0] == endPoint[0]
&& y <= endPoint[1])
|| startPoint[0] != endPoint[0]))
{
changeColor(x, y, "selecting");
}
else
{
changeColor(x, y, "deselected");
}
}
//last day of selection ...
else if (x == endPoint[0])
{
//... before or at last hour
if (y <= endPoint[1])
{
changeColor(x, y, "selecting");
}                                    
else
{
changeColor(x, y, "deselected");
}
}
//There, we're definitely in range and we can blindly "paint"
else
{
changeColor(x, y, "selecting");
}
}
}
}
}
});
tr.appendChild(td);
}
tbl.appendChild(tr);
}
container.appendChild(tbl);
document.addEventListener('mouseup', () =>
{
if (selecting)
{
if (!endPoint)
endPoint = startPoint;
console.log('final selection : from day ' + startPoint[0] + ' half-hour * ' + startPoint[1] + ' to day ' + endPoint[0] + ' half-hour * ' + endPoint[1]);
selecting = false;
let days = document.getElementsByClassName("selecting");

while (days.length)
days[0].className = "selected";
}
});
.selecting
{
background-color: #A9A9A9;
}
.deselected
{
background-color: #FFFFFF;
}
.selected
{
background-color: #00FF00;
}
<div id="myTable">
</div>

你正在做的事情很快就会变得非常复杂。 我建议通过在 HTML 中使用数据属性并在可重用函数中拆分逻辑来简化代码。

这里有一些伪代码,显示了我将如何处理它。

<div class='table'>
<div class='row'>
<div data-date="2018-12-11T00:03:30"></div>
<div data-date="2018-12-11T00:04:00"></div>
<div data-date="2018-12-11T00:04:30"></div>
<div data-date="2018-12-11T00:05:00"></div>
<div data-date="2018-12-11T00:05:30"></div>
<div data-date="2018-12-11T00:06:00"></div>
<div data-date="2018-12-11T00:06:30"></div>
</div>
</div>
let mouseDown = false;
let selectionStart;
let selectionEnd;
const table = document.querySelector('.table');
const getElementValueFromMouse = event => {
const element = document.elementFromPoint(event.clientX, event.clientY);
return element.dataset.date;
};
table.addEventListener('mousedown', (e) => {
mouseDown = true;
selectionStart = getElementValueFromMouse(e);
});
const paintCurrentSelection = () => {
const color = mouseDown ? 'selectionColor' : 'profileColor';
// Find all the cells between selectionStart and selectionEnd ...
// Revert the previous selection paint ...
// Paint ...
};
document.addEventListener('mouseup', (e) => {
mouseDown = false;
selectionEnd = getElementValueFromMouse(e);
paintCurrentSelection();
});
table.addEventListener('mousemove', (e) => {
if (!mouseDown) {
return;
}
selectionEnd = getElementValueFromMouse(e);
paintCurrentSelection();
});

最新更新