Skip to content

Commit

Permalink
fix: Floating point error for q-range control #473
Browse files Browse the repository at this point in the history
  • Loading branch information
rstoenescu committed Mar 31, 2017
1 parent badf4f9 commit fb080bf
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 24 deletions.
13 changes: 13 additions & 0 deletions dev/components/form/double-range.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
</p>
<q-double-range v-model="standalone" :min="0" :max="50"></q-double-range>

<p class="caption">
With Floating Point Precision
<span class="label inline bg-secondary text-white">
Model <span class="right-detail"><em>{{precision}}</em> &nbsp;&nbsp;(0.1 to 1.0)</span>
</span>
</p>
<q-double-range v-model="precision" :min="0.1" :max="1.0" :step="0.1" :decimals="1"></q-double-range>

<p class="caption">
With Label
<span class="label inline bg-secondary text-white">
Expand Down Expand Up @@ -117,6 +125,11 @@ export default {
max: 35
},
precision: {
min: 0.2,
max: 0.7
},
step: {
min: 10,
max: 20
Expand Down
4 changes: 2 additions & 2 deletions dev/components/form/range.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
Model <span class="right-detail"><em>{{precision}}</em> &nbsp;&nbsp;(0.1 to 1.0)</span>
</span>
</p>
<q-range v-model="precision" :min="0.1" :max="1.0" :step="0.1" :decimals="1"></q-range>
<q-range v-model="precision" :min="0.1" :max="1" :step="0.1" :decimals="1"></q-range>

<p class="caption">
With Step
Expand Down Expand Up @@ -111,7 +111,7 @@ export default {
data () {
return {
standalone: 20,
precision: 0.1,
precision: 0.4,
step: 30,
label: 5,
snap: 2,
Expand Down
17 changes: 9 additions & 8 deletions src/vue-components/range/DoubleRange.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import extend from '../../utils/extend'
import {
getModel,
getPercentage,
notDivides,
mixin
} from './range-utils'
Expand Down Expand Up @@ -161,7 +162,7 @@ export default {
type = dragType.RANGE
extend(this.dragging, {
offsetPercentage: percentage,
offsetModel: getModel(percentage, this.min, this.max, this.step),
offsetModel: getModel(percentage, this.min, this.max, this.step, this.decimals),
rangeValue: this.dragging.valueMax - this.dragging.valueMin,
rangePercentage: this.currentMaxPercentage - this.currentMinPercentage
})
Expand All @@ -187,7 +188,7 @@ export default {
__update (event) {
let
percentage = getPercentage(event, this.dragging),
model = getModel(percentage, this.min, this.max, this.step),
model = getModel(percentage, this.min, this.max, this.step, this.decimals),
pos
switch (this.dragging.type) {
Expand Down Expand Up @@ -261,14 +262,14 @@ export default {
if (this.min >= this.max) {
console.error('Range error: min >= max', this.$el, this.min, this.max)
}
else if ((this.max - this.min) % this.step !== 0) {
console.error('Range error: step must be a divisor of max - min', this.$el, this.min, this.max, this.step)
else if (notDivides((this.max - this.min) / this.step, this.decimals)) {
console.error('Range error: step must be a divisor of max - min', this.min, this.max, this.step)
}
else if ((this.value.min - this.min) % this.step !== 0) {
console.error('Range error: step must be a divisor of initial value.min - min', this.$el, this.value.min, this.min, this.step)
else if (notDivides((this.value.min - this.min) / this.step, this.decimals)) {
console.error('Range error: step must be a divisor of initial value.min - min', this.value.min, this.min, this.step)
}
else if ((this.value.max - this.min) % this.step !== 0) {
console.error('Range error: step must be a divisor of initial value.max - min', this.$el, this.value.max, this.max, this.step)
else if (notDivides((this.value.max - this.min) / this.step, this.decimals)) {
console.error('Range error: step must be a divisor of initial value.max - min', this.value.max, this.max, this.step)
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/vue-components/range/Range.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import {
getModel,
getPercentage,
precision,
notDivides,
mixin
} from './range-utils'
Expand Down Expand Up @@ -111,11 +111,10 @@ export default {
this.currentPercentage = (this.value - this.min) / (this.max - this.min)
},
__validateProps () {
console.log(this.decimals, precision((this.max - this.min) % this.step, this.decimals))
if (this.min >= this.max) {
console.error('Range error: min >= max', this.$el, this.min, this.max)
}
else if (precision((this.max - this.min) % this.step, this.decimals) !== 0) {
else if (notDivides((this.max - this.min) / this.step, this.decimals)) {
console.error('Range error: step must be a divisor of max - min', this.min, this.max, this.step, this.decimals)
}
}
Expand Down
26 changes: 15 additions & 11 deletions src/vue-components/range/range-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@ export function getPercentage (event, dragging) {
return between((position(event).left - dragging.left) / dragging.width, 0, 1)
}

export function precision (number, decimals) {
return decimals > 0
? parseFloat(number.toFixed(decimals))
: number
export function notDivides (res, decimals) {
let number = decimals
? parseFloat(res.toFixed(decimals), 10)
: res

return number !== parseInt(number, 10)
}

export function getModel (percentage, min, max, step, decimals) {
let
model = precision(min + percentage * (max - min), decimals),
modulo = precision((model - min) % step, decimals)
model = min + percentage * (max - min),
modulo = (model - min) % step

model += (Math.abs(modulo) >= step / 2 ? (modulo < 0 ? -1 : 1) * step : 0) - modulo

if (decimals) {
model = parseFloat(model.toFixed(decimals))
}

return between(
model - modulo + (Math.abs(modulo) >= step / 2 ? (modulo < 0 ? -1 : 1) * step : 0),
min,
max
)
return between(model, min, max)
}

export let mixin = {
Expand Down

0 comments on commit fb080bf

Please sign in to comment.