Skip to content

Commit

Permalink
Make sure that custom error messages are shown on input elements
Browse files Browse the repository at this point in the history
Attach MOS size error to commas and vals inputs in Rank-2 modal.

ref #540
  • Loading branch information
frostburn committed Feb 13, 2024
1 parent 12a00e1 commit 551aa18
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 33 deletions.
22 changes: 3 additions & 19 deletions src/components/ScaleLineInput.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { DEFAULT_NUMBER_OF_COMPONENTS } from '@/constants'
import { computedAndError } from '@/utils'
import { computedAndError, setAndReportValidity } from '@/utils'
import { parseLine, type Interval } from 'scale-workshop-core'
import { ref, watch } from 'vue'
Expand All @@ -18,24 +18,8 @@ const [value, error] = computedAndError(
props.defaultValue
)
watch(value, (newValue) => emit('update:value', newValue), { immediate: true })
watch(
element,
(newElement) => {
if (newElement) {
newElement.setCustomValidity(error.value)
}
},
{ immediate: true }
)
watch(
error,
(newError) => {
if (element.value) {
element.value.setCustomValidity(newError)
}
},
{ immediate: true }
)
watch(element, (newElement) => setAndReportValidity(newElement, error.value), { immediate: true })
watch(error, (newError) => setAndReportValidity(element.value, newError), { immediate: true })
</script>

<template>
Expand Down
3 changes: 2 additions & 1 deletion src/components/modals/generation/CombinationProductSet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ScaleLineInput from '@/components/ScaleLineInput.vue'
import { OCTAVE } from '@/constants'
import { Scale } from 'scale-workshop-core'
import { useModalStore } from '@/stores/modal'
import { setAndReportValidity } from '@/utils'
const emit = defineEmits(['update:scale', 'update:scaleName', 'cancel'])
Expand All @@ -13,7 +14,7 @@ const modal = useModalStore()
const factorsElement = ref<HTMLInputElement | null>(null)
watch(
() => modal.factorsError,
(newError) => factorsElement.value!.setCustomValidity(newError)
(newError) => setAndReportValidity(factorsElement.value, newError)
)
// It's not obvious that combination count depends on a parsed text element.
Expand Down
5 changes: 3 additions & 2 deletions src/components/modals/generation/EqualTemperament.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Modal from '@/components/ModalDialog.vue'
import ScaleLineInput from '@/components/ScaleLineInput.vue'
import { ExtendedMonzo, Interval, Scale } from 'scale-workshop-core'
import { useModalStore } from '@/stores/modal'
import { setAndReportValidity } from '@/utils'
const props = defineProps<{
centsFractionDigits: number
Expand All @@ -21,9 +22,9 @@ watch(
() => modal.divisions,
(newValue) => {
if (isNaN(newValue) || newValue === 0) {
divisionsElement.value!.setCustomValidity('Step size is zero')
setAndReportValidity(divisionsElement.value, 'Step size is zero')
} else {
divisionsElement.value!.setCustomValidity('')
setAndReportValidity(divisionsElement.value, '')
}
}
)
Expand Down
28 changes: 25 additions & 3 deletions src/components/modals/generation/RankTwo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { makeRank2FromVals, makeRank2FromCommas, type Rank2Params } from '@/temp
import { ref, watch } from 'vue'
import Modal from '@/components/ModalDialog.vue'
import PeriodCircle from '@/components/PeriodCircle.vue'
import { gapKeyColors } from '@/utils'
import { gapKeyColors, setAndReportValidity } from '@/utils'
import ScaleLineInput from '@/components/ScaleLineInput.vue'
import { ExtendedMonzo, Interval, Scale } from 'scale-workshop-core'
import { useRank2Store } from '@/stores/tempering'
Expand All @@ -18,6 +18,8 @@ const rank2 = useRank2Store()
const emit = defineEmits(['update:scaleName', 'update:scale', 'update:keyColors', 'cancel'])
const commasInput = ref<HTMLInputElement | null>(null)
const valsInput = ref<HTMLInputElement | null>(null)
const subgroupInput = ref<HTMLInputElement | null>(null)
// === Watchers ===
Expand Down Expand Up @@ -50,7 +52,20 @@ watch(
watch(
() => rank2.subgroupError,
(newValue) => subgroupInput.value!.setCustomValidity(newValue)
(newValue) => setAndReportValidity(subgroupInput.value, newValue)
)
watch(
() => rank2.mosPatternsError,
(newValue) => {
if (rank2.method === 'commas') {
setAndReportValidity(commasInput.value, newValue)
setAndReportValidity(valsInput.value, '')
} else if (rank2.method === 'vals') {
setAndReportValidity(commasInput.value, '')
setAndReportValidity(valsInput.value, newValue)
}
}
)
// === Methods ===
Expand Down Expand Up @@ -253,14 +268,21 @@ function generate() {
<div class="control-group" v-show="rank2.method === 'vals'">
<div class="control">
<label for="vals">Vals</label>
<input type="text" id="vals" placeholder="12 & 17c" v-model="rank2.valsString" />
<input
ref="valsInput"
type="text"
id="vals"
placeholder="12 & 17c"
v-model="rank2.valsString"
/>
</div>
</div>

<div class="control-group" v-show="rank2.method === 'commas'">
<div class="control">
<label for="commas">Comma list</label>
<input
ref="commasInput"
type="text"
id="commas"
placeholder="225/224, 1029/1024"
Expand Down
4 changes: 2 additions & 2 deletions src/components/modals/generation/SummonOctaplex.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ref, watch } from 'vue'
import Modal from '@/components/ModalDialog.vue'
import ScaleLineInput from '@/components/ScaleLineInput.vue'
import { OCTAVE } from '@/constants'
import { computedAndError, parseChordInput } from '@/utils'
import { computedAndError, parseChordInput, setAndReportValidity } from '@/utils'
import { Scale } from 'scale-workshop-core'
const props = defineProps<{
Expand All @@ -27,7 +27,7 @@ const [basis, basisError] = computedAndError(() => {
}
return chord
}, [])
watch(basisError, (newError) => basisElement.value!.setCustomValidity(newError))
watch(basisError, (newError) => setAndReportValidity(basisElement.value, newError))
function generate() {
try {
Expand Down
5 changes: 3 additions & 2 deletions src/components/modals/modification/ApproximateByRatios.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { DEFAULT_NUMBER_OF_COMPONENTS } from '@/constants'
import { fractionToString, ExtendedMonzo, Interval, type Scale } from 'scale-workshop-core'
import { useApproximateByRatiosStore } from '@/stores/approximate-by-ratios'
import { setAndReportValidity } from '@/utils'
const MAX_LENGTH = 128
Expand Down Expand Up @@ -96,9 +97,9 @@ const approximationsWithErrorsAndLimits = computed<Approximation[]>(() => {
watch(approximationsWithErrorsAndLimits, (newValue) => {
if (approximationSelect.value !== null) {
if (!newValue.length || newValue[0].error > approx.maxError) {
approximationSelect.value.setCustomValidity('Error exceeds the maximum value.')
setAndReportValidity(approximationSelect.value, 'Error exceeds the maximum value.')
} else {
approximationSelect.value.setCustomValidity('')
setAndReportValidity(approximationSelect.value, '')
}
}
approx.approximationIndex = Math.min(approx.approximationIndex, newValue.length - 1)
Expand Down
4 changes: 2 additions & 2 deletions src/components/modals/modification/TemperScale.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Modal from '@/components/ModalDialog.vue'
import { Fraction, PRIME_CENTS } from 'xen-dev-utils'
import { mapByVal, resolveMonzo, tenneyVals, vanishCommas } from 'temperaments'
import { ExtendedMonzo, Interval, Scale, type IntervalOptions } from 'scale-workshop-core'
import { splitText } from '@/utils'
import { setAndReportValidity, splitText } from '@/utils'
import { useTemperStore } from '@/stores/tempering'
const props = defineProps<{
Expand All @@ -22,7 +22,7 @@ const subgroupInput = ref<HTMLInputElement | null>(null)
watch(
() => temper.subgroupError,
(newValue) => subgroupInput.value!.setCustomValidity(newValue)
(newValue) => setAndReportValidity(subgroupInput.value, newValue)
)
function modify() {
Expand Down
16 changes: 14 additions & 2 deletions src/tempering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,13 @@ export function mosPatternsRank2FromCommas(
const temperament = Temperament.fromCommas(commas, subgroup, true)
const rank = temperament.getRank()
if (rank !== 2) {
throw new Error(`Given commas define a rank ${rank} temperament. Need rank 2.`)
if (subgroup) {
throw new Error(`Given commas and subgroup define a rank ${rank} temperament. Need rank 2.`)
} else {
throw new Error(
`Given commas and inferred subgroup define a rank ${rank} temperament. Need rank 2.`
)
}
}
return mosPatternsRank2(temperament, maxSize, maxLength, options)
}
Expand Down Expand Up @@ -231,7 +237,13 @@ export function makeRank2FromCommas(
const temperament = Temperament.fromCommas(commas, subgroup, true)
const rank = temperament.getRank()
if (rank !== 2) {
throw new Error(`Given commas define a rank ${rank} temperament. Need rank 2.`)
if (subgroup) {
throw new Error(`Given commas and subgroup define a rank ${rank} temperament. Need rank 2.`)
} else {
throw new Error(
`Given commas and inferred subgroup define a rank ${rank} temperament. Need rank 2.`
)
}
}
return makeRank2(temperament, size, options)
}
Expand Down
11 changes: 11 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,17 @@ export function computedAndError<T>(
return [value, error]
}

export function setAndReportValidity(
element: HTMLInputElement | HTMLSelectElement | HTMLObjectElement | null,
message: string
) {
if (!element) {
return
}
element.setCustomValidity(message)
element.reportValidity()
}

// Calculates euclidean distance for monzos, as it assumes that if points are not of the same dimension, then the missing dimensions have a value of zero.
export function monzoEuclideanDistance(
equavePrimeIndex: number,
Expand Down

0 comments on commit 551aa18

Please sign in to comment.