hr-design-system-handlebars 1.113.10 → 1.113.12
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.
- package/CHANGELOG.md +24 -0
- package/dist/assets/brand/hessenschau/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr-bigband/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr-fernsehen/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr-inforadio/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr-rundfunkrat/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr-sinfonieorchester/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr-werbung/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr1/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr2/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr3/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/hr4/conf/locatags.merged.json +1 -0
- package/dist/assets/brand/you-fm/conf/locatags.merged.json +1 -0
- package/dist/assets/index.css +44 -3
- package/dist/assets/js/components/forms/js/contactForm.alpine.js +18 -17
- package/dist/assets/js/components/voting/js/votingCookieCheckerDs.feature.js +25 -0
- package/dist/assets/js/components/voting/js/votingDs.feature.js +214 -0
- package/dist/assets/js/components/voting/js/votingValidatorDs.feature.js +193 -0
- package/dist/views/components/forms/components/choice.hbs +2 -2
- package/dist/views/components/forms/components/choiceGroup.hbs +4 -2
- package/dist/views/components/forms/components/fields.hbs +3 -1
- package/dist/views/components/voting/components/voting_submit.hbs +4 -0
- package/dist/views/components/voting/voting.hbs +48 -7
- package/dist/views/components/voting/voting_result.hbs +3 -3
- package/dist/views_static/components/forms/components/choice.hbs +2 -2
- package/dist/views_static/components/forms/components/choiceGroup.hbs +4 -2
- package/dist/views_static/components/forms/components/fields.hbs +3 -1
- package/dist/views_static/components/voting/components/voting_submit.hbs +4 -0
- package/dist/views_static/components/voting/voting.hbs +48 -7
- package/dist/views_static/components/voting/voting_result.hbs +3 -3
- package/package.json +1 -1
- package/src/assets/brand/_default/conf/locatags.json +1 -0
- package/src/assets/brand/hessenschau/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr-bigband/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr-fernsehen/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr-inforadio/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr-rundfunkrat/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr-sinfonieorchester/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr-werbung/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr1/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr2/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr3/conf/locatags.merged.json +1 -0
- package/src/assets/brand/hr4/conf/locatags.merged.json +1 -0
- package/src/assets/brand/you-fm/conf/locatags.merged.json +1 -0
- package/src/assets/fixtures/voting/voting.inc.json +21 -5
- package/src/stories/views/components/forms/components/choice.hbs +2 -2
- package/src/stories/views/components/forms/components/choiceGroup.hbs +4 -2
- package/src/stories/views/components/forms/components/fields.hbs +3 -1
- package/src/stories/views/components/forms/js/contactForm.alpine.js +18 -17
- package/src/stories/views/components/voting/components/voting_submit.hbs +4 -0
- package/src/stories/views/components/voting/fixtures/voting.json +1 -1
- package/src/stories/views/components/voting/fixtures/voting_error.json +1 -1
- package/src/stories/views/components/voting/fixtures/voting_over.json +1 -1
- package/src/stories/views/components/voting/fixtures/voting_result_absolute.json +1 -1
- package/src/stories/views/components/voting/js/voteValidatorDs.js +195 -0
- package/src/stories/views/components/voting/js/votingCookieCheckerDs.feature.js +25 -0
- package/src/stories/views/components/voting/js/votingCookieCheckerDs.js +31 -0
- package/src/stories/views/components/voting/js/votingDs.feature.js +214 -0
- package/src/stories/views/components/voting/js/votingDs.js +198 -0
- package/src/stories/views/components/voting/js/votingValidatorDs.feature.js +193 -0
- package/src/stories/views/components/voting/voting.hbs +48 -7
- package/src/stories/views/components/voting/voting.stories.js +7 -0
- package/src/stories/views/components/voting/voting_result.hbs +3 -3
- package/src/stories/views/components/voting/voting_result.stories.js +0 -30
- /package/dist/views/components/voting/{voting_header.hbs → components/voting_header.hbs} +0 -0
- /package/dist/views_static/components/voting/{voting_header.hbs → components/voting_header.hbs} +0 -0
- /package/src/stories/views/components/voting/{voting_header.hbs → components/voting_header.hbs} +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { hr$, listen, replaceAnimated } from 'hrQuery'
|
|
2
|
+
import $ from 'zepto-modules'
|
|
3
|
+
|
|
4
|
+
require('zepto-modules/callbacks')
|
|
5
|
+
require('zepto-modules/deferred')
|
|
6
|
+
|
|
7
|
+
const Voting = (context) => {
|
|
8
|
+
const { options } = context
|
|
9
|
+
const { element: rootElement } = context
|
|
10
|
+
const jsonUrl = options.jsonURL,
|
|
11
|
+
votingWrapper = hr$('.js-voting-wrapper', rootElement)[0],
|
|
12
|
+
votingTmpl = votingWrapper.innerHTML,
|
|
13
|
+
ajaxTimeout = 60 * 1000,
|
|
14
|
+
responseFormatParam = 'rf=inline'
|
|
15
|
+
let ajaxOptions,
|
|
16
|
+
votingForm = hr$('.js-votingForm', rootElement)[0],
|
|
17
|
+
actionUrl = votingForm && votingForm.getAttribute('action'),
|
|
18
|
+
isPosting = false,
|
|
19
|
+
responseStatus,
|
|
20
|
+
validationErrors
|
|
21
|
+
|
|
22
|
+
const checkForJsonUrl = function () {
|
|
23
|
+
if (jsonUrl) {
|
|
24
|
+
actionUrl = jsonUrl
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const handleSubmit = function (event) {
|
|
29
|
+
if (event.target.matches('.js-votingForm')) {
|
|
30
|
+
submitForm(event)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const submitForm = function (event) {
|
|
34
|
+
event.preventDefault()
|
|
35
|
+
|
|
36
|
+
if (isPosting) {
|
|
37
|
+
return
|
|
38
|
+
} else {
|
|
39
|
+
isPosting = true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//jedes mal neu holen,
|
|
43
|
+
//da das DOM mit innerHTML ersetzt wird
|
|
44
|
+
votingForm = hr$('.js-votingForm', rootElement)[0]
|
|
45
|
+
|
|
46
|
+
console.log('DATA: ' + $(votingForm).serialize())
|
|
47
|
+
setAjaxOptions()
|
|
48
|
+
|
|
49
|
+
$.ajax(ajaxOptions)
|
|
50
|
+
|
|
51
|
+
//Add handlers to be called when the Deferred object is resolved.
|
|
52
|
+
.done(function (data, status, xhr) {
|
|
53
|
+
console.log('Done')
|
|
54
|
+
console.log(data)
|
|
55
|
+
|
|
56
|
+
if (jsonUrl) {
|
|
57
|
+
responseStatus = JSON.parse(data).status
|
|
58
|
+
switch (responseStatus) {
|
|
59
|
+
case 'VALIDATION_ERROR':
|
|
60
|
+
console.log('Validation Error')
|
|
61
|
+
validationErrors = JSON.parse(data).errors
|
|
62
|
+
handleValidationErrors(validationErrors)
|
|
63
|
+
break
|
|
64
|
+
case 'SERVER_ERROR':
|
|
65
|
+
replaceAnimated(
|
|
66
|
+
votingWrapper,
|
|
67
|
+
hr$('.js-errorMessage', rootElement)[0].innerHTML,
|
|
68
|
+
true,
|
|
69
|
+
scrollIntoVoting
|
|
70
|
+
)
|
|
71
|
+
break
|
|
72
|
+
case 'OK':
|
|
73
|
+
replaceAnimated(
|
|
74
|
+
votingWrapper,
|
|
75
|
+
hr$('.js-successMessage', rootElement)[0].innerHTML,
|
|
76
|
+
true,
|
|
77
|
+
scrollIntoVoting
|
|
78
|
+
)
|
|
79
|
+
break
|
|
80
|
+
default:
|
|
81
|
+
replaceAnimated(
|
|
82
|
+
votingWrapper,
|
|
83
|
+
hr$('.js-errorMessage', rootElement)[0].innerHTML,
|
|
84
|
+
true,
|
|
85
|
+
scrollIntoVoting
|
|
86
|
+
)
|
|
87
|
+
break
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
replaceAnimated(votingWrapper, data, true, scrollIntoVoting)
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
//Add handlers to be called when the Deferred object is rejected.
|
|
95
|
+
.fail(function (xhr, errorType, error) {
|
|
96
|
+
//anzeige irgendetwas hat nicht geklappt
|
|
97
|
+
console.log('Fail ' + errorType)
|
|
98
|
+
replaceAnimated(
|
|
99
|
+
votingWrapper,
|
|
100
|
+
hr$('.js-errorMessage', rootElement)[0].innerHTML,
|
|
101
|
+
true,
|
|
102
|
+
scrollIntoVoting
|
|
103
|
+
)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
//Add handlers to be called when the Deferred object is either resolved or rejected.
|
|
107
|
+
.always(function () {
|
|
108
|
+
//aufräumen wenn bedarf besteht.
|
|
109
|
+
console.log('Always')
|
|
110
|
+
|
|
111
|
+
isPosting = false
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const setAjaxOptions = function () {
|
|
116
|
+
ajaxOptions = {}
|
|
117
|
+
ajaxOptions.timeout = ajaxTimeout
|
|
118
|
+
|
|
119
|
+
ajaxOptions.type = 'POST'
|
|
120
|
+
ajaxOptions.url = actionUrl + '?' + responseFormatParam
|
|
121
|
+
ajaxOptions.data = $(votingForm).serialize()
|
|
122
|
+
ajaxOptions.contentType = 'application/x-www-form-urlencoded; charset=UTF-8'
|
|
123
|
+
ajaxOptions.dataType = ''
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const scrollIntoVoting = function (vertical) {
|
|
127
|
+
setTimeout(function () {
|
|
128
|
+
rootElement.scrollIntoView({
|
|
129
|
+
behavior: 'smooth',
|
|
130
|
+
block: 'center',
|
|
131
|
+
})
|
|
132
|
+
}, 850)
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Handles click events globally
|
|
136
|
+
* and delegates to concrete handlers
|
|
137
|
+
* on the basis of the event target.
|
|
138
|
+
* @see {@link https://gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-vanilla-js/} for further information.
|
|
139
|
+
* @param event
|
|
140
|
+
*/
|
|
141
|
+
const handleClick = function (event) {
|
|
142
|
+
if (event.target.matches('.js-formReload')) {
|
|
143
|
+
handleFormReload(event)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const handleFormReload = function (event) {
|
|
148
|
+
event.preventDefault()
|
|
149
|
+
replaceAnimated(votingWrapper, votingTmpl, true, scrollIntoVoting)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const handleKeydown = function (event) {
|
|
153
|
+
if (event.target.matches('.js-form-email')) {
|
|
154
|
+
event.stopPropagation()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const setValidationErrors = function (errors) {
|
|
159
|
+
let wrapperElement, errorElement, prop, InvalidFields
|
|
160
|
+
|
|
161
|
+
for (prop in errors) {
|
|
162
|
+
wrapperElement = rootElement.getElementsByClassName('js-wrapper-' + prop)[0]
|
|
163
|
+
errorElement = document.createElement('p')
|
|
164
|
+
|
|
165
|
+
InvalidFields = document.getElementsByName(prop)
|
|
166
|
+
for (let i = 0; i < InvalidFields.length; i++) {
|
|
167
|
+
if (wrapperElement.contains(InvalidFields[i])) {
|
|
168
|
+
InvalidFields[i].classList.add('is-invalid')
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
errorElement.innerHTML = options.errorMessages[errors[prop]]
|
|
173
|
+
errorElement.classList.add('c-form__errorMessage')
|
|
174
|
+
|
|
175
|
+
wrapperElement.insertBefore(errorElement, wrapperElement.firstChild)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const resetValidationErrors = function () {
|
|
180
|
+
let oldInvalidFields = hr$('.is-invalid', rootElement),
|
|
181
|
+
oldErrorMessages = hr$('.c-form__errorMessage', rootElement)
|
|
182
|
+
|
|
183
|
+
for (let i = 0; i < oldInvalidFields.length; i++) {
|
|
184
|
+
oldInvalidFields[i].classList.remove('is-invalid')
|
|
185
|
+
oldErrorMessages[i].parentNode.removeChild(oldErrorMessages[i])
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const handleValidationErrors = function (errors) {
|
|
190
|
+
resetValidationErrors()
|
|
191
|
+
setValidationErrors(errors)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const isFormAvailable = function () {
|
|
195
|
+
return !!votingForm
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!isFormAvailable()) {
|
|
199
|
+
//skip code execution
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
//init
|
|
204
|
+
votingWrapper.style.WebkitTransition = 'opacity 0.8s ease-in-out'
|
|
205
|
+
votingWrapper.style.MozTransition = 'opacity 0.8s ease-in-out'
|
|
206
|
+
votingWrapper.style.transition = 'opacity 0.8s ease-in-out'
|
|
207
|
+
|
|
208
|
+
checkForJsonUrl()
|
|
209
|
+
|
|
210
|
+
listen('submit', handleSubmit, rootElement)
|
|
211
|
+
listen('click', handleClick, rootElement)
|
|
212
|
+
listen('keydown', handleKeydown, rootElement)
|
|
213
|
+
}
|
|
214
|
+
export default Voting
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
var Voting =
|
|
2
|
+
Voting ||
|
|
3
|
+
function (options) {
|
|
4
|
+
'use strict'
|
|
5
|
+
|
|
6
|
+
var element = hr$(options.selector)[0],
|
|
7
|
+
settings = options.data ? JSON.parse(options.data) : {},
|
|
8
|
+
jsonURL = settings.jsonURL,
|
|
9
|
+
votingWrapper = hr$('.js-voting-wrapper', element)[0],
|
|
10
|
+
votingTmpl = votingWrapper.innerHTML,
|
|
11
|
+
votingForm = hr$('.js-votingForm', element)[0],
|
|
12
|
+
actionUrl = votingForm && votingForm.getAttribute('action'),
|
|
13
|
+
ajaxOptions,
|
|
14
|
+
ajaxTimeout = 60 * 1000,
|
|
15
|
+
responseFormatParam = 'rf=inline',
|
|
16
|
+
isPosting = false,
|
|
17
|
+
preloadIcon,
|
|
18
|
+
loadingIcon,
|
|
19
|
+
validationErrors,
|
|
20
|
+
responseStatus,
|
|
21
|
+
checkForJsonURL = function () {
|
|
22
|
+
if (jsonURL) {
|
|
23
|
+
actionUrl = jsonURL
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
handleSubmit = function (event) {
|
|
27
|
+
event.preventDefault()
|
|
28
|
+
|
|
29
|
+
if (isPosting) {
|
|
30
|
+
return
|
|
31
|
+
} else {
|
|
32
|
+
isPosting = true
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//jedes mal neu holen,
|
|
36
|
+
//da das DOM mit innerHTML ersetzt wird
|
|
37
|
+
votingForm = hr$('.js-votingForm', element)[0]
|
|
38
|
+
|
|
39
|
+
// preloadIcon = hr$('.js-preloadIcon', formWrapper)[0];
|
|
40
|
+
// loadingIcon = hr$('.js-loadingIcon', formWrapper)[0];
|
|
41
|
+
//
|
|
42
|
+
// preloadIcon.classList.add('-isHidden');
|
|
43
|
+
// loadingIcon.classList.remove('-isHidden');
|
|
44
|
+
|
|
45
|
+
console.log('DATA: ' + $(votingForm).serialize())
|
|
46
|
+
ajaxOptions = {}
|
|
47
|
+
ajaxOptions.timeout = ajaxTimeout
|
|
48
|
+
|
|
49
|
+
ajaxOptions.type = 'POST'
|
|
50
|
+
ajaxOptions.url = actionUrl + '?' + responseFormatParam
|
|
51
|
+
ajaxOptions.data = $(votingForm).serialize()
|
|
52
|
+
ajaxOptions.contentType = 'application/x-www-form-urlencoded; charset=UTF-8'
|
|
53
|
+
ajaxOptions.dataType = ''
|
|
54
|
+
|
|
55
|
+
$.ajax(ajaxOptions)
|
|
56
|
+
|
|
57
|
+
//Add handlers to be called when the Deferred object is resolved.
|
|
58
|
+
.done(function (data, status, xhr) {
|
|
59
|
+
console.log('Done')
|
|
60
|
+
console.log(data)
|
|
61
|
+
|
|
62
|
+
if (settings.jsonURL) {
|
|
63
|
+
responseStatus = JSON.parse(data).status
|
|
64
|
+
switch (responseStatus) {
|
|
65
|
+
case 'VALIDATION_ERROR':
|
|
66
|
+
console.log('Validation Error')
|
|
67
|
+
validationErrors = JSON.parse(data).errors
|
|
68
|
+
handleValidationErrors(validationErrors)
|
|
69
|
+
break
|
|
70
|
+
case 'SERVER_ERROR':
|
|
71
|
+
hr$.replaceAnimated(
|
|
72
|
+
votingWrapper,
|
|
73
|
+
hr$('.js-errorMessage', element)[0].innerHTML,
|
|
74
|
+
true,
|
|
75
|
+
scrollIntoVoting()
|
|
76
|
+
)
|
|
77
|
+
break
|
|
78
|
+
case 'OK':
|
|
79
|
+
hr$.replaceAnimated(
|
|
80
|
+
votingWrapper,
|
|
81
|
+
hr$('.js-successMessage', element)[0].innerHTML,
|
|
82
|
+
true,
|
|
83
|
+
scrollIntoVoting()
|
|
84
|
+
)
|
|
85
|
+
break
|
|
86
|
+
default:
|
|
87
|
+
hr$.replaceAnimated(
|
|
88
|
+
votingWrapper,
|
|
89
|
+
hr$('.js-errorMessage', element)[0].innerHTML,
|
|
90
|
+
true,
|
|
91
|
+
scrollIntoVoting()
|
|
92
|
+
)
|
|
93
|
+
break
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
hr$.replaceAnimated(formWrapper, data, true)
|
|
97
|
+
scrollIntoVoting()
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
//Add handlers to be called when the Deferred object is rejected.
|
|
102
|
+
.fail(function (xhr, errorType, error) {
|
|
103
|
+
//anzeige irgendetwas hat nicht geklappt
|
|
104
|
+
console.log('Fail ' + errorType)
|
|
105
|
+
hr$.replaceAnimated(
|
|
106
|
+
votingWrapper,
|
|
107
|
+
hr$('.js-errorMessage', element)[0].innerHTML,
|
|
108
|
+
true,
|
|
109
|
+
setTimeout(function () {
|
|
110
|
+
scrollIntoVoting()
|
|
111
|
+
}, 850)
|
|
112
|
+
)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
//Add handlers to be called when the Deferred object is either resolved or rejected.
|
|
116
|
+
.always(function () {
|
|
117
|
+
//aufräumen wenn bedarf besteht.
|
|
118
|
+
console.log('Always')
|
|
119
|
+
|
|
120
|
+
isPosting = false
|
|
121
|
+
})
|
|
122
|
+
},
|
|
123
|
+
scrollIntoVoting = function (vertical) {
|
|
124
|
+
setTimeout(function () {
|
|
125
|
+
element.scrollIntoView({
|
|
126
|
+
behavior: 'smooth',
|
|
127
|
+
block: 'center',
|
|
128
|
+
})
|
|
129
|
+
}, 850)
|
|
130
|
+
},
|
|
131
|
+
handleFormReload = function (event) {
|
|
132
|
+
event.preventDefault()
|
|
133
|
+
hr$.replaceAnimated(votingWrapper, votingTmpl, false, reinitiateVotingForm)
|
|
134
|
+
scrollIntoVoting()
|
|
135
|
+
//hr$.ux('forms', 'formReload');
|
|
136
|
+
},
|
|
137
|
+
setValidationErrors = function (errors) {
|
|
138
|
+
var wrapperElement, errorElement, prop, InvalidFields
|
|
139
|
+
|
|
140
|
+
for (prop in errors) {
|
|
141
|
+
wrapperElement = element.getElementsByClassName('js-wrapper-' + prop)[0]
|
|
142
|
+
errorElement = document.createElement('p')
|
|
143
|
+
|
|
144
|
+
InvalidFields = document.getElementsByName(prop)
|
|
145
|
+
for (var i = 0; i < InvalidFields.length; i++) {
|
|
146
|
+
if (wrapperElement.contains(InvalidFields[i])) {
|
|
147
|
+
InvalidFields[i].classList.add('is-invalid')
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
errorElement.innerHTML = settings.errorMessages[errors[prop]]
|
|
152
|
+
errorElement.classList.add('c-form__errorMessage')
|
|
153
|
+
|
|
154
|
+
wrapperElement.insertBefore(errorElement, wrapperElement.firstChild)
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
resetValidationErrors = function () {
|
|
158
|
+
var oldInvalidFields = hr$('.is-invalid', element),
|
|
159
|
+
oldErrorMessages = hr$('.c-form__errorMessage', element)
|
|
160
|
+
|
|
161
|
+
for (var i = 0; i < oldInvalidFields.length; i++) {
|
|
162
|
+
oldInvalidFields[i].classList.remove('is-invalid')
|
|
163
|
+
oldErrorMessages[i].parentNode.removeChild(oldErrorMessages[i])
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
handleValidationErrors = function (errors) {
|
|
167
|
+
resetValidationErrors()
|
|
168
|
+
setValidationErrors(errors)
|
|
169
|
+
},
|
|
170
|
+
isFormAvailable = function () {
|
|
171
|
+
return !!votingForm
|
|
172
|
+
},
|
|
173
|
+
reinitiateVotingForm = function () {
|
|
174
|
+
hrScriptLoad.rescanForModulesAndVariants(element.parentElement)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!isFormAvailable()) {
|
|
178
|
+
//skip code execution
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
//init
|
|
183
|
+
votingWrapper.style.WebkitTransition = 'opacity 0.8s ease-in-out'
|
|
184
|
+
votingWrapper.style.MozTransition = 'opacity 0.8s ease-in-out'
|
|
185
|
+
votingWrapper.style.transition = 'opacity 0.8s ease-in-out'
|
|
186
|
+
|
|
187
|
+
checkForJsonURL()
|
|
188
|
+
|
|
189
|
+
$(element).on('submit', '.js-votingForm', handleSubmit)
|
|
190
|
+
$(element).on('click', '.js-formReload', handleFormReload)
|
|
191
|
+
$(element).on('keydown', '.js-form-email', function (e) {
|
|
192
|
+
e.stopPropagation()
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
hrScriptLoad.load('voting', ['hrQueryOld', 'zepto'], function (options) {
|
|
197
|
+
new Voting(options)
|
|
198
|
+
})
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { hr$, listen } from 'hrQuery'
|
|
2
|
+
|
|
3
|
+
const VotingValidator = (context) => {
|
|
4
|
+
// Production steps of ECMA-262, Edition 6, 22.1.2.1
|
|
5
|
+
if (!Array.from) {
|
|
6
|
+
Array.from = (function () {
|
|
7
|
+
let toStr = Object.prototype.toString
|
|
8
|
+
let isCallable = function (fn) {
|
|
9
|
+
return typeof fn === 'function' || toStr.call(fn) === '[object Function]'
|
|
10
|
+
}
|
|
11
|
+
const toInteger = function (value) {
|
|
12
|
+
let number = Number(value)
|
|
13
|
+
if (isNaN(number)) {
|
|
14
|
+
return 0
|
|
15
|
+
}
|
|
16
|
+
if (number === 0 || !isFinite(number)) {
|
|
17
|
+
return number
|
|
18
|
+
}
|
|
19
|
+
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number))
|
|
20
|
+
}
|
|
21
|
+
const maxSafeInteger = Math.pow(2, 53) - 1
|
|
22
|
+
const toLength = function (value) {
|
|
23
|
+
let len = toInteger(value)
|
|
24
|
+
return Math.min(Math.max(len, 0), maxSafeInteger)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// The length property of the from method is 1.
|
|
28
|
+
return function from(arrayLike /*, mapFn, thisArg */) {
|
|
29
|
+
// 1. Let C be the this value.
|
|
30
|
+
let C = this
|
|
31
|
+
|
|
32
|
+
// 2. Let items be ToObject(arrayLike).
|
|
33
|
+
let items = Object(arrayLike)
|
|
34
|
+
|
|
35
|
+
// 3. ReturnIfAbrupt(items).
|
|
36
|
+
if (arrayLike == null) {
|
|
37
|
+
throw new TypeError(
|
|
38
|
+
'Array.from requires an array-like object - not null or undefined'
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 4. If mapfn is undefined, then let mapping be false.
|
|
43
|
+
const mapFn = arguments.length > 1 ? arguments[1] : void undefined
|
|
44
|
+
let T
|
|
45
|
+
if (typeof mapFn !== 'undefined') {
|
|
46
|
+
// 5. else
|
|
47
|
+
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
|
|
48
|
+
if (!isCallable(mapFn)) {
|
|
49
|
+
throw new TypeError(
|
|
50
|
+
'Array.from: when provided, the second argument must be a function'
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
55
|
+
if (arguments.length > 2) {
|
|
56
|
+
T = arguments[2]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 10. Let lenValue be Get(items, "length").
|
|
61
|
+
// 11. Let len be ToLength(lenValue).
|
|
62
|
+
const len = toLength(items.length)
|
|
63
|
+
|
|
64
|
+
// 13. If IsConstructor(C) is true, then
|
|
65
|
+
// 13. a. Let A be the result of calling the [[Construct]] internal method
|
|
66
|
+
// of C with an argument list containing the single item len.
|
|
67
|
+
// 14. a. Else, Let A be ArrayCreate(len).
|
|
68
|
+
const A = isCallable(C) ? Object(new C(len)) : new Array(len)
|
|
69
|
+
|
|
70
|
+
// 16. Let k be 0.
|
|
71
|
+
let k = 0
|
|
72
|
+
// 17. Repeat, while k < len… (also steps a - h)
|
|
73
|
+
let kValue
|
|
74
|
+
while (k < len) {
|
|
75
|
+
kValue = items[k]
|
|
76
|
+
if (mapFn) {
|
|
77
|
+
A[k] =
|
|
78
|
+
typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k)
|
|
79
|
+
} else {
|
|
80
|
+
A[k] = kValue
|
|
81
|
+
}
|
|
82
|
+
k += 1
|
|
83
|
+
}
|
|
84
|
+
// 18. Let putStatus be Put(A, "length", len, true).
|
|
85
|
+
A.length = len
|
|
86
|
+
// 20. Return A.
|
|
87
|
+
return A
|
|
88
|
+
}
|
|
89
|
+
})()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { options } = context
|
|
93
|
+
const { element: rootElement } = context
|
|
94
|
+
const maxAnswerCount = options.maxAnswerCount,
|
|
95
|
+
isMultipleChoice = options.isMultipleChoice || false,
|
|
96
|
+
votingOptions = Array.from(hr$('input[name=multivoting]', rootElement)),
|
|
97
|
+
submit = hr$('input[type=submit]', rootElement)[0],
|
|
98
|
+
submitLabel = hr$('.js-voting-submit-button', rootElement)[0]
|
|
99
|
+
let counter = hr$('.js-voting-counter', rootElement),
|
|
100
|
+
selectedCheckboxes = 0
|
|
101
|
+
|
|
102
|
+
const countSelectedCheckboxes = function (event) {
|
|
103
|
+
console.log(submitLabel)
|
|
104
|
+
if (countCheckedCheckboxes() != 0) {
|
|
105
|
+
submit.disabled = false
|
|
106
|
+
submitLabel.classList.remove('-inactive')
|
|
107
|
+
} else {
|
|
108
|
+
submit.disabled = true
|
|
109
|
+
submitLabel.classList.add('-inactive')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (selectedCheckboxes < maxAnswerCount) {
|
|
113
|
+
countSelectedCheckBoxesIfMaxHasNotReached(event)
|
|
114
|
+
|
|
115
|
+
if (selectedCheckboxes == maxAnswerCount) {
|
|
116
|
+
disableCheckboxesIfMaxHasReached()
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
enableCheckboxesIfMaxHasUndershot()
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const isUnchecked = function (checkbox) {
|
|
124
|
+
return checkbox.checked == false
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const isDisabled = function (checkbox) {
|
|
128
|
+
return checkbox.disabled == true
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const isChecked = function (checkbox) {
|
|
132
|
+
return checkbox.checked == true
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const countCheckedCheckboxes = function () {
|
|
136
|
+
let checkedOptions = votingOptions.filter(isChecked)
|
|
137
|
+
return checkedOptions.length
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const countSelectedCheckBoxesIfMaxHasNotReached = function (event) {
|
|
141
|
+
if (event.target.checked === false) {
|
|
142
|
+
if (isMultipleChoice) {selectedCheckboxes = selectedCheckboxes - 1}
|
|
143
|
+
counter.innerHTML = '(' + selectedCheckboxes + '/' + maxAnswerCount + ')'
|
|
144
|
+
} else {
|
|
145
|
+
selectedCheckboxes = selectedCheckboxes + 1
|
|
146
|
+
counter.innerHTML = '(' + selectedCheckboxes + '/' + maxAnswerCount + ')'
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const disableCheckboxesIfMaxHasReached = function () {
|
|
151
|
+
let uncheckedOptions = votingOptions.filter(isUnchecked)
|
|
152
|
+
uncheckedOptions.map(function (uncheckedOptions) {
|
|
153
|
+
if (isMultipleChoice) {
|
|
154
|
+
uncheckedOptions.disabled = true
|
|
155
|
+
let label = hr$('label[for=' + uncheckedOptions.id + ']')
|
|
156
|
+
label = label.item(0)
|
|
157
|
+
label.classList.add('-inactive')
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const enableCheckboxesIfMaxHasUndershot = function () {
|
|
163
|
+
if (isMultipleChoice) {selectedCheckboxes = selectedCheckboxes - 1}
|
|
164
|
+
counter.innerHTML = '(' + selectedCheckboxes + '/' + maxAnswerCount + ')'
|
|
165
|
+
let disabledCheckboxes = votingOptions.filter(isDisabled)
|
|
166
|
+
disabledCheckboxes.map(function (disabledCheckboxes) {
|
|
167
|
+
disabledCheckboxes.disabled = false
|
|
168
|
+
let label = hr$('label[for=' + disabledCheckboxes.id + ']')
|
|
169
|
+
label = label.item(0)
|
|
170
|
+
label.classList.remove('-inactive')
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const initVotingValidation = function () {
|
|
175
|
+
//if (isMultipleChoice) {
|
|
176
|
+
counter = counter.item(0)
|
|
177
|
+
submit.disabled = true
|
|
178
|
+
|
|
179
|
+
// Uncheck all checkboxes if User was faster than JS loading
|
|
180
|
+
for (let i = 0; i < votingOptions.length; i++) {
|
|
181
|
+
votingOptions[i].checked = false
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
for (let i = 0; i < votingOptions.length; i++) {
|
|
185
|
+
votingOptions[i].disabled = false
|
|
186
|
+
listen('click', countSelectedCheckboxes, votingOptions[i])
|
|
187
|
+
}
|
|
188
|
+
//}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
initVotingValidation()
|
|
192
|
+
}
|
|
193
|
+
export default VotingValidator
|
|
@@ -1,12 +1,53 @@
|
|
|
1
1
|
{{#with this.form}}
|
|
2
2
|
{{#unless this.isVotingOver}}
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
{{#unless ../this.hasRedirect}}
|
|
4
|
+
<div class="js-load {{../_addClass}}"
|
|
5
|
+
data-hr-voting-ds='{"jsonURL":"{{this.jsonUrl}}", "errorMessages": {{this.errorMessages}} }'
|
|
6
|
+
data-hr-voting-validator-ds='{"isMultipleChoice": {{../this.isMultipleChoice}}, "minAnswerCount": 1, "maxAnswerCount": {{../this.maxAnswerCount}} }'
|
|
7
|
+
{{#if this.isSimpleSecured}}
|
|
8
|
+
data-hr-voting-cookie-checker-ds='{ "alreadyVotedHintText": "{{loca "votingform_already_voted_cookie_hint"}}" , "hideVotingResult": {{this.hideVotingResult}} , "votingId": "{{this.sophoraId}}" }'
|
|
9
|
+
id="{{this.sophoraId}}"
|
|
10
|
+
{{/if}}
|
|
11
|
+
>
|
|
12
|
+
{{else}}
|
|
13
|
+
<div class="js-load {{../_addClass}}"
|
|
14
|
+
{{#if this.is2FSecured}}data-hr-voting-ds='{"jsonURL":"{{this.jsonUrl}}", "errorMessages": {{this.errorMessages}} }'{{/if}}
|
|
15
|
+
data-hr-voting-validator-ds='{"isMultipleChoice": {{../this.isMultipleChoice}}, "minAnswerCount": 1, "maxAnswerCount": {{../this.maxAnswerCount}} }'
|
|
16
|
+
{{#if this.isSimpleSecured}}
|
|
17
|
+
data-hr-voting-cookie-checker-ds='{ "alreadyVotedHintText": "{{loca "votingform_already_voted_cookie_hint"}}" , "hideVotingResult": {{this.hideVotingResult}} , "votingId": "{{this.sophoraId}}" }'
|
|
18
|
+
id="{{this.sophoraId}}"
|
|
19
|
+
{{/if}}
|
|
20
|
+
>
|
|
21
|
+
{{/unless}}
|
|
22
|
+
<div class="js-voting-wrapper">
|
|
23
|
+
<form class="js-votingForm"
|
|
24
|
+
action="{{this.url}}"
|
|
25
|
+
method="post"
|
|
26
|
+
enctype="application/x-www-form-urlencoded"
|
|
27
|
+
accept-charset="utf-8"
|
|
28
|
+
autocomplete="off"
|
|
29
|
+
>
|
|
30
|
+
{{> components/voting/components/voting_header _title=../this.title _topline=../this.topline}}
|
|
31
|
+
|
|
32
|
+
<div class="c-voting-form__bottomWrapper">
|
|
33
|
+
{{#if this.shorttext}}
|
|
34
|
+
<p class="mt-4 text-base font-copy sm:text-lg sm:mt-5 dark:text-text-dark">{{this.shorttext}}</p>
|
|
35
|
+
{{/if}}
|
|
36
|
+
|
|
37
|
+
<div class="w-full mt-6 text-xs text-right sm:mt-12 font-headingSerif sm:text-sm text-gray-scorpion dark:text-text-dark">
|
|
38
|
+
{{#if ../this.isMultipleChoice}}
|
|
39
|
+
{{loca "votingform_open_answers_text" ../this.maxAnswerCount}}
|
|
40
|
+
{{else}}
|
|
41
|
+
{{loca "votingform_single_answer_text"}}
|
|
42
|
+
{{/if}}
|
|
43
|
+
<span class="block float-right w-8 js-voting-counter">(0/{{../this.maxAnswerCount}})</span>
|
|
44
|
+
</div>
|
|
45
|
+
{{> components/forms/components/fields _multipleChoice=../this.isMultipleChoice _addClassGroup="!flex-col mt-5" _addClassChoice="has-[input:checked]:outline outline-2 outline-blue-science-hex bg-white p-4" _addClassLabel="!text-base sm:!text-lg md:!text-lg"}}
|
|
46
|
+
{{> components/voting/components/voting_submit _label="Abstimmen" _addClass="-inactive js-voting-submit-button"}}
|
|
47
|
+
</div>
|
|
48
|
+
</form>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
10
51
|
{{else}}
|
|
11
52
|
{{> components/voting/voting_result _isVotingOver=true _title=../this.title _topline=../this.topline}}
|
|
12
53
|
{{/unless}}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import votingJson from './fixtures/voting.json'
|
|
2
|
+
import votingOverJson from './fixtures/voting_over.json'
|
|
2
3
|
|
|
3
4
|
const handlebars = require('hrHandlebars')
|
|
4
5
|
|
|
@@ -28,3 +29,9 @@ export const Default = {
|
|
|
28
29
|
name: 'default',
|
|
29
30
|
args: votingJson,
|
|
30
31
|
}
|
|
32
|
+
|
|
33
|
+
export const Voting_Over = {
|
|
34
|
+
render: Template.bind({}),
|
|
35
|
+
name: 'Beeendet',
|
|
36
|
+
args: votingOverJson,
|
|
37
|
+
}
|