-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
382 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<!DOCTYPE html> | ||
<html lang="zh-Hans"> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> | ||
<title>Calendar</title> | ||
|
||
<div class="page"> | ||
<nav> | ||
<h1 class="date"></h1> | ||
<div class="controls"> | ||
<button id="previousMonth"><</button> | ||
<button id="today">今天</button> | ||
<button id="nextMonth">></button> | ||
</div> | ||
</nav> | ||
<div class="calendar"></div> | ||
</div> | ||
<script src="../lib/dom/index.js"></script> | ||
<script src="../lib/date2/index.js"></script> | ||
<script src="../lib/calendar/index.js"></script> | ||
<style> | ||
body{margin:0;} | ||
* {box-sizing: border-box;} | ||
h1{margin: 0;} | ||
.page{ min-height: 100vh; display: flex; flex-direction: column; } | ||
.page > nav:first-child{text-align: right; display: flex; | ||
justify-content: space-between; align-items: center;padding: 1em;} | ||
.calendar { flex-grow: 1; display: flex; flex-direction: column;} | ||
.calendar> ol{list-style:none; margin:0; padding:0; } | ||
.calendar> ol.weekdays{display: flex; text-align: right; } | ||
.calendar> ol.weekdays >li{width: 14.2857%; padding: .5em 1em;} | ||
|
||
.calendar> ol.days{display: flex; flex-wrap: wrap; flex-grow: 1;} | ||
.calendar> ol.days>li{width: 14.2857%; border-right: 1px solid #C7C7CC; border-top: 1px solid #C7C7CC; | ||
position: relative; | ||
} | ||
.calendar> ol.days>li:nth-child(7n){ border-right: none; } | ||
.calendar> ol.days>li> .dayLabel{ | ||
position: absolute; right: 1em; top: .8em; white-space: nowrap; text-align: right; | ||
} | ||
|
||
.calendar .today .day{ background: red; width: 1.6em; display: inline-block; text-align: center; height: 1.6em; | ||
line-height: 1.6em; border-radius: 50%; color: white; | ||
} | ||
.calendar .weekdays .weekend{ color: #B8B8B8; } | ||
.calendar .days .weekend{ background: #F5F5F5; } | ||
</style> | ||
<script> | ||
let calendar = new Calendar({ | ||
element: document.querySelector('.calendar'), | ||
output: document.querySelector('.date'), | ||
}) | ||
previousMonth.onclick = function(){ | ||
calendar.previousMonth() | ||
} | ||
nextMonth.onclick = function(){ | ||
calendar.nextMonth() | ||
} | ||
today.onclick = function(){ | ||
calendar.resetMonth() | ||
} | ||
</script> | ||
|
||
<!--百度统计--> | ||
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?950926001a84a4f88cd3e1c7c0bfac08"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<!DOCTYPE html> | ||
<html lang="zh-Hans"> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> | ||
<title>Date2</title> | ||
|
||
<div class="calendar"></div> | ||
<script src="../lib/date2/index.js"></script> | ||
<script> | ||
{ | ||
let assert = console.assert.bind(console) | ||
let date = new Date(2011, 0, 4, 6, 8, 10, 999) | ||
let d1 = new Date2(date) | ||
assert(d1.date !== date) | ||
assert(d1.date.getTime() === date.getTime()) | ||
|
||
assert(d1.weekday() === date.getDay()) | ||
assert(d1.day() === date.getDate()) | ||
assert(d1.year() === date.getFullYear()) | ||
assert(d1.month() === date.getMonth() + 1) | ||
assert(d1.hours() === date.getHours()) | ||
assert(d1.minutes() === date.getMinutes()) | ||
assert(d1.seconds() === date.getSeconds()) | ||
assert(d1.milliseconds() === date.getMilliseconds()) | ||
assert(d1.year(2012).date.getFullYear() === 2012) | ||
assert(date.getFullYear() === 2011) | ||
assert(d1.month(4).date.getMonth() === 3) | ||
assert(d1.day(1).date.getDate() === 1) | ||
assert(d1.hours(2).date.getHours() === 2) | ||
assert(d1.minutes(2).date.getMinutes() === 2) | ||
assert(d1.seconds(2).date.getSeconds() === 2) | ||
assert(d1.milliseconds(2).date.getMilliseconds() === 2) | ||
|
||
assert(d1.monthBeginning.day() === 1) | ||
assert(d1.monthEnding.day() === 31) | ||
|
||
let d2 = new Date2(new Date(2011,0,31)) | ||
assert(d2.nextMonth.month() === 2) | ||
assert(d2.nextMonth.nextMonth.month() === 3) | ||
} | ||
|
||
</script> | ||
|
||
<!--百度统计--> | ||
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?950926001a84a4f88cd3e1c7c0bfac08"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
{ | ||
class Calendar { | ||
constructor(options) { | ||
let defaultOptions = { | ||
element: null, | ||
startOfWeek: 1, // 1 or 0 | ||
strings: { | ||
weekdays: n => { | ||
let map = { 0: '周日', 1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六' } | ||
return map[n] | ||
}, | ||
days: n => `${n}`, | ||
dayTemplate: ` | ||
<li> | ||
<span class="dayLabel"> | ||
<span class="day"></span><span class="unit">日</span> | ||
</span> | ||
</li> | ||
`, | ||
output: d => `${d.getFullYear()}年${d.getMonth() + 1}月`, | ||
}, | ||
} | ||
|
||
this.options = Object.assign({}, defaultOptions, options) | ||
this.currentDate = new Date() | ||
this._checkOptions() | ||
this._generateCalendar() | ||
} | ||
nextMonth() { | ||
this.currentDate = new Date2(this.currentDate).nextMonth.date | ||
this._generateCalendar() | ||
} | ||
previousMonth() { | ||
this.currentDate = new Date2(this.currentDate).previousMonth.date | ||
this._generateCalendar() | ||
} | ||
resetMonth() { | ||
this.currentDate = new Date() | ||
this._generateCalendar() | ||
} | ||
_checkOptions() { | ||
if (!this.options.element) { | ||
throw new Error('element is required') | ||
} | ||
return this | ||
} | ||
_generateWeekdays() { | ||
let { startOfWeek, strings } = this.options | ||
let items = createArray({ length: 7, fill: startOfWeek }).map((day, i) => { | ||
let n = day + i >= 7 ? day + i - 7 : day + i | ||
let text = strings.weekdays(n) | ||
let li = dom.create(`<li>${text}</li>`) | ||
if ([0, 6].indexOf(n) >= 0) { | ||
li.classList.add('weekend') | ||
} | ||
return li | ||
}) | ||
return dom.create(`<ol class="weekdays"></ol>`, items) | ||
} | ||
_generateCurrentMonth() { | ||
let current = new Date2(this.currentDate) | ||
let dayCount = current.monthEnding.day() | ||
let convert = this.options.strings.days | ||
return createArray({ length: dayCount }).map((_, i) => { | ||
let date2 = current.day(i + 1) | ||
let li = dom.create(this.options.strings.dayTemplate) | ||
li.className = 'currentMonth' | ||
if (date2.isSameDayAs(new Date())) { | ||
li.classList.add('today') | ||
} | ||
if ([0, 6].indexOf(date2.weekday()) >= 0) { | ||
li.classList.add('weekend') | ||
} | ||
li.querySelector('.day').textContent = convert(i + 1) | ||
return li | ||
}) | ||
} | ||
_generatePreviousMonth() { | ||
let { startOfWeek } = this.options | ||
let date2 = new Date2(this.currentDate) | ||
let monthBeginning = date2.monthBeginning | ||
let startPadding = monthBeginning.weekday() >= startOfWeek | ||
? monthBeginning.weekday() - startOfWeek | ||
: monthBeginning.weekday() + 7 - startOfWeek | ||
let convert = this.options.strings.days | ||
return createArray({ length: startPadding }) | ||
.map((_, i) => { | ||
let li = dom.create(this.options.strings.dayTemplate) | ||
li.className = 'previousMonth' | ||
if ([0, 6].indexOf(date2.day(-i).weekday()) >= 0) { | ||
li.classList.add('weekend') | ||
} | ||
li.querySelector('.day').textContent = convert(date2.day(-i).day()) | ||
return li | ||
}) | ||
.reverse() | ||
} | ||
_generateNextMonth() { | ||
let { startOfWeek } = this.options | ||
let date2 = new Date2(this.currentDate) | ||
let monthEnding = date2.monthEnding | ||
let endPadding = monthEnding.weekday() >= startOfWeek | ||
? 7 - (monthEnding.weekday() - startOfWeek + 1) | ||
: 7 - (monthEnding.weekday() + 7 - startOfWeek + 1) | ||
let convert = this.options.strings.days | ||
|
||
return createArray({ length: endPadding }).map((_, i) => { | ||
let li = dom.create(this.options.strings.dayTemplate) | ||
li.className = 'nextMonth' | ||
let data2 = new Date2(this.currentDate) | ||
if ([0, 6].indexOf(date2.nextMonth.day(i + 1).weekday()) >= 0) { | ||
li.classList.add('weekend') | ||
} | ||
li.querySelector('.day').textContent = convert(i + 1) | ||
return li | ||
}) | ||
} | ||
_generateDays() { | ||
let { startOfWeek } = this.options | ||
let date2 = new Date2(this.currentDate) | ||
let monthBeginning = date2.monthBeginning | ||
let monthEnding = date2.monthEnding | ||
|
||
let days = this._generateCurrentMonth() | ||
days = this._generatePreviousMonth().concat(days) | ||
days = days.concat(this._generateNextMonth()) | ||
return dom.create(`<ol class=days></ol>`, days) | ||
} | ||
_generateCalendar() { | ||
let { element } = this.options | ||
dom.removeChildren(element) | ||
dom.append(element, this._generateWeekdays()) | ||
dom.append(element, this._generateDays()) | ||
this.options.output.textContent = this.options.strings.output(this.currentDate) | ||
return this | ||
} | ||
} | ||
|
||
window.Calendar = Calendar | ||
|
||
// 生成一个长度位 length,内容为 fill 的数组 | ||
// 不同于 new Array(length),createArray 生成的数组是有 0 到 length 下标的 | ||
function createArray({ length, fill }) { | ||
let array = Array.apply(null, { length: length }) | ||
if (fill !== undefined) { | ||
array = array.map(() => fill) | ||
} | ||
return array | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
{ | ||
class Date2 { | ||
constructor(date = new Date()) { | ||
this.date = new Date(date - 0) | ||
} | ||
weekday(n) { | ||
if (n) { | ||
throw new Error('You can not set weekday') | ||
} | ||
return this._proxy('day') | ||
} | ||
day(n) { | ||
return this._proxy('date', n) | ||
} | ||
year(n) { | ||
return this._proxy('fullYear', n) | ||
} | ||
month(n) { | ||
return this._proxy('month', n, 1) | ||
} | ||
get monthBeginning() { | ||
return this.day(1) | ||
} | ||
get monthEnding() { | ||
return this.month(this.month() + 1).day(0) | ||
} | ||
get nextMonth() { | ||
let day = this.day() | ||
let month = this.month() | ||
let nextMonth = this.day(1).month(month + 1) | ||
if (day > nextMonth.monthEnding.day()) { | ||
return nextMonth.monthEnding | ||
} else { | ||
return nextMonth.day(day) | ||
} | ||
} | ||
get previousMonth() { | ||
let day = this.day() | ||
let month = this.month() | ||
let nextMonth = this.day(1).month(month - 1) | ||
if (day > nextMonth.monthEnding.day()) { | ||
return nextMonth.monthEnding | ||
} else { | ||
return nextMonth.day(day) | ||
} | ||
} | ||
hours(n) { | ||
return this._proxy('hours', n) | ||
} | ||
minutes(n) { | ||
return this._proxy('minutes', n) | ||
} | ||
seconds(n) { | ||
return this._proxy('seconds', n) | ||
} | ||
milliseconds(n) { | ||
return this._proxy('milliseconds', n) | ||
} | ||
get clone() { | ||
return new Date2(this.date) | ||
} | ||
|
||
_proxy(name, n, offset = 0) { | ||
if (n === undefined) { | ||
return this.date[`get${capitalize(name)}`]() + offset | ||
} else { | ||
let d = this.clone | ||
d.date[`set${capitalize(name)}`](n - offset) | ||
return d | ||
} | ||
} | ||
isSameMonthAs(date) { | ||
return this.year() === date.getFullYear() && this.month() === date.getMonth() + 1 | ||
} | ||
isSameDayAs(date) { | ||
return this.isSameMonthAs(date) && this.day() === date.getDate() | ||
} | ||
} | ||
|
||
function capitalize(string) { | ||
return string.charAt(0).toUpperCase() + string.slice(1) | ||
} | ||
|
||
window.Date2 = Date2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters