diff --git a/CHANGELOG.md b/CHANGELOG.md index e305ac600..b7beca335 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ -# v0.6.0 +# v0.6.1 ## Bug Fixes +`v-date-picker` +* Prevent bug causing infinite update cycle loop and locking the browser when using `disabled-dates`. Closes #61. + +## Improvements +`v-calendar` +* Improve efficiency of date intersection detection logic. +# v0.6.0 +## Bug Fixes `v-date-picker` * Bug: `fromPage` and `toPage` not updating when new date was assigned or selected. Fix: `fromPage` and `toPage` are updated when new value is assigned, if needed. Closes #51. @@ -8,13 +16,10 @@ Fix: When clearing out input element, date is cleared or reverts to previous value, depending on `is-required` prop or if dragging in `"range"` mode. Closes #54. ## Improvements - * Add Finnish translation to locales - `v-calendar` -### Props -* Rename `popover-header` slot name to `day-popover-header` to more clearly identify slot target ### Slots +* Rename `popover-header` slot name to `day-popover-header` to more clearly identify slot target * Add `day-popover-footer` slot for day popover footers * `day-popover-header`, `day-popover-footer` and custom popover slots accept `day` prop instead of `day-info` prop ### Events diff --git a/package.json b/package.json index cd640af87..4313861d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "v-calendar", - "version": "0.6.0", + "version": "0.6.1", "description": "A clean and extendable plugin for building simple attributed calendars in Vue.js.", "keywords": [ "vue", @@ -13,7 +13,7 @@ "bars", "indicators" ], - "homepage": "https://vcalendar.netlify.com", + "homepage": "https://vcalendar.io", "author": "Nathan Reyes ", "main": "lib/v-calendar.min.js", "files": [ diff --git a/src/components/DatePicker.vue b/src/components/DatePicker.vue index 9f92c2594..bff7a0a17 100755 --- a/src/components/DatePicker.vue +++ b/src/components/DatePicker.vue @@ -155,6 +155,7 @@ export default { ...(this.disabledAttribute || resolveDefault(defaults.datePickerDisabledAttribute, this.attributeParams)), dates: this.disabledDates_, excludeDates: this.availableDates, + excludeMode: 'includes', }); }, inputProps_() { @@ -333,7 +334,8 @@ export default { // Keep the popover open because something they entered was modified this.disablePopoverForceHidden = true; } - this.$emit('input', filteredValue); + // Emit event to update value if it has changed + if (!this.profile.valuesAreEqual(filteredValue, this.value)) this.$emit('input', filteredValue); // Blur the input if it is visible if (this.$refs.input) this.$refs.input.blur(); // Update input text for good measure diff --git a/src/components/DateRangePicker.vue b/src/components/DateRangePicker.vue index 265878143..c7a8a7df8 100755 --- a/src/components/DateRangePicker.vue +++ b/src/components/DateRangePicker.vue @@ -118,7 +118,7 @@ export default { } }, dateIsValid(date) { - return !(this.disabledAttribute && this.disabledAttribute.intersectsDate(date)); + return !this.disabledAttribute || !this.disabledAttribute.intersectsDate(date); }, }, }; diff --git a/src/utils/attribute.js b/src/utils/attribute.js index 3015cecb6..c0d8f3c87 100644 --- a/src/utils/attribute.js +++ b/src/utils/attribute.js @@ -10,6 +10,7 @@ const Attribute = (config) => { if (config.excludeDates && !isArray(config.excludeDates)) config.excludeDates = [config.excludeDates]; const hasDates = arrayHasItems(config.dates); const hasExcludeDates = arrayHasItems(config.excludeDates); + const excludeMode = config.excludeMode || 'intersects'; const dates = ( (hasDates && config.dates) || // Use provided dates if they have items @@ -33,35 +34,19 @@ const Attribute = (config) => { dates, excludeDates, isComplex, - // Any date partly intersects with given date - intersectsDate: date => dates.find((d) => { - // Date doesn't match - if (!d.intersectsDate(date)) return null; - // No exclude dates to check - just return first match - if (!hasExcludeDates) return d; - // Return match date if test date doesn't intersect any excluded dates - return excludeDates.find(ed => ed.intersectsDate(date)) ? false : d; - }) || false, // Accepts: Date or date range object - // Returns: First attribute date info that occurs on given date - includesDate: date => dates.find((d) => { - // Date doesn't match - if (!d.includesDate(date)) return null; - // No exclude dates to check - just return first match - if (!hasExcludeDates) return d; - // Return match date if test date doesn't intersect any excluded dates - return excludeDates.find(ed => ed.intersectsDate(date)) ? false : d; - }) || false, + // Returns: First attribute date info that partially intersects the given date + intersectsDate: date => !attr.excludesDate(date) && (dates.find(d => d.intersectsDate(date)) || false), + // Accepts: Date or date range object + // Returns: First attribute date info that completely includes the given date + includesDate: date => !attr.excludesDate(date) && (dates.find(d => d.includesDate(date)) || false), + excludesDate: date => hasExcludeDates && excludeDates.find(ed => + (excludeMode === 'intersects' && ed.intersectsDate(date)) || + (excludeMode === 'includes' && ed.includesDate(date))), // Accepts: Day object // Returns: First attribute date info that occurs on given day. - includesDay: day => dates.find((d) => { - // Date doesn't match - if (!d.includesDay(day)) return null; - // No exclude dates to check - just return first match - if (!hasExcludeDates) return d; - // Return match date if test day doesn't intersect any excluded dates - return excludeDates.find(ed => ed.includesDay(day)) ? false : d; - }) || false, + includesDay: day => !attr.excludesDay(day) && (dates.find(d => d.includesDay(day)) || false), + excludesDay: day => hasExcludeDates && excludeDates.find(ed => ed.includesDay(day)), }; mixinOptionalProps(config, attr, [ { name: 'highlight', mixin: defaults.highlight },