mirror of https://github.com/ElemeFE/element
* date-table: simplify implementation, fix #12980 * date-table: remove rangeState's row and column * date-table: fix disabled cell highlight this is a regression introduced in pr #8156, which allows disabled date to be highlighted. Also simplifies handleClick's implementation to avoid DOM operations.pull/13398/head
parent
61f2b8afae
commit
9738054dd4
|
@ -32,16 +32,19 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, nextDate, isDate } from '../util';
|
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, nextDate, isDate, clearTime as _clearTime} from '../util';
|
||||||
import { hasClass } from 'element-ui/src/utils/dom';
|
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
import { arrayFindIndex, arrayFind, coerceTruthyValueToArray } from 'element-ui/src/utils/util';
|
import { arrayFindIndex, arrayFind, coerceTruthyValueToArray } from 'element-ui/src/utils/util';
|
||||||
|
|
||||||
const WEEKS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
const WEEKS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||||
const clearHours = function(time) {
|
const getDateTimestamp = function(time) {
|
||||||
const cloneDate = new Date(time);
|
if (typeof time === 'number' || typeof time === 'string') {
|
||||||
cloneDate.setHours(0, 0, 0, 0);
|
return _clearTime(new Date(time)).getTime();
|
||||||
return cloneDate.getTime();
|
} else if (time instanceof Date) {
|
||||||
|
return _clearTime(time).getTime();
|
||||||
|
} else {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// remove the first element that satisfies `pred` from arr
|
// remove the first element that satisfies `pred` from arr
|
||||||
|
@ -92,9 +95,7 @@
|
||||||
default() {
|
default() {
|
||||||
return {
|
return {
|
||||||
endDate: null,
|
endDate: null,
|
||||||
selecting: false,
|
selecting: false
|
||||||
row: null,
|
|
||||||
column: null
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,7 @@
|
||||||
const startDate = this.startDate;
|
const startDate = this.startDate;
|
||||||
const disabledDate = this.disabledDate;
|
const disabledDate = this.disabledDate;
|
||||||
const selectedDate = this.selectionMode === 'dates' ? coerceTruthyValueToArray(this.value) : [];
|
const selectedDate = this.selectionMode === 'dates' ? coerceTruthyValueToArray(this.value) : [];
|
||||||
const now = clearHours(new Date());
|
const now = getDateTimestamp(new Date());
|
||||||
|
|
||||||
for (let i = 0; i < 6; i++) {
|
for (let i = 0; i < 6; i++) {
|
||||||
const row = rows[i];
|
const row = rows[i];
|
||||||
|
@ -162,9 +163,9 @@
|
||||||
|
|
||||||
const index = i * 7 + j;
|
const index = i * 7 + j;
|
||||||
const time = nextDate(startDate, index - offset).getTime();
|
const time = nextDate(startDate, index - offset).getTime();
|
||||||
cell.inRange = time >= clearHours(this.minDate) && time <= clearHours(this.maxDate);
|
cell.inRange = time >= getDateTimestamp(this.minDate) && time <= getDateTimestamp(this.maxDate);
|
||||||
cell.start = this.minDate && time === clearHours(this.minDate);
|
cell.start = this.minDate && time === getDateTimestamp(this.minDate);
|
||||||
cell.end = this.maxDate && time === clearHours(this.maxDate);
|
cell.end = this.maxDate && time === getDateTimestamp(this.maxDate);
|
||||||
const isToday = time === now;
|
const isToday = time === now;
|
||||||
|
|
||||||
if (isToday) {
|
if (isToday) {
|
||||||
|
@ -220,32 +221,27 @@
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
'rangeState.endDate'(newVal) {
|
'rangeState.endDate'(newVal) {
|
||||||
this.markRange(newVal);
|
this.markRange(this.minDate, newVal);
|
||||||
},
|
},
|
||||||
|
|
||||||
minDate(newVal, oldVal) {
|
minDate(newVal, oldVal) {
|
||||||
if (newVal && !oldVal) {
|
if (getDateTimestamp(newVal) !== getDateTimestamp(oldVal)) {
|
||||||
this.rangeState.selecting = true;
|
this.markRange(this.minDate, this.maxDate);
|
||||||
this.markRange(newVal);
|
|
||||||
} else if (!newVal) {
|
|
||||||
this.rangeState.selecting = false;
|
|
||||||
this.markRange(newVal);
|
|
||||||
} else {
|
|
||||||
this.markRange();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
maxDate(newVal, oldVal) {
|
maxDate(newVal, oldVal) {
|
||||||
if (newVal && !oldVal) {
|
if (getDateTimestamp(newVal) !== getDateTimestamp(oldVal)) {
|
||||||
this.rangeState.selecting = false;
|
this.markRange(this.minDate, this.maxDate);
|
||||||
this.markRange(newVal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tableRows: [ [], [], [], [], [], [] ]
|
tableRows: [ [], [], [], [], [], [] ],
|
||||||
|
lastRow: null,
|
||||||
|
lastColumn: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -329,14 +325,13 @@
|
||||||
return year === valueYear && getWeekNumber(newDate) === getWeekNumber(this.value);
|
return year === valueYear && getWeekNumber(newDate) === getWeekNumber(this.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
markRange(maxDate) {
|
markRange(minDate, maxDate) {
|
||||||
const startDate = this.startDate;
|
minDate = getDateTimestamp(minDate);
|
||||||
if (!maxDate) {
|
maxDate = getDateTimestamp(maxDate) || minDate;
|
||||||
maxDate = this.maxDate;
|
[minDate, maxDate] = [Math.min(minDate, maxDate), Math.max(minDate, maxDate)];
|
||||||
}
|
|
||||||
|
|
||||||
|
const startDate = this.startDate;
|
||||||
const rows = this.rows;
|
const rows = this.rows;
|
||||||
const minDate = this.minDate;
|
|
||||||
for (let i = 0, k = rows.length; i < k; i++) {
|
for (let i = 0, k = rows.length; i < k; i++) {
|
||||||
const row = rows[i];
|
const row = rows[i];
|
||||||
for (let j = 0, l = row.length; j < l; j++) {
|
for (let j = 0, l = row.length; j < l; j++) {
|
||||||
|
@ -346,15 +341,9 @@
|
||||||
const index = i * 7 + j + (this.showWeekNumber ? -1 : 0);
|
const index = i * 7 + j + (this.showWeekNumber ? -1 : 0);
|
||||||
const time = nextDate(startDate, index - this.offsetDay).getTime();
|
const time = nextDate(startDate, index - this.offsetDay).getTime();
|
||||||
|
|
||||||
if (maxDate && maxDate < minDate) {
|
cell.inRange = minDate && time >= minDate && time <= maxDate;
|
||||||
cell.inRange = minDate && time >= clearHours(maxDate) && time <= clearHours(minDate);
|
cell.start = minDate && time === minDate;
|
||||||
cell.start = maxDate && time === clearHours(maxDate.getTime());
|
cell.end = maxDate && time === maxDate;
|
||||||
cell.end = minDate && time === clearHours(minDate.getTime());
|
|
||||||
} else {
|
|
||||||
cell.inRange = minDate && time >= clearHours(minDate) && time <= clearHours(maxDate);
|
|
||||||
cell.start = minDate && time === clearHours(minDate.getTime());
|
|
||||||
cell.end = maxDate && time === clearHours(maxDate.getTime());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -362,12 +351,6 @@
|
||||||
handleMouseMove(event) {
|
handleMouseMove(event) {
|
||||||
if (!this.rangeState.selecting) return;
|
if (!this.rangeState.selecting) return;
|
||||||
|
|
||||||
this.$emit('changerange', {
|
|
||||||
minDate: this.minDate,
|
|
||||||
maxDate: this.maxDate,
|
|
||||||
rangeState: this.rangeState
|
|
||||||
});
|
|
||||||
|
|
||||||
let target = event.target;
|
let target = event.target;
|
||||||
if (target.tagName === 'SPAN') {
|
if (target.tagName === 'SPAN') {
|
||||||
target = target.parentNode.parentNode;
|
target = target.parentNode.parentNode;
|
||||||
|
@ -377,15 +360,25 @@
|
||||||
}
|
}
|
||||||
if (target.tagName !== 'TD') return;
|
if (target.tagName !== 'TD') return;
|
||||||
|
|
||||||
const column = target.cellIndex;
|
|
||||||
const row = target.parentNode.rowIndex - 1;
|
const row = target.parentNode.rowIndex - 1;
|
||||||
const { row: oldRow, column: oldColumn } = this.rangeState;
|
const column = target.cellIndex;
|
||||||
|
|
||||||
if (oldRow !== row || oldColumn !== column) {
|
// can not select disabled date
|
||||||
this.rangeState.row = row;
|
if (this.rows[row][column].disabled) return;
|
||||||
this.rangeState.column = column;
|
|
||||||
|
|
||||||
this.rangeState.endDate = this.getDateOfCell(row, column);
|
// only update rangeState when mouse moves to a new cell
|
||||||
|
// this avoids frequent Date object creation and improves performance
|
||||||
|
if (row !== this.lastRow || column !== this.lastColumn) {
|
||||||
|
this.lastRow = row;
|
||||||
|
this.lastColumn = column;
|
||||||
|
this.$emit('changerange', {
|
||||||
|
minDate: this.minDate,
|
||||||
|
maxDate: this.maxDate,
|
||||||
|
rangeState: {
|
||||||
|
selecting: true,
|
||||||
|
endDate: this.getDateOfCell(row, column)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -399,86 +392,31 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.tagName !== 'TD') return;
|
if (target.tagName !== 'TD') return;
|
||||||
if (hasClass(target, 'disabled') || hasClass(target, 'week')) return;
|
|
||||||
|
|
||||||
const selectionMode = this.selectionMode;
|
const row = target.parentNode.rowIndex - 1;
|
||||||
|
const column = this.selectionMode === 'week' ? 1 : target.cellIndex;
|
||||||
|
const cell = this.rows[row][column];
|
||||||
|
|
||||||
if (selectionMode === 'week') {
|
if (cell.disabled || cell.type === 'week') return;
|
||||||
target = target.parentNode.cells[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
let year = Number(this.year);
|
const newDate = this.getDateOfCell(row, column);
|
||||||
let month = Number(this.month);
|
|
||||||
|
|
||||||
const cellIndex = target.cellIndex;
|
|
||||||
const rowIndex = target.parentNode.rowIndex;
|
|
||||||
|
|
||||||
const cell = this.rows[rowIndex - 1][cellIndex];
|
|
||||||
const text = cell.text;
|
|
||||||
const className = target.className;
|
|
||||||
|
|
||||||
const newDate = new Date(year, month, 1);
|
|
||||||
|
|
||||||
if (className.indexOf('prev') !== -1) {
|
|
||||||
if (month === 0) {
|
|
||||||
year = year - 1;
|
|
||||||
month = 11;
|
|
||||||
} else {
|
|
||||||
month = month - 1;
|
|
||||||
}
|
|
||||||
newDate.setFullYear(year);
|
|
||||||
newDate.setMonth(month);
|
|
||||||
} else if (className.indexOf('next') !== -1) {
|
|
||||||
if (month === 11) {
|
|
||||||
year = year + 1;
|
|
||||||
month = 0;
|
|
||||||
} else {
|
|
||||||
month = month + 1;
|
|
||||||
}
|
|
||||||
newDate.setFullYear(year);
|
|
||||||
newDate.setMonth(month);
|
|
||||||
}
|
|
||||||
|
|
||||||
newDate.setDate(parseInt(text, 10));
|
|
||||||
|
|
||||||
if (this.selectionMode === 'range') {
|
if (this.selectionMode === 'range') {
|
||||||
if (this.minDate && this.maxDate) {
|
if (!this.rangeState.selecting) {
|
||||||
const minDate = new Date(newDate.getTime());
|
this.$emit('pick', {minDate: newDate, maxDate: null});
|
||||||
const maxDate = null;
|
|
||||||
|
|
||||||
this.$emit('pick', { minDate, maxDate }, false);
|
|
||||||
this.rangeState.selecting = true;
|
this.rangeState.selecting = true;
|
||||||
this.markRange(this.minDate);
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.handleMouseMove(event);
|
|
||||||
});
|
|
||||||
} else if (this.minDate && !this.maxDate) {
|
|
||||||
if (newDate >= this.minDate) {
|
|
||||||
const maxDate = new Date(newDate.getTime());
|
|
||||||
this.rangeState.selecting = false;
|
|
||||||
|
|
||||||
this.$emit('pick', {
|
|
||||||
minDate: this.minDate,
|
|
||||||
maxDate
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const minDate = new Date(newDate.getTime());
|
if (newDate >= this.minDate) {
|
||||||
|
this.$emit('pick', {minDate: this.minDate, maxDate: newDate});
|
||||||
|
} else {
|
||||||
|
this.$emit('pick', {minDate: newDate, maxDate: this.minDate});
|
||||||
|
}
|
||||||
this.rangeState.selecting = false;
|
this.rangeState.selecting = false;
|
||||||
|
|
||||||
this.$emit('pick', { minDate, maxDate: this.minDate });
|
|
||||||
}
|
}
|
||||||
} else if (!this.minDate) {
|
} else if (this.selectionMode === 'day') {
|
||||||
const minDate = new Date(newDate.getTime());
|
|
||||||
|
|
||||||
this.$emit('pick', { minDate, maxDate: this.maxDate }, false);
|
|
||||||
this.rangeState.selecting = true;
|
|
||||||
this.markRange(this.minDate);
|
|
||||||
}
|
|
||||||
} else if (selectionMode === 'day') {
|
|
||||||
this.$emit('pick', newDate);
|
this.$emit('pick', newDate);
|
||||||
} else if (selectionMode === 'week') {
|
} else if (this.selectionMode === 'week') {
|
||||||
const weekNumber = getWeekNumber(newDate);
|
const weekNumber = getWeekNumber(newDate);
|
||||||
|
|
||||||
const value = newDate.getFullYear() + 'w' + weekNumber;
|
const value = newDate.getFullYear() + 'w' + weekNumber;
|
||||||
this.$emit('pick', {
|
this.$emit('pick', {
|
||||||
year: newDate.getFullYear(),
|
year: newDate.getFullYear(),
|
||||||
|
@ -486,7 +424,7 @@
|
||||||
value: value,
|
value: value,
|
||||||
date: newDate
|
date: newDate
|
||||||
});
|
});
|
||||||
} else if (selectionMode === 'dates') {
|
} else if (this.selectionMode === 'dates') {
|
||||||
const value = this.value || [];
|
const value = this.value || [];
|
||||||
const newValue = cell.selected
|
const newValue = cell.selected
|
||||||
? removeFromArray(value, date => date.getTime() === newDate.getTime())
|
? removeFromArray(value, date => date.getTime() === newDate.getTime())
|
||||||
|
|
Loading…
Reference in New Issue