You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
12 KiB
Vue

1 year ago
<template>
<form ref="filter">
<div :class="cls">
<!--Only code you need is this label-->
<label class="switch">
<input name="ext" @change="apply" v-model="ext" type="checkbox">
<div class="slider round"></div>
</label>
فقط کالاهای موجود
</div>
<div :class="cls">
<h2 id="fon">
مرتب سازی بر اساس:
</h2>
<input type="hidden" name="sort" value="sale" id="sort">
<span class="badge p-2 mb-1 bg-secondary" id="sale" @click="changeSort('sale',$event)">
پرفروشترین
</span>
<span class="badge p-2 mb-1 bg-secondary" id="new" @click="changeSort('new',$event)">
جدیدترین
</span>
<span class="badge p-2 mb-1 bg-secondary" id="fav" @click="changeSort('fav',$event)">
محبوبترین
</span>
<span class="badge p-2 mb-1 bg-secondary" id="cheap" @click="changeSort('cheap',$event)">
ارزانترین
</span>
<span class="badge p-2 mb-1 bg-secondary" id="expensive" @click="changeSort('expensive',$event)">
گرانترین
</span>
</div>
<div :class="cls" v-if="minm < maxm">
<label>
{{ t.priceRange }}
</label>
<VueSimpleRangeSlider
style="width: 95%;margin: auto"
:min="minm"
dir="rtl"
@input="price()"
:max="maxm"
active-bar-color="#1d68a7"
v-model="state.range"
>
<template #prefix="{ value }">ت</template>
</VueSimpleRangeSlider>
<input type="hidden" name="from" v-model="state.range[0]">
<input type="hidden" name="to" v-model="state.range[1]">
</div>
<div v-for="d in elms" :class="cls" v-if="d.searchable">
<template v-if="d.type !== 'checkbox'">
<label :for="d.name" >
{{ makeLabel(d.label) }}
1 year ago
</label>
</template>
<div v-if="d.type === 'text'">
1 year ago
<input v-model="defaults[d.name]" type="text" :id="d.name" :name="'meta['+d.name+']'"
class="form-control">
</div>
<div v-else-if="d.type === 'number'">
<input type="number" v-model="defaults[d.name]" :placeholder="makeLabel(d.label)" :id="d.name"
1 year ago
:name="'meta['+d.name+']'" class="form-control">
</div>
<div v-else-if="d.type === 'color'" :id="d.name" :name="'meta['+d.name+']'">
<select v-model="defaults[d.name]" :name="'meta['+d.name+']'" :id="d.name" class="form-control">
<option value=""> {{ makeLabel(d.label) }}</option>
1 year ago
<option :style="'background-color:' + o.value " :value="o.value" v-for="o in d.options">
{{ o.title }}
</option>
</select>
</div>
<div v-else-if="d.type === 'checkbox'">
<!--Only code you need is this label-->
<label class="switch">
<input :name="'meta['+d.name+']'" v-model="defaults[d.name]" type="checkbox">
<div class="slider round"></div>
</label>
<span >
</span>
{{ makeLabel(d.label) }}
1 year ago
</div>
<div v-else-if="d.type === 'select'">
<select v-model="defaults[d.name]" :name="'meta['+d.name+']'" :id="d.name" class="form-control">
<option value=""> {{ t.all }}</option>
<option :value="o.value" v-for="o in d.options"> {{ o.title }}</option>
</select>
</div>
<div v-else-if="d.type === 'multi'">
<multiselect :multiple="true" :taggable="true" label="title" v-model="defaults[d.name]"
:placeholder="makeLabel(d.label)" :options="d.options"></multiselect>
1 year ago
<input :id="d.label" type="hidden" :name="'meta['+d.name+']'" :value="makeVal(defaults[d.name])">
</div>
<div v-else-if="d.type === 'singlemulti'">
<multiselect @remove="rem(d.name,$event)" @select="upd(d.name,defaults[d.name])"
v-model="defaults[d.name]" :multiple="true" :taggable="true" label="title"
:placeholder="makeLabel(d.label)" :options="d.options"></multiselect>
1 year ago
<input type="hidden" :name="'meta['+d.name+']'" :value="makeVal(defaults[d.name])">
</div>
</div>
<button class="btn btn-primary w-100">
<i class="fa fa-check float-start mt-1"></i>
اعمال
</button>
</form>
</template>
<script>
import multiselect from 'vue-multiselect';
import VueSimpleRangeSlider from "vue-simple-range-slider/vue2";
import "vue-simple-range-slider/vue2/css";
function getParameterByName(name, url = window.location.href) {
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
function getURLParam(key, target = window.location.href) {
var values = [];
if (!target) target = location.href;
key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var pattern = key + '=([^&#]+)';
var o_reg = new RegExp(pattern, 'ig');
while (true) {
console.log('x1');
var matches = o_reg.exec(target);
if (matches && matches[1]) {
values.push(matches[1]);
} else {
break;
}
}
if (!values.length) {
return null;
} else {
return values.length == 1 ? values[0] : values;
}
}
export default {
name: "MetaElement",
components: {multiselect, VueSimpleRangeSlider},
data: function () {
return {
b: true,
content: this.value,
value: '',
t: window.translate,
classes: 'form-control',
elms: [],
defaults: {},
ext: false,
state: {range: [parseInt(this.minm), parseInt(this.maxm)], number: 1000}
}
},
props: ['jdata', 'searchable', 'defz', 'cls', 'minm', 'maxm','langg'],
1 year ago
mounted() {
this.updateJdata(this.jdata, this.defz);
if (getParameterByName('to') !== null) {
this.state.range[1] = getParameterByName('to');
}
if (getParameterByName('from') !== null) {
this.state.range[0] = getParameterByName('from');
}
if (getParameterByName('ext') !== null) {
this.ext = true;
}
if (getParameterByName('sort') !== null) {
document.querySelector('#' + getParameterByName('sort')).click();
}
},
methods: {
makeLabel(lbl){
if ( typeof lbl == 'object'){
return lbl[this.langg];
}else{
return lbl;
}
},
1 year ago
apply: function () {
this.$refs.filter.submit();
},
changeSort: function (val, e) {
let x = document.querySelector('.badge.bg-primary');
x.classList.remove('bg-primary');
x.classList.add('bg-secondary');
document.querySelector('#sort').value = val;
e.target.classList.remove('bg-secondary');
e.target.classList.add('bg-primary');
},
price: function () {
console.log(this.state);
},
upd: function (name, data) {
this.defaults[name] = data;
this.$forceUpdate();
},
rem: function (name, value) {
for (const x in this.defaults[name]) {
let val = this.defaults[name][x];
if (val.value === value.value) {
this.defaults[name].splice(x, 1);
this.$forceUpdate();
return;
}
}
},
makeVal: function (ob) {
return JSON.stringify(ob);
},
updateJdata: function (e, def = []) {
try {
const params = new URL(window.location.href).searchParams;
// make defaults
for (const d of this.elms) {
switch (d.type) {
case 'checkbox':
if (params.get('meta[' + d.name + ']') !== null) {
this.defaults[d.name] = true;
} else {
this.defaults[d.name] = false;
}
break;
case 'select':
if (params.get('meta[' + d.name + ']') !== null) {
this.defaults[d.name] = params.get('meta[' + d.name + ']');
} else {
this.defaults[d.name] = '';
}
break;
case 'multi':
case 'singlemulti':
if (params.get('meta[' + d.name + ']') !== null) {
try {
this.defaults[d.name] = JSON.parse(params.get('meta[' + d.name + ']'));
} catch {
}
} else {
this.defaults[d.name] = [];
}
break;
default:
if (params.get('meta[' + d.name + ']') !== null) {
this.defaults[d.name] = params.get('meta[' + d.name + ']');
} else {
this.defaults[d.name] = '';
}
}
}
if (typeof e == 'string') {
this.elms = JSON.parse(e);
} else {
this.elms = e;
}
for (const e of this.elms) {
try {
e.options = JSON.parse(e.options);
// fix for multi select object
if (e.type === 'multi' || (e.type === '' && this.searchable)) {
this.defaults[e.name] = JSON.parse(this.defaults[e.name]);
}
// console.log(JSON.parse(e.options));
} catch {
}
}
} catch (e) {
this.elms = [];
console.log('no meta ele', e.message);
}
},
handleInput(e) {
this.$emit('input', this.content);
},
}
}
</script>
<style scoped>
.switch {
margin-top: 0px;
position: relative;
display: inline-block;
width: 35px;
height: 20px;
float: left;
}
.switch input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 16px;
width: 16px;
left: 2px;
bottom: 2px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked + .slider {
background-color: #1d68a7;
}
input:focus + .slider {
box-shadow: 0 0 1px #1d68a7;
}
input:checked + .slider:before {
-webkit-transform: translateX(16px);
-ms-transform: translateX(16px);
transform: translateX(16px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.scroll {
height: 150px;
overflow-y: scroll;
}
label {
margin-bottom: 4px;
}
select {
padding: 3px;
text-align: center;
}
</style>