"Taking over work in progress."

This commit is contained in:
Naida Vatric
2019-12-10 11:07:31 +01:00
10 changed files with 654 additions and 179 deletions

View File

@@ -199,6 +199,10 @@ const EMAIL_FREQUENCY = {
};
const HEATING_TYPE = {
ANY: {
id: "ANY",
title: "Svi"
},
NO_HEATING: {
id: "NO_HEATING",
title: "Nije uvedeno"
@@ -238,6 +242,10 @@ const HEATING_TYPE = {
};
const ACCESS_ROAD_TYPE = {
ANY: {
id: "ANY",
title: "Svi"
},
ASPHALT: {
id: "ASPHALT",
title: "Asfalt"

110
app/common/filterEnums.js Normal file
View File

@@ -0,0 +1,110 @@
const { AD_CATEGORY, ACCESS_ROAD_TYPE, HEATING_TYPE } = require("./enums");
const ADVANCED_BOOLEAN_FILTERS = [
{
dbField: "balcony",
title: "Balkon",
categoriesToShow: [
AD_CATEGORY.FLAT,
AD_CATEGORY.HOUSE,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.COTTAGE
]
},
{
dbField: "elevator",
title: "Lift",
categoriesToShow: [
AD_CATEGORY.FLAT,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.OFFICE
]
},
{
dbField: "newBuilding",
title: "Novogradnja",
categoriesToShow: [
AD_CATEGORY.FLAT,
AD_CATEGORY.HOUSE,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.COTTAGE,
AD_CATEGORY.OFFICE
]
}
];
const ADVANCED_SEGMENT_SELECT_FILTERS = [
{
dbField: "accessRoadType",
title: "Pristupni put",
values: Object.keys(ACCESS_ROAD_TYPE).map(key => ACCESS_ROAD_TYPE[key]),
categoriesToShow: [
AD_CATEGORY.FLAT,
AD_CATEGORY.HOUSE,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.COTTAGE,
AD_CATEGORY.OFFICE,
AD_CATEGORY.LAND,
AD_CATEGORY.GARAGE
]
}
// {
// dbField: "heatingType",
// title: "Vrsta grijanja",
// values: Object.keys(HEATING_TYPE).map(key => HEATING_TYPE[key]),
// categoriesToShow: [
// AD_CATEGORY.FLAT,
// AD_CATEGORY.HOUSE,
// AD_CATEGORY.APARTMENT,
// AD_CATEGORY.COTTAGE,
// AD_CATEGORY.OFFICE
// ]
// }
];
const ADVANCED_RANGE_FILTERS = [
{
id: "numberOfFloors",
title: "Broj spratova",
dbFieldMin: "numberOfFloorsMin",
dbFieldMax: "numberOfFloorsMax",
validValueMin: -1,
validValueMax: 50,
categoriesToShow: [AD_CATEGORY.HOUSE, AD_CATEGORY.COTTAGE]
},
{
id: "floor",
title: "Sprat",
dbFieldMin: "floorMin",
dbFieldMax: "floorMax",
validValueMin: -10,
validValueMax: 50,
categoriesToShow: [
AD_CATEGORY.FLAT,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.OFFICE
]
},
{
id: "numberOfRooms",
title: "Broj soba",
dbFieldMin: "numberOfRoomsMin",
dbFieldMax: "numberOfRoomsMax",
decimalPlaces: 1,
validValueMin: 0,
validValueMax: 200,
categoriesToShow: [
AD_CATEGORY.FLAT,
AD_CATEGORY.HOUSE,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.COTTAGE,
AD_CATEGORY.OFFICE
]
}
];
module.exports = {
ADVANCED_BOOLEAN_FILTERS,
ADVANCED_SEGMENT_SELECT_FILTERS,
ADVANCED_RANGE_FILTERS
};

View File

@@ -1,5 +1,10 @@
const { currentSearchRequest } = require("../helpers/url");
const { AD_CATEGORY, AD_TYPE } = require("../common/enums");
const { AD_CATEGORY, AD_TYPE, ACCESS_ROAD_TYPE } = require("../common/enums");
const {
ADVANCED_BOOLEAN_FILTERS,
ADVANCED_SEGMENT_SELECT_FILTERS,
ADVANCED_RANGE_FILTERS
} = require("../common/filterEnums");
const getFilters = async (req, res) => {
const searchRequest = await currentSearchRequest(req);
@@ -19,7 +24,18 @@ const getFilters = async (req, res) => {
sizeMin,
sizeMax,
gardenSizeMin,
gardenSizeMax
gardenSizeMax,
numberOfRoomsMin,
numberOfRoomsMax,
numberOfFloorsMin,
numberOfFloorsMax,
floorMin,
floorMax,
includeIncompleteAds,
balcony,
elevator,
newBuilding,
accessRoadType
} = searchRequest;
const category = AD_CATEGORY[realEstateType] || AD_CATEGORY.FLAT;
@@ -41,6 +57,40 @@ const getFilters = async (req, res) => {
return;
}
// TODO: Maybe this is slow, pay attention to this
const filterFilters = filterObject => {
const filterCategories = filterObject.categoriesToShow;
return filterCategories.indexOf(category) !== -1;
};
const advancedBooleanFilterObjects = ADVANCED_BOOLEAN_FILTERS.filter(
filterFilters
);
const advancedSegmentSelectFilterObjects = ADVANCED_SEGMENT_SELECT_FILTERS.filter(
filterFilters
);
const advancedRangeFilterObjects = ADVANCED_RANGE_FILTERS.filter(
filterFilters
);
const advancedBooleanFilterValues = {
includeIncompleteAds,
balcony,
elevator,
newBuilding
};
const advancedSegmentSelectFilterValues = {
accessRoadType
};
const advancedRangeFilterValues = {
numberOfFloorsMin,
numberOfFloorsMax,
numberOfRoomsMin,
numberOfRoomsMax,
floorMin,
floorMax
};
if (priceMin || priceMax) {
priceSliderOptions.start = [priceMin, priceMax];
}
@@ -58,7 +108,14 @@ const getFilters = async (req, res) => {
hasGardenSize,
priceSliderOptions: JSON.stringify(priceSliderOptions),
sizeSliderOptions: JSON.stringify(sizeSliderOptions),
gardenSizeSliderOptions: JSON.stringify(gardenSizeSliderOptions)
gardenSizeSliderOptions: JSON.stringify(gardenSizeSliderOptions),
advancedBooleanFilterObjects,
advancedBooleanFilterValues,
advancedSegmentSelectFilterObjects,
advancedSegmentSelectFilterValues,
advancedRangeFilterObjects,
advancedRangeFilterValues,
includeIncompleteAds
});
};
@@ -78,13 +135,91 @@ const postFilters = async (req, res) => {
const sizeMin = parseInt(req.body.sizeMin) || 0;
const sizeMax = parseInt(req.body.sizeMax) || 0;
//TODO: Filter validation
const advancedRangeFilters = {};
ADVANCED_RANGE_FILTERS.forEach(filter => {
let parsingFunction = parseInt;
if (filter.decimalPlaces) {
parsingFunction = parseFloat;
}
advancedRangeFilters[filter.dbFieldMin] = parsingFunction(
req.body[filter.dbFieldMin]
);
advancedRangeFilters[filter.dbFieldMax] = parsingFunction(
req.body[filter.dbFieldMax]
);
advancedRangeFilters[filter.dbFieldMin] = isNaN(
advancedRangeFilters[filter.dbFieldMin]
)
? null
: advancedRangeFilters[filter.dbFieldMin];
advancedRangeFilters[filter.dbFieldMax] = isNaN(
advancedRangeFilters[filter.dbFieldMax]
)
? null
: advancedRangeFilters[filter.dbFieldMax];
try {
if (filter.decimalPlaces) {
advancedRangeFilters[filter.dbFieldMin] = advancedRangeFilters[
filter.dbFieldMin
].toFixed(filter.decimalPlaces);
advancedRangeFilters[filter.dbFieldMax] = advancedRangeFilters[
filter.dbFieldMax
].toFixed(filter.decimalPlaces);
}
} catch (e) {
advancedRangeFilters[filter.dbFieldMin] = null;
advancedRangeFilters[filter.dbFieldMax] = null;
}
if (
advancedRangeFilters[filter.dbFieldMin] < filter.validValueMin ||
advancedRangeFilters[filter.dbFieldMin] > filter.validValueMax
) {
advancedRangeFilters[filter.dbFieldMin] = filter.validValueMin;
}
if (
advancedRangeFilters[filter.dbFieldMax] < filter.validValueMin ||
advancedRangeFilters[filter.dbFieldMax] > filter.validValueMax
) {
advancedRangeFilters[filter.dbFieldMax] = filter.validValueMax;
}
});
const includeIncompleteAds = req.body.includeIncompleteAds === "on";
const balcony = req.body.balcony === "on";
const elevator = req.body.elevator === "on";
const newBuilding = req.body.newBuilding === "on";
const accessRoadType = req.body.accessRoadType;
if (!ACCESS_ROAD_TYPE[accessRoadType]) {
res.render("notFound", { title: " Greška !" });
return;
}
//TODO: Filter validation
searchRequest.priceMin = priceMin;
searchRequest.priceMax = priceMax;
searchRequest.sizeMin = sizeMin;
searchRequest.sizeMax = sizeMax;
for (const filter of Object.keys(advancedRangeFilters)) {
searchRequest[filter] = advancedRangeFilters[filter];
}
searchRequest.balcony = balcony;
searchRequest.elevator = elevator;
searchRequest.newBuilding = newBuilding;
searchRequest.includeIncompleteAds = includeIncompleteAds;
searchRequest.accessRoadType = accessRoadType;
if (
req.body.gardenSizeMin !== undefined &&
req.body.gardenSizeMax !== undefined

View File

@@ -0,0 +1,64 @@
"use strict";
const { ACCESS_ROAD_TYPE, HEATING_TYPE } = require("../common/enums");
module.exports = {
up: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.addColumn("SearchRequests", "includeIncompleteAds", {
type: Sequelize.BOOLEAN
}),
queryInterface.addColumn("SearchRequests", "balcony", {
type: Sequelize.BOOLEAN
}),
queryInterface.addColumn("SearchRequests", "newBuilding", {
type: Sequelize.BOOLEAN
}),
queryInterface.addColumn("SearchRequests", "elevator", {
type: Sequelize.BOOLEAN
}),
queryInterface.addColumn("SearchRequests", "numberOfRoomsMin", {
type: Sequelize.REAL
}),
queryInterface.addColumn("SearchRequests", "numberOfRoomsMax", {
type: Sequelize.REAL
}),
queryInterface.addColumn("SearchRequests", "numberOfFloorsMin", {
type: Sequelize.INTEGER
}),
queryInterface.addColumn("SearchRequests", "numberOfFloorsMax", {
type: Sequelize.INTEGER
}),
queryInterface.addColumn("SearchRequests", "floorMin", {
type: Sequelize.INTEGER
}),
queryInterface.addColumn("SearchRequests", "floorMax", {
type: Sequelize.INTEGER
}),
queryInterface.addColumn("SearchRequests", "accessRoadType", {
type: Sequelize.TEXT,
defaultValue: ACCESS_ROAD_TYPE.ANY.id
}),
queryInterface.addColumn("SearchRequests", "heatingType", {
type: Sequelize.TEXT,
defaultValue: HEATING_TYPE.ANY.id
})
]);
},
down: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.removeColumn("SearchRequests", "includeIncompleteAds"),
queryInterface.removeColumn("SearchRequests", "balcony"),
queryInterface.removeColumn("SearchRequests", "newBuilding"),
queryInterface.removeColumn("SearchRequests", "elevator"),
queryInterface.removeColumn("SearchRequests", "numberOfRoomsMin"),
queryInterface.removeColumn("SearchRequests", "numberOfRoomsMax"),
queryInterface.removeColumn("SearchRequests", "numberOfFloorsMin"),
queryInterface.removeColumn("SearchRequests", "numberOfFloorsMax"),
queryInterface.removeColumn("SearchRequests", "floorMin"),
queryInterface.removeColumn("SearchRequests", "floorMax"),
queryInterface.removeColumn("SearchRequests", "accessRoadType"),
queryInterface.removeColumn("SearchRequests", "heatingType")
]);
}
};

View File

@@ -69,7 +69,19 @@ module.exports = (sequelize, DataTypes) => {
},
deletedEmail: {
type: DataTypes.TEXT
}
},
includeIncompleteAds: DataTypes.BOOLEAN,
balcony: DataTypes.BOOLEAN,
elevator: DataTypes.BOOLEAN,
newBuilding: DataTypes.BOOLEAN,
numberOfRoomsMin: DataTypes.REAL,
numberOfRoomsMax: DataTypes.REAL,
numberOfFloorsMin: DataTypes.INTEGER,
numberOfFloorsMax: DataTypes.INTEGER,
floorMin: DataTypes.INTEGER,
floorMax: DataTypes.INTEGER,
accessRoadType: DataTypes.TEXT,
heatingType: DataTypes.TEXT
});
return SearchRequest;

View File

@@ -110,3 +110,47 @@ h3 {
.collection a.collection-item:not(.active):hover {
background-color: rgba(2, 173, 186, 0.2);
}
.tabs .tab a {
color: #02adba;
-webkit-transition: color 0.28s ease, background-color 0.28s ease;
transition: color 0.28s ease, background-color 0.28s ease;
}
.tabs .tab a:focus,
.tabs .tab a:focus.active {
background-color: rgba(2, 173, 186, 0.2);
}
.tabs .tab a:hover,
.tabs .tab a.active {
color: #02adba;
}
.tabs .indicator {
background-color: #02adba;
}
[type="checkbox"].filled-in:checked + span:not(.lever):after {
border: 2px solid #02adba;
background-color: #02adba;
}
[type="checkbox"].filled-in:not(:checked) + span:not(.lever):after {
background-color: transparent;
border: 2px solid #02adba;
}
.distinguished {
border: 2px solid #02adba;
border-radius: 4px;
padding: 5px 5px 3px 5px;
margin-left: -5px;
}
.checkbox-label {
color: black;
font-size: 14px;
}
.column-label {
position: relative;
margin-top: 2rem;
margin-bottom: 1rem;
}

View File

@@ -25,6 +25,12 @@
border-right: 1px solid #02adba;
}
.segmented.small [type="radio"]:not(:checked) + span,
.segmented.small [type="radio"]:checked + span {
padding-left: 7px;
padding-right: 7px;
}
.segmented :last-child .label {
border-right: none;
}

View File

@@ -0,0 +1,69 @@
<br>
<% for (const filter of advancedBooleanFilterObjects){ %>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="<%= filter.dbField %>"
<% if (advancedBooleanFilterValues[filter.dbField]) { %>
checked
<% } %>>
<span><%= filter.title %></span>
</label>
</p>
<% } %>
<br>
<% for (const filter of advancedRangeFilterObjects){ %>
<div class="row">
<p class="column-label col s5 m3 l2">
<%= filter.title %>
</p>
<div class="input-field col s3 m4 l5">
<input
id="<%= filter.dbFieldMin %>"
name="<%= filter.dbFieldMin %>"
type="number"
value="<%= advancedRangeFilterValues[filter.dbFieldMin] !== undefined ? advancedRangeFilterValues[filter.dbFieldMin] : ""%>"
>
<label for="<%= filter.dbFieldMin %>">Od</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="<%= filter.dbFieldMax %>"
name="<%= filter.dbFieldMax %>"
type="number"
value="<%= advancedRangeFilterValues[filter.dbFieldMax] !== undefined ? advancedRangeFilterValues[filter.dbFieldMax] : ""%>"
>
<label for="<%= filter.dbFieldMax %>">Do</label>
</div>
</div>
<% } %>
<br>
<% for (const filter of advancedSegmentSelectFilterObjects){ %>
<div>
<label class="checkbox-label"><%= filter.title %>: </label><br><br>
<span class="segmented small">
<% for (const segmentObject of filter.values) { %>
<label>
<input type="radio" name="<%= filter.dbField %>" value="<%= segmentObject.id %>"
<% if (advancedSegmentSelectFilterValues[filter.dbField] === segmentObject.id) { %>
checked
<% } %>>
<span class="label"><%= segmentObject.title %></span>
</label>
<% } %>
</span>
</div>
<% } %>
<br>
<p class="distinguished">
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="includeIncompleteAds"
<% if (includeIncompleteAds) { %>
checked
<% } %>>
<span>Uključi i oglase bez potpunih informacija</span>
</label>
</p>

View File

@@ -1,63 +1,20 @@
<br>
<form id="filtersForm" method="POST">
<br>
<div class="row center-align">
<h5>Cijena</h5>
<br><br>
<div class="center-align no-ui-slider" id="priceFilter"></div>
</div>
<br>
<div class="row">
<div class="col s5 m3 l3 push-m1 push-l2">
<input class="sliderInputBox" type="number" id="priceMin" name="priceMin">
<div class="col s12">
<ul class="tabs">
<li class="tab col s6"><a href="#standardFilters">Filteri</a></li>
<li class="tab col s6"><a href="#advancedFilters">Napredni filteri</a></li>
</ul>
</div>
<div class="col s5 m3 l3 push-s1 push-m4 push-l4">
<input class="sliderInputBox" type="number" id="priceMax" name="priceMax">
<div id="standardFilters" class="col s12">
<%- include("./standardFilters.ejs") %>
</div>
<div id="advancedFilters" class="col s12">
<%- include("./advancedFilters.ejs") %>
</div>
</div>
<br>
<div class="row center-align">
<h5>Površina</h5>
<br><br>
<div class="center-align no-ui-slider" id="sizeFilter"></div>
</div>
<br>
<div class="row">
<div class="col s5 m3 l3 push-m1 push-l2">
<input class="sliderInputBox" type="number" id="sizeMin" name="sizeMin">
</div>
<div class="col s5 m3 l3 push-s1 push-m4 push-l4">
<input class="sliderInputBox" type="number" id="sizeMax" name="sizeMax">
</div>
</div>
<br>
<% if(hasGardenSize) { %>
<div class="row center-align">
<h5>Površina okućnice</h5>
<br><br>
<div class="center-align no-ui-slider" id="gardenSizeFilter"></div>
</div>
<br>
<div class="row">
<div class="col s5 m3 l3 push-m1 push-l2">
<input class="sliderInputBox" type="number" id="gardenSizeMin" name="gardenSizeMin">
</div>
<div class="col s5 m3 l3 push-s1 push-m4 push-l4">
<input class="sliderInputBox" type="number" id="gardenSizeMax" name="gardenSizeMax">
</div>
</div>
<% } %>
<div class="row">
<div class="col s6 push-s3">
<a id="submit" href="#" class="welcome-center-button waves-effect waves-light btn">Dalje</a>
@@ -66,125 +23,7 @@
</form>
<script>
$(document).ready(function() {
const priceSliderOptions = <%- priceSliderOptions %>;
const sizeSliderOptions = <%- sizeSliderOptions %>;
const priceStep = priceSliderOptions.step;
const sizeStep = sizeSliderOptions.step;
delete priceSliderOptions.step;
delete sizeSliderOptions.step;
function updatePriceInputs(values, handle, unencoded) {
$("#priceMin").val(Math.round(unencoded[0]/priceStep)*priceStep);
$("#priceMax").val(Math.round(unencoded[1]/priceStep)*priceStep);
}
function updateSizeInputs(values, handle, unencoded) {
$("#sizeMin").val(Math.round(unencoded[0]/sizeStep)*sizeStep);
$("#sizeMax").val(Math.round(unencoded[1]/sizeStep)*sizeStep);
}
const priceSlider = document.getElementById("priceFilter");
const sizeSlider = document.getElementById("sizeFilter");
const priceSliderObject = noUiSlider.create(priceSlider, priceSliderOptions);
const sizeSliderObject = noUiSlider.create(sizeSlider, sizeSliderOptions);
priceSliderObject.on('slide', updatePriceInputs);
sizeSliderObject.on('slide', updateSizeInputs);
function priceMinChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const currentValues = priceSliderObject.get();
const newValue = element.currentTarget.value;
const fixedNewValue = newValue > currentValues[1] ? currentValues[1] : newValue;
priceSliderObject.set([fixedNewValue, null]);
$("#priceMin").val(Math.round(priceSliderObject.get()[0]));
}
}
function priceMaxChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const newValue = element.currentTarget.value;
priceSliderObject.set([null, newValue]);
$("#priceMax").val(Math.round(priceSliderObject.get()[1]));
}
}
$("#priceMin").val(priceSliderOptions.start[0]);
$("#priceMax").val(priceSliderOptions.start[1]);
$("#priceMin").change(priceMinChangeHandler);
$("#priceMax").change(priceMaxChangeHandler);
function sizeMinChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const currentValues = sizeSliderObject.get();
const newValue = element.currentTarget.value;
const fixedNewValue = newValue > currentValues[1] ? currentValues[1] : newValue;
sizeSliderObject.set([fixedNewValue, null]);
$("#sizeMin").val(Math.round(sizeSliderObject.get()[0]));
}
}
function sizeMaxChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const newValue = element.currentTarget.value;
sizeSliderObject.set([null, newValue]);
$("#sizeMax").val(Math.round(sizeSliderObject.get()[1]));
}
}
$("#sizeMin").val(sizeSliderOptions.start[0]);
$("#sizeMax").val(sizeSliderOptions.start[1]);
$("#sizeMin").change(sizeMinChangeHandler);
$("#sizeMax").change(sizeMaxChangeHandler);
<% if(hasGardenSize) { %>
const gardenSizeSliderOptions = <%- gardenSizeSliderOptions %>;
const gardenSizeStep = gardenSizeSliderOptions.step;
delete gardenSizeSliderOptions.step;
function updateGardenSizeInputs(values, handle, unencoded) {
$("#gardenSizeMin").val(Math.round(unencoded[0]/gardenSizeStep)*gardenSizeStep);
$("#gardenSizeMax").val(Math.round(unencoded[1]/gardenSizeStep)*gardenSizeStep);
}
const gardenSizeSlider = document.getElementById("gardenSizeFilter");
const gardenSizeSliderObject = noUiSlider.create(gardenSizeSlider, gardenSizeSliderOptions);
gardenSizeSliderObject.on('slide', updateGardenSizeInputs);
function gardenSizeMinChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const currentValues = gardenSizeSliderObject.get();
const newValue = element.currentTarget.value;
const fixedNewValue = newValue > currentValues[1] ? currentValues[1] : newValue;
gardenSizeSliderObject.set([fixedNewValue, null]);
$("#gardenSizeMin").val(Math.round(gardenSizeSliderObject.get()[0]));
}
}
function gardenSizeMaxChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const newValue = element.currentTarget.value;
gardenSizeSliderObject.set([null, newValue]);
$("#gardenSizeMin").val(Math.round(gardenSizeSliderObject.get()[0]));
}
}
$("#gardenSizeMin").val(gardenSizeSliderOptions.start[0]);
$("#gardenSizeMax").val(gardenSizeSliderOptions.start[1]);
$("#gardenSizeMin").change("step", gardenSizeMinChangeHandler);
$("#gardenSizeMax").change("step", gardenSizeMaxChangeHandler);
<% } %>
$("#submit").click(function() {
const priceFilterValues = priceSlider.noUiSlider.get();
$("#priceFilterMin").val(priceFilterValues[0]);
$("#priceFilterMax").val(priceFilterValues[1]);
const sizeFilterValues = sizeSlider.noUiSlider.get();
$("#sizeFilterMin").val(sizeFilterValues[0]);
$("#sizeFilterMax").val(sizeFilterValues[1]);
<% if (hasGardenSize) { %>
const gardenSizeFilterValues = gardenSizeSlider.noUiSlider.get();
$("#gardenSizeFilterMin").val(gardenSizeFilterValues[0]);
$("#gardenSizeFilterMax").val(gardenSizeFilterValues[1]);
<% } %>
$("#filtersForm").submit();
});
$(document).ready(function(){
$('.tabs').tabs();
});
</script>

View File

@@ -0,0 +1,188 @@
<br>
<div class="row center-align">
<h5>Cijena</h5>
<br><br>
<div class="col s12">
<div class="center-align no-ui-slider" id="priceFilter"></div>
</div>
</div>
<br>
<div class="row">
<div class="col s5 m3 l3 push-m1 push-l2">
<input class="sliderInputBox" type="number" id="priceMin" name="priceMin">
</div>
<div class="col s5 m3 l3 push-s1 push-m4 push-l4">
<input class="sliderInputBox" type="number" id="priceMax" name="priceMax">
</div>
</div>
<br>
<div class="row center-align">
<h5>Površina</h5>
<br><br>
<div class="col s12">
<div class="center-align no-ui-slider" id="sizeFilter"></div>
</div>
</div>
<br>
<div class="row">
<div class="col s5 m3 l3 push-m1 push-l2">
<input class="sliderInputBox" type="number" id="sizeMin" name="sizeMin">
</div>
<div class="col s5 m3 l3 push-s1 push-m4 push-l4">
<input class="sliderInputBox" type="number" id="sizeMax" name="sizeMax">
</div>
</div>
<br>
<% if(hasGardenSize) { %>
<div class="row center-align">
<h5>Površina okućnice</h5>
<br><br>
<div class="col s12">
<div class="center-align no-ui-slider" id="gardenSizeFilter"></div>
</div>
</div>
<br>
<div class="row">
<div class="col s5 m3 l3 push-m1 push-l2">
<input class="sliderInputBox" type="number" id="gardenSizeMin" name="gardenSizeMin">
</div>
<div class="col s5 m3 l3 push-s1 push-m4 push-l4">
<input class="sliderInputBox" type="number" id="gardenSizeMax" name="gardenSizeMax">
</div>
</div>
<% } %>
<script>
$(document).ready(function() {
const priceSliderOptions = <%- priceSliderOptions %>;
const sizeSliderOptions = <%- sizeSliderOptions %>;
const priceStep = priceSliderOptions.step;
const sizeStep = sizeSliderOptions.step;
delete priceSliderOptions.step;
delete sizeSliderOptions.step;
function updatePriceInputs(values, handle, unencoded) {
$("#priceMin").val(Math.round(unencoded[0]/priceStep)*priceStep);
$("#priceMax").val(Math.round(unencoded[1]/priceStep)*priceStep);
}
function updateSizeInputs(values, handle, unencoded) {
$("#sizeMin").val(Math.round(unencoded[0]/sizeStep)*sizeStep);
$("#sizeMax").val(Math.round(unencoded[1]/sizeStep)*sizeStep);
}
const priceSlider = document.getElementById("priceFilter");
const sizeSlider = document.getElementById("sizeFilter");
const priceSliderObject = noUiSlider.create(priceSlider, priceSliderOptions);
const sizeSliderObject = noUiSlider.create(sizeSlider, sizeSliderOptions);
priceSliderObject.on('slide', updatePriceInputs);
sizeSliderObject.on('slide', updateSizeInputs);
function priceMinChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const currentValues = priceSliderObject.get();
const newValue = element.currentTarget.value;
const fixedNewValue = newValue > currentValues[1] ? currentValues[1] : newValue;
priceSliderObject.set([fixedNewValue, null]);
$("#priceMin").val(Math.round(priceSliderObject.get()[0]));
}
}
function priceMaxChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const newValue = element.currentTarget.value;
priceSliderObject.set([null, newValue]);
$("#priceMax").val(Math.round(priceSliderObject.get()[1]));
}
}
$("#priceMin").val(priceSliderOptions.start[0]);
$("#priceMax").val(priceSliderOptions.start[1]);
$("#priceMin").change(priceMinChangeHandler);
$("#priceMax").change(priceMaxChangeHandler);
function sizeMinChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const currentValues = sizeSliderObject.get();
const newValue = element.currentTarget.value;
const fixedNewValue = newValue > currentValues[1] ? currentValues[1] : newValue;
sizeSliderObject.set([fixedNewValue, null]);
$("#sizeMin").val(Math.round(sizeSliderObject.get()[0]));
}
}
function sizeMaxChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const newValue = element.currentTarget.value;
sizeSliderObject.set([null, newValue]);
$("#sizeMax").val(Math.round(sizeSliderObject.get()[1]));
}
}
$("#sizeMin").val(sizeSliderOptions.start[0]);
$("#sizeMax").val(sizeSliderOptions.start[1]);
$("#sizeMin").change(sizeMinChangeHandler);
$("#sizeMax").change(sizeMaxChangeHandler);
<% if(hasGardenSize) { %>
const gardenSizeSliderOptions = <%- gardenSizeSliderOptions %>;
const gardenSizeStep = gardenSizeSliderOptions.step;
delete gardenSizeSliderOptions.step;
function updateGardenSizeInputs(values, handle, unencoded) {
$("#gardenSizeMin").val(Math.round(unencoded[0]/gardenSizeStep)*gardenSizeStep);
$("#gardenSizeMax").val(Math.round(unencoded[1]/gardenSizeStep)*gardenSizeStep);
}
const gardenSizeSlider = document.getElementById("gardenSizeFilter");
const gardenSizeSliderObject = noUiSlider.create(gardenSizeSlider, gardenSizeSliderOptions);
gardenSizeSliderObject.on('slide', updateGardenSizeInputs);
function gardenSizeMinChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const currentValues = gardenSizeSliderObject.get();
const newValue = element.currentTarget.value;
const fixedNewValue = newValue > currentValues[1] ? currentValues[1] : newValue;
gardenSizeSliderObject.set([fixedNewValue, null]);
$("#gardenSizeMin").val(Math.round(gardenSizeSliderObject.get()[0]));
}
}
function gardenSizeMaxChangeHandler(element) {
if (element && element.currentTarget && element.currentTarget.value){
const newValue = element.currentTarget.value;
gardenSizeSliderObject.set([null, newValue]);
$("#gardenSizeMin").val(Math.round(gardenSizeSliderObject.get()[0]));
}
}
$("#gardenSizeMin").val(gardenSizeSliderOptions.start[0]);
$("#gardenSizeMax").val(gardenSizeSliderOptions.start[1]);
$("#gardenSizeMin").change("step", gardenSizeMinChangeHandler);
$("#gardenSizeMax").change("step", gardenSizeMaxChangeHandler);
<% } %>
$("#submit").click(function() {
const priceFilterValues = priceSlider.noUiSlider.get();
$("#priceFilterMin").val(priceFilterValues[0]);
$("#priceFilterMax").val(priceFilterValues[1]);
const sizeFilterValues = sizeSlider.noUiSlider.get();
$("#sizeFilterMin").val(sizeFilterValues[0]);
$("#sizeFilterMax").val(sizeFilterValues[1]);
<% if (hasGardenSize) { %>
const gardenSizeFilterValues = gardenSizeSlider.noUiSlider.get();
$("#gardenSizeFilterMin").val(gardenSizeFilterValues[0]);
$("#gardenSizeFilterMax").val(gardenSizeFilterValues[1]);
<% } %>
$("#filtersForm").submit();
});
});
</script>