$f['max'] = -INF;
$f['unit'] = $data->unit;
$f['type'] = 'range';
+ $f['scale'] = $data->logarithmic_scale ? 'log' : 'linear';
if ($data->type == 'numeric' || $data->type == 'numeric_list') {
$f['prefix'] = $data['prefix'];
continue;
}
+
+ $fvmax = $filter_value[1];
+ $fvmin = $filter_value[0];
+
+ if ($f['scale'] == 'log') {
+ $fvmax = safeExp($fvmax);
+ $fvmin = safeExp($fvmin);
+ }
+
if ($data->type == 'range') {
$f['min'] = min($f['min'], $v['first'] ?? INF, $v['second'] ?? INF);
$f['max'] = max($f['max'], $v['first'] ?? -INF, $v['second'] ?? -INF);
$min = min($v['first'], $v['second']);
$max = max($v['first'], $v['second']);
- if (null === $v || ($min <= $filter_value[1] && $max >= $filter_value[0])) {
+
+ if (null === $v || ($min <= $fvmax && $max >= $fvmin)) {
$matching[] = $product->id;
}
+
}
} else if ($data->type == 'numeric') {
$f['min'] = min($f['min'], $v);
$f['max'] = max($f['max'], $v);
if (null !== $filter_value) {
- if (null === $v || ($v >= $filter_value[0] && $v <= $filter_value[1])) {
+ if (null === $v || ($v >= $fvmin && $v <= $fvmax)) {
$matching[] = $product->id;
}
}
$f['max'] = max($f['max'], $vv);
if (null !== $filter_value) {
- if (null === $vv || ($vv >= $filter_value[0] && $vv <= $filter_value[1])) {
+ if (null === $vv || ($vv >= $fvmin && $vv <= $fvmax)) {
$matching[] = $product->id;
}
}
}
}
+
+ if ($f['scale'] === 'log') {
+ $f['minscale'] = safeLog($f['min']);
+ $f['maxscale'] = safeLog($f['max']);
+ } else {
+ $f['minscale'] = $f['min'];
+ $f['maxscale'] = $f['max'];
+ }
+
if (null === $filter_value && $v != '') {
$matching[] = $product->id;
}
}
}
+
+function safeLog($v)
+{
+ if ($v == 0) {
+ $res = 0;
+ } elseif ($v < 0) {
+ $res = -log10(abs($v));
+ } else {
+ $res = log10($v);
+ }
+
+ return round($res,8);
+}
+
+function safeExp($log)
+{
+ if ($log === 0) {
+ $res = 0;
+ } else {
+ $m = $log > 0 ? 1 : -1;
+ $res = $m * (10 ** ($log * $m));
+ }
+ return $res;
+}
<div class="relative" :class="{ 'overflow-hidden': noResults }">
<!-- Filters column -->
- <div class="products-filters-wrapper sticky sm:static top-60 mr-1v sm:mr-0 pt-4 whitespace-no-wrap float-left sm:float-none">
+ <div
+ class="products-filters-wrapper sticky sm:static top-60 mr-1v sm:mr-0 pt-4 whitespace-no-wrap float-left sm:float-none">
<!-- Filters panel -->
<div class="bg-white p-4">
<div class="products-filters" v-for="(filter, index) in filterData" :key="index">
- <hr class="h-px bg-grey-250 my-4" v-if="index !== 0" />
+ <hr class="h-px bg-grey-250 my-4" v-if="index !== 0"/>
<h3 class="text-base mb-2 whitespace-normal">{{ filter.label }}</h3>
<ul v-if="filter.type === 'list'">
- <li v-for="(option, option_index) in filter.options" :key="option_index" class="flex justify-between py-1 text-sm">
+ <li v-for="(option, option_index) in filter.options" :key="option_index"
+ class="flex justify-between py-1 text-sm">
<label>
- <input type="checkbox" v-model="filters[filter.id]" :value="option.value" @change="updateFilters">
+ <input type="checkbox" v-model="filters[filter.id]" :value="option.value"
+ @change="updateFilters">
{{ option.label }}
</label>
<div v-if="filter.type === 'range'">
<vue-slider class="mt-3"
v-model="filters[filter.id]"
- :min="parseFloat(filter.min)"
- :max="parseFloat(filter.max)"
+ :min="parseFloat(filter.minscale)"
+ :max="parseFloat(filter.maxscale)"
:enable-cross="false"
:contained="true"
:lazy="true"
- :interval="(filter.max - filter.min) / 100"
+ :interval="(filter.maxscale - filter.minscale) / 100"
+ :tooltip-formatter="filter.scale === 'log' ? log : linear"
@change="updateFilters">
</vue-slider>
<div class="products-grid flex-grow">
<!-- Grid summary header -->
- <div :class="{ 'top-60': !noResults }" class="products-grid-summary sticky sm:static z-10 bg-grey-100 pt-4 pb-4 flex justify-between sm:block">
+ <div :class="{ 'top-60': !noResults }"
+ class="products-grid-summary sticky sm:static z-10 bg-grey-100 pt-4 pb-4 flex justify-between sm:block">
<!-- Active filters -->
<div class="products-grid-active-filters flex-grow text-sm">
{{ getFilter(filterID).options[filter_option].label }}
- <svg class="svg inline-block ml-3 cursor-pointer" @click="removeFilter(filterID, filter_option)"
+ <svg class="svg inline-block ml-3 cursor-pointer"
+ @click="removeFilter(filterID, filter_option)"
xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 11 11">
- <path fill="#6B7287" d="M11 1.4L9.6 0 5.5 4.1 1.4 0 0 1.4l4.1 4.1L0 9.6 1.4 11l4.1-4.1L9.6 11 11 9.6 6.9 5.5z"/>
+ <path fill="#6B7287"
+ d="M11 1.4L9.6 0 5.5 4.1 1.4 0 0 1.4l4.1 4.1L0 9.6 1.4 11l4.1-4.1L9.6 11 11 9.6 6.9 5.5z"/>
</svg>
</li>
filters: {},
matches: {},
products: [],
+ log: function (v) {
+ var res = Math.pow(10, v);
+ var nbZeros = Math.max(-1, Math.round(v - 2));
+ var roundFactor = Math.pow(10, nbZeros);
+ var introunded = Math.round(res / roundFactor);
+ var rounded = introunded * roundFactor;
+ rounded = rounded.toFixed(Math.max(0, -nbZeros));
+
+ return rounded;
+ },
+ linear: function (v) {
+ return v;
+ }
}),
computed: {
// Don't include range values if they're unchanged (at min / max values)
if (filter.type === 'range'
- && filter.min === this.filters[filterID][0]
- && filter.max === this.filters[filterID][1]) {
+ && filter.minscale === this.filters[filterID][0]
+ && filter.maxscale === this.filters[filterID][1]) {
return;
}
let filters = {};
Object.values(this.filterData).forEach(filter => {
if (filter.type === 'range') {
- filters[filter.id] = [filter.min, filter.max];
+ filters[filter.id] = [filter.minscale, filter.maxscale];
} else {
filters[filter.id] = [];
}