Replace datepicker with flatpicker

This commit is contained in:
Björn Fromme
2018-09-13 18:59:32 +02:00
parent 3afb5a7fd6
commit 63361dd524
9 changed files with 64 additions and 223 deletions
+5
View File
@@ -3176,6 +3176,11 @@
"locate-path": "^2.0.0" "locate-path": "^2.0.0"
} }
}, },
"flatpickr": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.5.2.tgz",
"integrity": "sha512-jDy4QYGpmiy7+Qk8QvKJ4spjDdxcx9cxMydmq1x427HkKWBw0qizLYeYM2F6tMcvvqGjU5VpJS55j4LnsaBblA=="
},
"flatten": { "flatten": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
+2 -1
View File
@@ -11,11 +11,12 @@
}, },
"dependencies": { "dependencies": {
"@fancyapps/fancybox": "^3.2.5", "@fancyapps/fancybox": "^3.2.5",
"@fengyuanchen/datepicker": "^0.6.4", "@fengyuanchen/datepicker": "^0.6.5",
"bootstrap-sass": "^3.3.7", "bootstrap-sass": "^3.3.7",
"bourbon": "^4.3.2", "bourbon": "^4.3.2",
"cookieconsent": "^3.1.0", "cookieconsent": "^3.1.0",
"dayjs": "^1.7.5", "dayjs": "^1.7.5",
"flatpickr": "^4.5.2",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"iframe-resizer": "^3.6.1", "iframe-resizer": "^3.6.1",
"jquery": "^2.2.4", "jquery": "^2.2.4",
@@ -5,3 +5,4 @@ require('cookieconsent/build/cookieconsent.min.css');
require('@fancyapps/fancybox/dist/jquery.fancybox.min.css'); require('@fancyapps/fancybox/dist/jquery.fancybox.min.css');
require('slick-carousel/slick/slick.css'); require('slick-carousel/slick/slick.css');
require('leaflet/dist/leaflet.css'); require('leaflet/dist/leaflet.css');
require('flatpickr/dist/flatpickr.css');
@@ -1,77 +0,0 @@
<template>
<input ref="field" type="text" :value="dateDisplayed" />
</template>
<script>
import Vue from 'vue'
import $ from 'jquery'
import dayjs from 'dayjs'
import 'dayjs/locale/de'
import datepicker from '@fengyuanchen/datepicker'
require('@fengyuanchen/datepicker/dist/datepicker.css');
export default {
props: {
date: {
default: null
},
minDate: {
type: Date,
default () {
return new Date()
}
},
maxDate: {
type: Date,
default () {
return new Date()
}
},
container: {
type: String,
required: true
}
},
computed: {
dateDisplayed () {
if (this.date === null) {
return '';
}
return dayjs(this.date).format('DD.MM.YYYY');
}
},
watch: {
date (value) {
this.date = value;
},
minDate (value) {
$(this.$refs.field).datepicker('setStartDate', value);
},
maxDate (value) {
$(this.$refs.field).datepicker('setEndDate', value);
}
},
mounted () {
const field = this.$refs.field;
Vue.nextTick(() => {
$(field).datepicker({
inline: true,
container: $(field).closest(this.container),
language: 'de-DE',
format: 'dd.mm.yyyy',
weekStart: 1,
days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
daysShort: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
daysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September',
'Oktober', 'November', 'Dezember'],
monthsShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
startDate: this.minDate,
endDate: this.maxDate
}).on('pick.datepicker', (event) => {
this.$emit('picked', event.date);
});
});
}
}
</script>
@@ -4,13 +4,13 @@
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="dropdown" ref="dropdown"> <li class="dropdown" ref="dropdown">
<input type="text" class="form-control" placeholder="von... bis" <input type="text" class="form-control" placeholder="von... bis"
v-bind:value="selectedRange" v-on:click="togglePanel"/> :value="selectedRange" @click="togglePanel"/>
<ul class="dropdown-menu daterange"> <ul class="dropdown-menu daterange">
<li v-if="presets"> <li v-if="presets">
<div class="daterange__presets"> <div class="daterange__presets">
<template v-for="preset of presets"> <template v-for="preset of presets">
<a class="daterange__preset" href="#" <a class="daterange__preset" href="#"
v-on:click.prevent="selectPreset(preset)"> @click.prevent="selectPreset(preset)">
<i class="fa fa-calendar"></i> {{ preset.label }} <i class="fa fa-calendar"></i> {{ preset.label }}
</a> </a>
</template> </template>
@@ -18,44 +18,11 @@
</li> </li>
<li> <li>
<div class="daterange__panel"> <div class="daterange__panel">
<div class="daterange__column daterange--from"> <input ref="field" type="hidden">
<span class="headline headline--4 daterange__headline">Früheste Anreise</span>
<div class="daterange__picker">
<date-picker
class="daterange__input"
container=".daterange--from"
v-on:picked="updateFrom"
v-bind:date="range.from"
v-bind:min-date="dateFromMin"
v-bind:max-date="dateFromMax"
></date-picker>
<button class="daterange__button"
v-on:click.prevent="resetFrom">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="daterange__column daterange--to">
<span class="headline headline--4 daterange__headline">Späteste Abreise</span>
<div class="daterange__picker">
<date-picker
class="daterange__input"
container=".daterange--to"
v-on:picked="updateTo"
v-bind:date="range.to"
v-bind:min-date="dateToMin"
v-bind:max-date="dateToMax"
></date-picker>
<button class="daterange__button"
v-on:click.prevent="resetTo">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
</div> </div>
</li> </li>
<li class="closebtn"> <li class="closebtn">
<a class="btn btn-default btn-xs" href="#" v-on:click.prevent="togglePanel">schließen</a> <a class="btn btn-default btn-xs" href="#" @click.prevent="togglePanel">schließen</a>
</li> </li>
</ul> </ul>
</li> </li>
@@ -64,25 +31,17 @@
</template> </template>
<script> <script>
import Vue from 'vue'
import $ from 'jquery' import $ from 'jquery'
import DatePicker from './Datepicker.vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import 'dayjs/locale/de' import 'dayjs/locale/de'
import flatpickr from 'flatpickr'
import { German } from 'flatpickr/dist/l10n/de'
export default { export default {
components: {
DatePicker
},
data () { data () {
return { return {
dateFromMin: null, picker: null,
dateFromMax: null,
dateToMin: null,
dateToMax: null,
range: {
from: null,
to: null
},
selectedFrom: this.from, selectedFrom: this.from,
selectedTo: this.to selectedTo: this.to
} }
@@ -116,76 +75,53 @@
} }
}, },
created () { created () {
this.range.from = this.selectedFrom !== null ? new Date(this.selectedFrom) : null; Vue.nextTick(() => {
this.range.to = this.selectedTo !== null ? new Date(this.selectedTo) : null; this.picker = $(this.$refs.field).flatpickr({
this.dateFromMin = new Date(this.minDate); mode: 'range',
this.dateFromMax = new Date(this.maxDate); dateFormat: 'd.m.Y',
this.dateToMin = new Date(this.minDate); locale: German,
this.dateToMax = new Date(this.maxDate); inline: true,
}, minDate: new Date(this.minDate),
watch: { maxDate: new Date(this.maxDate),
from (value) { onChange: (selectedDates) => {
this.selectedFrom = value; if (selectedDates.length === 2) {
}, this.selectedFrom = selectedDates[0];
to (value) { this.selectedTo = selectedDates[1];
this.selectedTo = value; this.togglePanel();
}, this.$emit('selected', { from: this.selectedFrom, to: this.selectedTo });
minDate (date) {
this.dateFromMin = new Date(date);
this.dateToMin = new Date(date);
},
maxDate (date) {
this.dateFromMax = new Date(date);
this.dateToMax = new Date(date);
} }
}
});
if (this.from && this.to) {
this.picker.setDate([ new Date(this.from), new Date(this.to) ]);
}
})
}, },
computed: { computed: {
selectedRange () { selectedRange () {
if (this.range.from == null && this.range.to == null) { if (this.selectedFrom == null && this.selectedTo == null) {
return ''; return '';
} }
if (this.range.from !== null && this.range.to === null) { if (this.selectedFrom !== null && this.selectedTo === null) {
return 'ab ' + dayjs(this.range.from).format('DD.MM.YYYY'); return 'ab ' + dayjs(this.selectedFrom).format('DD.MM.YYYY');
} }
if (this.range.from === null && this.range.to !== null) { if (this.selectedFrom === null && this.selectedTo !== null) {
return 'bis ' + dayjs(this.range.to).format('DD.MM.YYYY'); return 'bis ' + dayjs(this.selectedTo).format('DD.MM.YYYY');
} }
return dayjs(this.range.from).format('DD.MM.YYYY') + '-' + dayjs(this.range.to).format('DD.MM.YYYY'); return dayjs(this.selectedFrom).format('DD.MM.YYYY')
+ '-' + dayjs(this.selectedTo).format('DD.MM.YYYY');
} }
}, },
methods: { methods: {
updateFrom (date) {
if (this.range.to !== null && dayjs(date).isAfter(this.range.to)) {
this.range.to = dayjs(date).add(1, 'd');
}
this.range.from = date;
this.dateToMin = date;
this.$emit('selected', this.range);
},
updateTo (date) {
if (this.range.from !== null && dayjs(date).isBefore(this.range.from)) {
date = dayjs(this.range.from).add(1, 'd');
}
this.range.to = date;
this.dateFromMax = date;
this.$emit('selected', this.range);
},
togglePanel () { togglePanel () {
$(this.$refs.dropdown).toggleClass('open'); $(this.$refs.dropdown).toggleClass('open');
}, },
resetFrom () {
this.range.from = null;
this.$emit('selected', this.range);
},
resetTo () {
this.range.to = null;
this.$emit('selected', this.range);
},
selectPreset (preset) { selectPreset (preset) {
this.range.from = new Date(preset.dateFrom); this.selectedFrom = new Date(preset.dateFrom);
this.range.to = new Date(preset.dateTo); this.selectedTo = new Date(preset.dateTo);
this.picker.setDate([ this.selectedFrom, this.selectedTo ]);
this.togglePanel(); this.togglePanel();
this.$emit('selected', this.range); this.$emit('selected', { from: this.selectedFrom, to: this.selectedTo });
} }
} }
} }
@@ -16,13 +16,6 @@
}, },
data () { data () {
return { return {
lock: false,
dateRange () {
return {
dateFrom: null,
dateTo: null
}
},
searchParams: this.initialSearchParams, searchParams: this.initialSearchParams,
filterOptions: this.initialFilterOptions filterOptions: this.initialFilterOptions
} }
@@ -30,15 +23,10 @@
props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ], props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ],
methods: { methods: {
loadOptions () { loadOptions () {
if (this.lock) {
return;
}
this.lock = true;
const query = {}; const query = {};
query[this.argumentPrefix + '[searchParams]'] = this.searchParams; query[this.argumentPrefix + '[searchParams]'] = this.searchParams;
$.post(this.optionsUri, query, (json) => { $.post(this.optionsUri, query, (json) => {
this.applyOptions(json); this.applyOptions(json);
this.lock = false;
}, 'json'); }, 'json');
}, },
applyOptions (json) { applyOptions (json) {
@@ -10,7 +10,6 @@
}, },
data () { data () {
return { return {
lock: false,
searchParams: this.initialSearchParams, searchParams: this.initialSearchParams,
filterOptions: this.initialFilterOptions filterOptions: this.initialFilterOptions
} }
@@ -18,15 +17,10 @@
props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ], props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ],
methods: { methods: {
loadOptions () { loadOptions () {
if (this.lock) {
return;
}
this.lock = true;
const query = {}; const query = {};
query[this.argumentPrefix + '[searchParams]'] = this.searchParams; query[this.argumentPrefix + '[searchParams]'] = this.searchParams;
$.post(this.optionsUri, query, (json) => { $.post(this.optionsUri, query, (json) => {
this.applyOptions(json); this.applyOptions(json);
this.lock = false;
}, 'json'); }, 'json');
}, },
applyOptions (json) { applyOptions (json) {
@@ -12,16 +12,6 @@
text-align: center; text-align: center;
} }
.daterange__column {
flex: 1;
&:first-child {
border-right: 1px solid #c7c7c7;
margin-right: 10px;
}
}
.daterange__presets { .daterange__presets {
display: flex; display: flex;
padding: 8px 0; padding: 8px 0;
@@ -32,21 +22,24 @@
color: $color-font-base; color: $color-font-base;
} }
.daterange__picker {
display: flex;
flex-wrap: nowrap;
}
.daterange__input {
text-align: center;
background-color: white;
border: 1px solid $color-grey-light;
color: $color-font-base;
}
.daterange__button { .daterange__button {
color: $color-font-base; color: $color-font-base;
border: none; border: none;
background: none; background: none;
outline: none; outline: none;
} }
.flatpickr-input {
display: none;
}
.flatpickr-calendar {
box-shadow: none;
}
.flatpickr-day.selected {
&.startRange, &.endRange {
background: $color-brand-secondary;
border-color: $color-brand-secondary;
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ Encore
.addEntry('unichamp', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/unichamp.js') .addEntry('unichamp', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/unichamp.js')
.addStyleEntry('rte', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/css/rte.css') .addStyleEntry('rte', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/css/rte.css')
.createSharedEntry('vendor', [ .createSharedEntry('vendor', [
'jquery', 'vue', 'vue-session', '@fengyuanchen/datepicker', 'jquery-lazy', 'jquery', 'vue', 'vue-session', 'flatpickr', 'jquery-lazy',
'bootstrap-sass/assets/javascripts/bootstrap', 'slick-carousel', 'bootstrap-sass/assets/javascripts/bootstrap', 'slick-carousel',
'dayjs', 'cookieconsent', 'picturefill', '@fancyapps/fancybox', 'leaflet' 'dayjs', 'cookieconsent', 'picturefill', '@fancyapps/fancybox', 'leaflet'
]) ])