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.
Files changed (69) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/assets/brand/hessenschau/conf/locatags.merged.json +1 -0
  3. package/dist/assets/brand/hr/conf/locatags.merged.json +1 -0
  4. package/dist/assets/brand/hr-bigband/conf/locatags.merged.json +1 -0
  5. package/dist/assets/brand/hr-fernsehen/conf/locatags.merged.json +1 -0
  6. package/dist/assets/brand/hr-inforadio/conf/locatags.merged.json +1 -0
  7. package/dist/assets/brand/hr-rundfunkrat/conf/locatags.merged.json +1 -0
  8. package/dist/assets/brand/hr-sinfonieorchester/conf/locatags.merged.json +1 -0
  9. package/dist/assets/brand/hr-werbung/conf/locatags.merged.json +1 -0
  10. package/dist/assets/brand/hr1/conf/locatags.merged.json +1 -0
  11. package/dist/assets/brand/hr2/conf/locatags.merged.json +1 -0
  12. package/dist/assets/brand/hr3/conf/locatags.merged.json +1 -0
  13. package/dist/assets/brand/hr4/conf/locatags.merged.json +1 -0
  14. package/dist/assets/brand/you-fm/conf/locatags.merged.json +1 -0
  15. package/dist/assets/index.css +44 -3
  16. package/dist/assets/js/components/forms/js/contactForm.alpine.js +18 -17
  17. package/dist/assets/js/components/voting/js/votingCookieCheckerDs.feature.js +25 -0
  18. package/dist/assets/js/components/voting/js/votingDs.feature.js +214 -0
  19. package/dist/assets/js/components/voting/js/votingValidatorDs.feature.js +193 -0
  20. package/dist/views/components/forms/components/choice.hbs +2 -2
  21. package/dist/views/components/forms/components/choiceGroup.hbs +4 -2
  22. package/dist/views/components/forms/components/fields.hbs +3 -1
  23. package/dist/views/components/voting/components/voting_submit.hbs +4 -0
  24. package/dist/views/components/voting/voting.hbs +48 -7
  25. package/dist/views/components/voting/voting_result.hbs +3 -3
  26. package/dist/views_static/components/forms/components/choice.hbs +2 -2
  27. package/dist/views_static/components/forms/components/choiceGroup.hbs +4 -2
  28. package/dist/views_static/components/forms/components/fields.hbs +3 -1
  29. package/dist/views_static/components/voting/components/voting_submit.hbs +4 -0
  30. package/dist/views_static/components/voting/voting.hbs +48 -7
  31. package/dist/views_static/components/voting/voting_result.hbs +3 -3
  32. package/package.json +1 -1
  33. package/src/assets/brand/_default/conf/locatags.json +1 -0
  34. package/src/assets/brand/hessenschau/conf/locatags.merged.json +1 -0
  35. package/src/assets/brand/hr/conf/locatags.merged.json +1 -0
  36. package/src/assets/brand/hr-bigband/conf/locatags.merged.json +1 -0
  37. package/src/assets/brand/hr-fernsehen/conf/locatags.merged.json +1 -0
  38. package/src/assets/brand/hr-inforadio/conf/locatags.merged.json +1 -0
  39. package/src/assets/brand/hr-rundfunkrat/conf/locatags.merged.json +1 -0
  40. package/src/assets/brand/hr-sinfonieorchester/conf/locatags.merged.json +1 -0
  41. package/src/assets/brand/hr-werbung/conf/locatags.merged.json +1 -0
  42. package/src/assets/brand/hr1/conf/locatags.merged.json +1 -0
  43. package/src/assets/brand/hr2/conf/locatags.merged.json +1 -0
  44. package/src/assets/brand/hr3/conf/locatags.merged.json +1 -0
  45. package/src/assets/brand/hr4/conf/locatags.merged.json +1 -0
  46. package/src/assets/brand/you-fm/conf/locatags.merged.json +1 -0
  47. package/src/assets/fixtures/voting/voting.inc.json +21 -5
  48. package/src/stories/views/components/forms/components/choice.hbs +2 -2
  49. package/src/stories/views/components/forms/components/choiceGroup.hbs +4 -2
  50. package/src/stories/views/components/forms/components/fields.hbs +3 -1
  51. package/src/stories/views/components/forms/js/contactForm.alpine.js +18 -17
  52. package/src/stories/views/components/voting/components/voting_submit.hbs +4 -0
  53. package/src/stories/views/components/voting/fixtures/voting.json +1 -1
  54. package/src/stories/views/components/voting/fixtures/voting_error.json +1 -1
  55. package/src/stories/views/components/voting/fixtures/voting_over.json +1 -1
  56. package/src/stories/views/components/voting/fixtures/voting_result_absolute.json +1 -1
  57. package/src/stories/views/components/voting/js/voteValidatorDs.js +195 -0
  58. package/src/stories/views/components/voting/js/votingCookieCheckerDs.feature.js +25 -0
  59. package/src/stories/views/components/voting/js/votingCookieCheckerDs.js +31 -0
  60. package/src/stories/views/components/voting/js/votingDs.feature.js +214 -0
  61. package/src/stories/views/components/voting/js/votingDs.js +198 -0
  62. package/src/stories/views/components/voting/js/votingValidatorDs.feature.js +193 -0
  63. package/src/stories/views/components/voting/voting.hbs +48 -7
  64. package/src/stories/views/components/voting/voting.stories.js +7 -0
  65. package/src/stories/views/components/voting/voting_result.hbs +3 -3
  66. package/src/stories/views/components/voting/voting_result.stories.js +0 -30
  67. /package/dist/views/components/voting/{voting_header.hbs → components/voting_header.hbs} +0 -0
  68. /package/dist/views_static/components/voting/{voting_header.hbs → components/voting_header.hbs} +0 -0
  69. /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
- {{> components/voting/voting_header _title=../this.title _topline=../this.topline}}
5
-
6
- {{#if this.shorttext}}
7
- <p class="mt-4 text-base font-copy sm:text-lg sm:mt-5 dark:text-text-dark">{{this.shorttext}}</p>
8
- {{/if}}
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
+ }