@afeefa/vue-app 0.0.132 → 0.0.133
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.133
|
package/package.json
CHANGED
@@ -1,38 +1,44 @@
|
|
1
1
|
<template>
|
2
|
-
<
|
3
|
-
v-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
:readonly="type === 'month'"
|
19
|
-
v-on="on"
|
20
|
-
@input="dateInputChanged"
|
21
|
-
@click:clear="clearDate"
|
22
|
-
@click.native="on.click"
|
23
|
-
/>
|
24
|
-
</template>
|
25
|
-
|
26
|
-
<v-date-picker
|
27
|
-
v-if="menu"
|
28
|
-
:value="date"
|
29
|
-
no-title
|
30
|
-
:type="type"
|
31
|
-
v-bind="$attrs"
|
32
|
-
:first-day-of-week="1"
|
33
|
-
@input="dateChanged"
|
2
|
+
<div :class="['a-date-picker', {'type--month': type === 'month'}]">
|
3
|
+
<v-text-field
|
4
|
+
ref="input"
|
5
|
+
:value="formattedDate"
|
6
|
+
:label="label"
|
7
|
+
:placeholder="type === 'month' ? '' : 'DD.MM.JJJJ'"
|
8
|
+
:style="cwm_widthStyle"
|
9
|
+
v-bind="{...$attrs, dense, outlined}"
|
10
|
+
:error-messages="errorMessages"
|
11
|
+
append-icon="$calendarIcon"
|
12
|
+
:readonly="type === 'month'"
|
13
|
+
:clearable="clearable"
|
14
|
+
@input="dateInputChanged"
|
15
|
+
@click:clear="clearDate"
|
16
|
+
@click:append="open"
|
17
|
+
@mouseup="openIfMonth"
|
34
18
|
/>
|
35
|
-
|
19
|
+
|
20
|
+
<v-overlay
|
21
|
+
:value="isOpen"
|
22
|
+
:z-index="299"
|
23
|
+
:opacity="0"
|
24
|
+
/>
|
25
|
+
|
26
|
+
<div :class="popUpCssClass">
|
27
|
+
<div
|
28
|
+
v-if="isOpen"
|
29
|
+
class="popUpContent elevation-6"
|
30
|
+
>
|
31
|
+
<v-date-picker
|
32
|
+
:value="date"
|
33
|
+
no-title
|
34
|
+
:type="type"
|
35
|
+
v-bind="$attrs"
|
36
|
+
:first-day-of-week="1"
|
37
|
+
@input="dateChanged"
|
38
|
+
/>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
</div>
|
36
42
|
</template>
|
37
43
|
|
38
44
|
|
@@ -40,22 +46,22 @@
|
|
40
46
|
import { Component, Mixins, Watch } from '@a-vue'
|
41
47
|
import { formatDate } from '@a-vue/utils/format-date'
|
42
48
|
import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
|
49
|
+
import { UsesPositionServiceMixin } from '../services/position/UsesPositionServiceMixin'
|
50
|
+
import { CancelOnEscMixin } from '@a-vue/services/escape/CancelOnEscMixin'
|
51
|
+
import { PositionConfig } from '../services/PositionService'
|
52
|
+
import { randomCssClass } from '../utils/random'
|
43
53
|
|
44
54
|
@Component({
|
45
55
|
props: ['value', 'validator', 'type', {dense: true, outlined: true}]
|
46
56
|
})
|
47
|
-
export default class ADatePicker extends Mixins(ComponentWidthMixin) {
|
57
|
+
export default class ADatePicker extends Mixins(ComponentWidthMixin, UsesPositionServiceMixin, CancelOnEscMixin) {
|
48
58
|
value_ = null
|
49
|
-
menu = false
|
50
59
|
errorMessages = []
|
60
|
+
popUpId = randomCssClass(10)
|
61
|
+
isOpen = false
|
51
62
|
|
52
63
|
created () {
|
53
|
-
|
54
|
-
this.value_ = this.value
|
55
|
-
} else {
|
56
|
-
this.value_Changed() // force validation if date is null
|
57
|
-
}
|
58
|
-
this.$emit('input', this.value_)
|
64
|
+
this.value_ = this.value
|
59
65
|
}
|
60
66
|
|
61
67
|
mounted () {
|
@@ -65,27 +71,112 @@ export default class ADatePicker extends Mixins(ComponentWidthMixin) {
|
|
65
71
|
@Watch('value')
|
66
72
|
valueChanged () {
|
67
73
|
this.value_ = this.value
|
74
|
+
this.validate()
|
68
75
|
}
|
69
76
|
|
70
|
-
|
71
|
-
|
72
|
-
|
77
|
+
get clearable () {
|
78
|
+
if (this.validator && this.validator.param('null') === false) {
|
79
|
+
return false
|
80
|
+
}
|
81
|
+
return true
|
73
82
|
}
|
74
83
|
|
75
|
-
|
76
|
-
this.
|
77
|
-
|
78
|
-
const rules = this.validator.getRules(this.label)
|
79
|
-
for (const rule of rules) {
|
80
|
-
const message = rule(this.value_)
|
81
|
-
if (typeof message === 'string') {
|
82
|
-
this.errorMessages.push(message)
|
83
|
-
break
|
84
|
-
}
|
85
|
-
}
|
84
|
+
openIfMonth () {
|
85
|
+
if (this.type === 'month') {
|
86
|
+
this.open()
|
86
87
|
}
|
87
88
|
}
|
88
89
|
|
90
|
+
open () {
|
91
|
+
window.addEventListener('mousedown', this.onClickOutside)
|
92
|
+
|
93
|
+
const container = this.getContainer()
|
94
|
+
|
95
|
+
container.appendChild(this.popUp)
|
96
|
+
this.positionize()
|
97
|
+
|
98
|
+
this.isOpen = true
|
99
|
+
|
100
|
+
this.coe_watchCancel()
|
101
|
+
|
102
|
+
this.$emit('open')
|
103
|
+
}
|
104
|
+
|
105
|
+
close () {
|
106
|
+
if (!this.isOpen) {
|
107
|
+
return
|
108
|
+
}
|
109
|
+
|
110
|
+
this.urp_unregisterPositionWatchers()
|
111
|
+
|
112
|
+
window.removeEventListener('mousedown', this.onClickOutside)
|
113
|
+
|
114
|
+
this.$el.appendChild(this.popUp)
|
115
|
+
|
116
|
+
this.isOpen = false
|
117
|
+
|
118
|
+
this.coe_unwatchCancel()
|
119
|
+
|
120
|
+
this.$emit('close')
|
121
|
+
}
|
122
|
+
|
123
|
+
positionize () {
|
124
|
+
const position = new PositionConfig()
|
125
|
+
.setAnchor(this.$refs.input, '.v-input__slot')
|
126
|
+
.setTarget(
|
127
|
+
document.documentElement,
|
128
|
+
'.' + this.popUpCssClass + ' .popUpContent'
|
129
|
+
)
|
130
|
+
.targetTop()
|
131
|
+
.anchorBottom()
|
132
|
+
.diffY('.5rem')
|
133
|
+
.alternativeY(p => {
|
134
|
+
p.targetBottom().anchorTop().diffY('-.5rem')
|
135
|
+
})
|
136
|
+
|
137
|
+
this.urp_registerPositionWatcher(position)
|
138
|
+
}
|
139
|
+
|
140
|
+
get popUpCssClass () {
|
141
|
+
return 'popUp-' + this.popUpId
|
142
|
+
}
|
143
|
+
|
144
|
+
getContainer () {
|
145
|
+
return document.querySelector('.v-application')
|
146
|
+
}
|
147
|
+
|
148
|
+
get popUp () {
|
149
|
+
const container = this.getContainer()
|
150
|
+
return container.querySelector('.' + this.popUpCssClass)
|
151
|
+
}
|
152
|
+
|
153
|
+
coe_cancelOnEsc () {
|
154
|
+
this.close()
|
155
|
+
return false // stop esc propagation
|
156
|
+
}
|
157
|
+
|
158
|
+
onClickOutside (e) {
|
159
|
+
const popUp = this.popUp
|
160
|
+
|
161
|
+
// no popup present
|
162
|
+
if (!popUp) {
|
163
|
+
return
|
164
|
+
}
|
165
|
+
|
166
|
+
// popup clicked
|
167
|
+
if (popUp.contains(e.target)) {
|
168
|
+
return
|
169
|
+
}
|
170
|
+
|
171
|
+
// activator clicked
|
172
|
+
const activator = this.$refs.input.$el
|
173
|
+
if (activator && activator.contains(e.target)) {
|
174
|
+
return
|
175
|
+
}
|
176
|
+
|
177
|
+
this.close()
|
178
|
+
}
|
179
|
+
|
89
180
|
get date () {
|
90
181
|
return this.value_
|
91
182
|
? this.value_.toISOString().substr(0, this.type === 'month' ? 7 : 10)
|
@@ -98,25 +189,28 @@ export default class ADatePicker extends Mixins(ComponentWidthMixin) {
|
|
98
189
|
|
99
190
|
clearDate () {
|
100
191
|
this.value_ = null
|
192
|
+
this.validate()
|
101
193
|
this.$emit('input', this.value_)
|
102
194
|
}
|
103
195
|
|
104
|
-
|
196
|
+
textInputIsDate (value) {
|
105
197
|
return value && value.match(/^(3[01]|[12][0-9]|0?[1-9]).(1[012]|0?[1-9]).((?:19|20)\d{2})$/)
|
106
198
|
}
|
107
199
|
|
108
200
|
dateInputChanged (value) {
|
109
201
|
if (!value) {
|
110
202
|
this.dateChanged(null)
|
111
|
-
} else if (this.
|
203
|
+
} else if (this.validateTextInput(value)) {
|
112
204
|
const [day, month, year] = value.split('.')
|
113
205
|
this.dateChanged(new Date(year + '-' + month + '-' + day))
|
114
206
|
}
|
115
207
|
}
|
116
208
|
|
117
209
|
dateChanged (date) {
|
118
|
-
this.menu = false
|
119
210
|
this.value_ = date ? new Date(date) : null
|
211
|
+
this.validate()
|
212
|
+
|
213
|
+
this.close()
|
120
214
|
this.$emit('input', this.value_)
|
121
215
|
}
|
122
216
|
|
@@ -133,31 +227,68 @@ export default class ADatePicker extends Mixins(ComponentWidthMixin) {
|
|
133
227
|
}
|
134
228
|
|
135
229
|
validate () {
|
136
|
-
this.
|
230
|
+
this.errorMessages = []
|
231
|
+
if (this.validator) {
|
232
|
+
const rules = this.validator.getRules(this.label)
|
233
|
+
for (const rule of rules) {
|
234
|
+
const message = rule(this.value_)
|
235
|
+
if (typeof message === 'string') {
|
236
|
+
this.errorMessages.push(message)
|
237
|
+
break
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
137
241
|
}
|
138
242
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
243
|
+
validateTextInput (value) {
|
244
|
+
this.errorMessages = []
|
245
|
+
const rules = this.textInputValidationRules
|
246
|
+
for (const rule of rules) {
|
247
|
+
const message = rule(value)
|
248
|
+
if (typeof message === 'string') {
|
249
|
+
this.errorMessages.push(message)
|
250
|
+
break
|
146
251
|
}
|
147
|
-
return [dateFormat]
|
148
252
|
}
|
253
|
+
return !this.errorMessages.length
|
254
|
+
}
|
255
|
+
|
256
|
+
get textInputValidationRules () {
|
257
|
+
if (this.type === 'month') {
|
258
|
+
return []
|
259
|
+
}
|
260
|
+
|
261
|
+
return [v => {
|
262
|
+
if (v && !this.textInputIsDate(v)) {
|
263
|
+
return 'Das Datum sollte das Format TT.MM.JJJJ haben.'
|
264
|
+
}
|
265
|
+
return true
|
266
|
+
}]
|
267
|
+
}
|
268
|
+
|
269
|
+
get dateValidationRules () {
|
270
|
+
if (this.validator) {
|
271
|
+
return this.validator.getRules(this.label)
|
272
|
+
}
|
273
|
+
return []
|
149
274
|
}
|
150
275
|
}
|
151
276
|
</script>
|
152
277
|
|
153
278
|
|
154
279
|
<style lang="scss" scoped>
|
155
|
-
|
156
|
-
|
280
|
+
.popUpContent {
|
281
|
+
min-height: 2.2rem;
|
282
|
+
position: absolute;
|
283
|
+
z-index: 400;
|
284
|
+
display: block;
|
285
|
+
background-color: white;
|
286
|
+
padding: .5rem;
|
287
|
+
transition: left .2s;
|
288
|
+
}
|
157
289
|
|
158
|
-
|
159
|
-
|
160
|
-
}
|
290
|
+
.a-date-picker.type--month :deep(input) {
|
291
|
+
cursor: pointer;
|
161
292
|
}
|
162
293
|
|
163
294
|
.v-text-field :deep(.v-input__icon--clear) { // always show clear icon, https://github.com/vuetifyjs/vuetify/pull/15876
|