前回(vuetifyのv-calendarで土日の色を変える)の続きです。
前提
vue: 2.6.11
vuetify: 2.6.0
手順
祝日ライブラリーの選定
JavaScriptで日本の祝日を扱うライブラリ5選を参考にし
今回は japanese-holidays-js 使うこととしました。
採用理由
- 2020年のオリンピック特例も対応されており、メンテナンスがされていること
- ライブラリの容量が軽いこと
祝日ライブラリーを設定する
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
+ <script src="https://cdn.rawgit.com/osamutake/japanese-holidays-js/v1.0.10/lib/japanese-holidays.min.js"></script>
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
+ <script>
+ const getJPHoliday = function(year) {
+ return JapaneseHolidays.getHolidaysOf(year)
+ }
+ </script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
+ <App :get-jp-holiday-list="getJPHoliday"></App>
</div>
<!-- built files will be auto injected -->
</body>
</html>
vueの中ではライブラリを設定することができないので、index.htmlで設定し、vueに渡します。
JapaneseHolidays.getHolidaysOf
でその年の祝日の月・日・祝日名を配列で取得します。
<script>
export default {
name: 'App',
+ props: ['getJPHolidayList'],
methods:{
changeColor: function () {
setTimeout(() => {
const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__week'))
dayList.map(el => {
el.children[0].classList.add('sunday')
el.children[6].classList.add('saturday')
})
}, 200)
+ // eslint-disable-next-line no-undef
+ const holidaysOfYear = getJPHoliday(2022);
+ console.log(holidaysOfYear)
}
},
};
</script>
+
が前回土日カレンダーから変更した箇所です。
これで、console.log(holidaysOfYear)
で2022年の祝日を配列で取得することを確認することができました。
const holidaysOfYear = getJPHoliday(2022);
がeslintでエラーが出てしまったので、例外的に下記のコメントを入れてエラーを回避してます。
// eslint-disable-next-line no-undef
祝日を抽出する
methods:{
changeColor: function () {
setTimeout(() => {
const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__week'))
dayList.map(el => {
el.children[0].classList.add('sunday')
el.children[6].classList.add('saturday')
})
}, 200)
// eslint-disable-next-line no-undef
const holidaysOfYear = getJPHoliday(2022);
console.log(holidaysOfYear)
+ const holidayList = holidaysOfYear.filter(holiday => {
+ if (holiday.month == 7) {
+ return holiday
+ }
+ })
+ console.log("holidayList:",holidayList)
今月(2022/7)の祝日を抽出します。
祝日に背景色を設定
const holidayList = holidaysOfYear.filter(holiday => {
if (holiday.month == 7) {
return holiday
}
})
+ setTimeout(() => {
+ const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__day'))
+ .filter(el => !el.classList.contains('v-outside'))
+ for (let [i, dayEl] of dayList.entries()) {
+ let dayNum = i + 1
+ holidayList.forEach((holiday) => {
+ if (holiday.date === dayNum) {
+ dayEl.classList.add('holiday');
+ }
+ })
+ }
+ }, 200)
v-outside
は当月ではない日付の部分なので、こちらは排除します。
entriesでkey, valueをそれぞれ取得し、取得した祝日のdateとkeyが一緒であれば、classListにholiday
を追加します。
完成
最終形のソースはこちらです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<script src="https://cdn.rawgit.com/osamutake/japanese-holidays-js/v1.0.10/lib/japanese-holidays.min.js"></script>
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
<script>
const getJPHoliday = function(year) {
return JapaneseHolidays.getHolidaysOf(year)
}
</script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
<App :get-jp-holiday-list="getJPHoliday"></App>
</div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<v-app>
<div>
<v-sheet height="94vh">
<v-calendar ref="calendar" @change="changeColor"></v-calendar>
</v-sheet>
</div>
</v-app>
</template>
<script>
export default {
name: 'App',
props: ['getJPHolidayList'],
methods:{
changeColor: function () {
setTimeout(() => {
const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__week'))
dayList.map(el => {
el.children[0].classList.add('sunday')
el.children[6].classList.add('saturday')
})
}, 200)
// eslint-disable-next-line no-undef
const holidaysOfYear = getJPHoliday(2022);
const holidayList = holidaysOfYear.filter(holiday => {
if (holiday.month == 7) {
return holiday
}
})
setTimeout(() => {
const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__day'))
.filter(el => !el.classList.contains('v-outside'))
for (let [i, dayEl] of dayList.entries()) {
let dayNum = i + 1
holidayList.forEach((holiday) => {
if (holiday.date === dayNum) {
dayEl.classList.add('holiday');
}
})
}
}, 200)
}
},
};
</script>
<style>
.saturday {
background: rgba(0, 0, 255, .1);
}
.sunday {
background: rgba(255, 0, 0, .1);
}
.holiday {
background: rgba(255, 0, 0, .3);
}
</style>
感想
意外と探せばあるようでなかったので、今回は土日編と祝日編に分けて記事を書かせていただきました。
この記事では今月(2022年7月)の祝日に色を塗るだけでしたが、moment.jsなどを使って、カレンダーの月が変わったらその都度取得するようにしたり、祝日名も取得できるので、ラベルで祝日を出してもいいかもしれません。
moment.jsをかなり苦戦した部分もあるので、いつか記事にできたらなと思います。
お付き合いいただき、ありがとうございました。