fix poll checkboxes
This commit is contained in:
parent
1adb8236d9
commit
9f1f37ec7e
4 changed files with 101 additions and 112 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<label
|
<label
|
||||||
class="checkbox"
|
class="checkbox"
|
||||||
:class="{ disabled, indeterminate, 'indeterminate-fix': indeterminateTransitionFix }"
|
:class="[{ disabled, indeterminate, 'indeterminate-fix': indeterminateTransitionFix }, radio ? '-radio' : '-checkbox']"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
v-if="!!$slots.before"
|
v-if="!!$slots.before"
|
||||||
|
|
@ -19,9 +19,9 @@
|
||||||
@change="$emit('update:modelValue', $event.target.checked)"
|
@change="$emit('update:modelValue', $event.target.checked)"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="input -checkbox checkbox-indicator"
|
class="input checkbox-indicator"
|
||||||
:aria-hidden="true"
|
:aria-hidden="true"
|
||||||
:class="{ disabled }"
|
:class="[{ disabled }, radio ? '-radio' : '-checkbox']"
|
||||||
@transitionend.capture="onTransitionEnd"
|
@transitionend.capture="onTransitionEnd"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: [
|
props: [
|
||||||
|
'radio',
|
||||||
'modelValue',
|
'modelValue',
|
||||||
'indeterminate',
|
'indeterminate',
|
||||||
'disabled'
|
'disabled'
|
||||||
|
|
@ -68,6 +69,15 @@ export default {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
min-height: 1.2em;
|
min-height: 1.2em;
|
||||||
|
|
||||||
|
&.-radio {
|
||||||
|
.checkbox-indicator {
|
||||||
|
&,
|
||||||
|
&::before {
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-indicator,
|
&-indicator,
|
||||||
& .label {
|
& .label {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import Timeago from 'components/timeago/timeago.vue'
|
import Timeago from 'components/timeago/timeago.vue'
|
||||||
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
|
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
|
||||||
import RichContent from 'components/rich_content/rich_content.jsx'
|
import RichContent from 'components/rich_content/rich_content.jsx'
|
||||||
|
import Checkbox from 'components/checkbox/checkbox.vue'
|
||||||
import { forEach, map } from 'lodash'
|
import { forEach, map } from 'lodash'
|
||||||
import { usePollsStore } from 'src/stores/polls'
|
import { usePollsStore } from 'src/stores/polls'
|
||||||
|
|
||||||
|
|
@ -9,7 +10,8 @@ export default {
|
||||||
props: ['basePoll', 'emoji'],
|
props: ['basePoll', 'emoji'],
|
||||||
components: {
|
components: {
|
||||||
Timeago,
|
Timeago,
|
||||||
RichContent
|
RichContent,
|
||||||
|
Checkbox
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
@ -78,26 +80,15 @@ export default {
|
||||||
resultTitle (option) {
|
resultTitle (option) {
|
||||||
return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
|
return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
|
||||||
},
|
},
|
||||||
activateOption (index) {
|
activateOption (index, value) {
|
||||||
// forgive me father: doing checking the radio/checkboxes
|
let result
|
||||||
// in code because of customized input elements need either
|
|
||||||
// a) an extra element for the actual graphic, or b) use a
|
|
||||||
// pseudo element for the label. We use b) which mandates
|
|
||||||
// using "for" and "id" matching which isn't nice when the
|
|
||||||
// same poll appears multiple times on the site (notifs and
|
|
||||||
// timeline for example). With code we can make sure it just
|
|
||||||
// works without altering the pseudo element implementation.
|
|
||||||
const allElements = this.$el.querySelectorAll('input')
|
|
||||||
const clickedElement = this.$el.querySelector(`input[value="${index}"]`)
|
|
||||||
if (this.poll.multiple) {
|
if (this.poll.multiple) {
|
||||||
// Checkboxes, toggle only the clicked one
|
result = this.choices || this.options.map(() => false)
|
||||||
clickedElement.checked = !clickedElement.checked
|
|
||||||
} else {
|
} else {
|
||||||
// Radio button, uncheck everything and check the clicked one
|
result = this.options.map(() => false)
|
||||||
forEach(allElements, element => { element.checked = false })
|
|
||||||
clickedElement.checked = true
|
|
||||||
}
|
}
|
||||||
this.choices = map(allElements, e => e.checked)
|
result[index] = value
|
||||||
|
this.choices = result
|
||||||
},
|
},
|
||||||
optionId (index) {
|
optionId (index) {
|
||||||
return `poll${this.poll.id}-${index}`
|
return `poll${this.poll.id}-${index}`
|
||||||
|
|
|
||||||
72
src/components/poll/poll.scss
Normal file
72
src/components/poll/poll.scss
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
.poll {
|
||||||
|
.votes {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 0 0 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll-option {
|
||||||
|
margin: 0.75em 0.5em;
|
||||||
|
|
||||||
|
.input {
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-result {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
color: var(--textLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-result-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.1em 0.25em;
|
||||||
|
z-index: 1;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-percentage {
|
||||||
|
width: 3.5em;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-fill {
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: var(--roundness);
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
transition: width 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-vote {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 3.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.loading * {
|
||||||
|
cursor: progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll-vote-button {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll-checkbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,32 +37,21 @@
|
||||||
:role="poll.multiple ? 'checkbox' : 'radio'"
|
:role="poll.multiple ? 'checkbox' : 'radio'"
|
||||||
:aria-labelledby="`option-vote-${randomSeed}-${index}`"
|
:aria-labelledby="`option-vote-${randomSeed}-${index}`"
|
||||||
:aria-checked="choices[index]"
|
:aria-checked="choices[index]"
|
||||||
class="input unstyled"
|
|
||||||
@click="activateOption(index)"
|
|
||||||
>
|
>
|
||||||
<!-- TODO: USE CHECKBOX -->
|
<Checkbox
|
||||||
<input
|
:radio="!poll.multiple"
|
||||||
v-if="poll.multiple"
|
|
||||||
type="checkbox"
|
|
||||||
class="input -checkbox poll-checkbox"
|
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
:value="index"
|
:model-value="choices[index]"
|
||||||
|
@update:model-value="value => activateOption(index, value)"
|
||||||
>
|
>
|
||||||
<input
|
{{ choices[index] }}
|
||||||
v-else
|
|
||||||
type="radio"
|
|
||||||
:disabled="loading"
|
|
||||||
:value="index"
|
|
||||||
class="input -radio"
|
|
||||||
>
|
|
||||||
<label class="option-vote">
|
|
||||||
<RichContent
|
<RichContent
|
||||||
:id="`option-vote-${randomSeed}-${index}`"
|
:id="`option-vote-${randomSeed}-${index}`"
|
||||||
:html="option.title_html"
|
:html="option.title_html"
|
||||||
:handle-links="false"
|
:handle-links="false"
|
||||||
:emoji="emoji"
|
:emoji="emoji"
|
||||||
/>
|
/>
|
||||||
</label>
|
</Checkbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -112,77 +101,4 @@
|
||||||
|
|
||||||
<script src="./poll.js"></script>
|
<script src="./poll.js"></script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style src="./poll.scss" lang="scss"/>
|
||||||
.poll {
|
|
||||||
.votes {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin: 0 0 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.poll-option {
|
|
||||||
margin: 0.75em 0.5em;
|
|
||||||
|
|
||||||
.input {
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.option-result {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
position: relative;
|
|
||||||
color: var(--textLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.option-result-label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.1em 0.25em;
|
|
||||||
z-index: 1;
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-percentage {
|
|
||||||
width: 3.5em;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-fill {
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: var(--roundness);
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
transition: width 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.option-vote {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 3.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.loading * {
|
|
||||||
cursor: progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
.poll-vote-button {
|
|
||||||
padding: 0 0.5em;
|
|
||||||
margin-right: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.poll-checkbox {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue