Kivi original ads input #105

Open
RabbIT09-n wants to merge 29 commits from kivi-original-ads-input into master
12 changed files with 1248 additions and 14 deletions
Showing only changes of commit edb22266bd - Show all commits

View File

@@ -62,7 +62,10 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.OFFICE,
AD_CATEGORY.LAND,
AD_CATEGORY.GARAGE
]
],
constraint: {
numericality: true
}
},
{
dbField: "area",
@@ -75,12 +78,19 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.OFFICE,
AD_CATEGORY.LAND,
AD_CATEGORY.GARAGE
]
],
constraint: {
numericality: true,
presence: true
}
},
{
dbField: "gardenSize",
title: "Površina okućnice (m\xB2)",
categoriesToShow: [AD_CATEGORY.HOUSE, AD_CATEGORY.COTTAGE]
categoriesToShow: [AD_CATEGORY.HOUSE, AD_CATEGORY.COTTAGE],
constraint: {
numericality: true
}
},
{
dbField: "numberOfRooms",
@@ -91,7 +101,13 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.APARTMENT,
AD_CATEGORY.COTTAGE,
AD_CATEGORY.OFFICE
]
],
constraint: {
numericality: {
onlyInteger: true,
greaterThanOrEqualTo: 0
}
}
},
{
dbField: "numberOfFloors",
@@ -101,7 +117,12 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.HOUSE,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.COTTAGE
]
],
constraint: {
numericality: {
onlyInteger: true
}
}
},
{
dbField: "floor",
@@ -110,7 +131,12 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.FLAT,
AD_CATEGORY.APARTMENT,
AD_CATEGORY.OFFICE
]
],
constraint: {
numericality: {
onlyInteger: true
}
}
},
{
dbField: "title",
@@ -123,7 +149,10 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.OFFICE,
AD_CATEGORY.LAND,
AD_CATEGORY.GARAGE
]
],
constraint: {
presence: true
}
},
{
dbField: "shortDescription",
@@ -136,7 +165,8 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.OFFICE,
AD_CATEGORY.LAND,
AD_CATEGORY.GARAGE
]
],
constraint: {}
},
{
dbField: "streetName",
@@ -149,7 +179,8 @@ const BASIC_INPUT_PUBLISH = [
AD_CATEGORY.OFFICE,
AD_CATEGORY.LAND,
AD_CATEGORY.GARAGE
]
],
constraint: {}
}
];

View File

@@ -2,6 +2,8 @@ const { currentRealEstate } = require("../helpers/url");
const { createRealEstate } = require("../helpers/db/realEstate");
const { getKiviOriginalById } = require("../helpers/db/kiviOriginal");
const validate = require("validate.js");
const {
AD_CATEGORY,
FURNISHING_TYPE,
@@ -162,7 +164,8 @@ const getPublishInputs = async (req, res) => {
basicInputInputs,
basicInputValues,
additionalInputInputs,
additionalInputValues
additionalInputValues,
validate: validate
});
};

View File

@@ -158,3 +158,7 @@ h3 {
.estates-link {
color: rgba(0, 0, 0, 0.87);
}
.error {
color: #cc0033;
}

View File

@@ -16,6 +16,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/validate.js/0.13.1/validate.min.js"></script>
<meta charset="UTF-8" />
<link rel="stylesheet" href="/assets/main.css">
<link rel="stylesheet" href="/assets/segment.css">

View File

@@ -4,12 +4,13 @@
Unesite kontakt email i objavite oglas.
<br>
<div class="row center-align input-field col s3 m4 l5">
<div class="row center-align input-field col s3 m4 l5 form-group">
<input
id="email"
name="email"
type="email"
>
<div class="messages"></div>
<label for="email">Email</label>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<br>
<form id="publishForm" method="POST">
<form id="publishForm" method="POST" novalidate>
<div class="row">
<div class="col s12">
<ul class="tabs">
@@ -28,13 +28,83 @@
</form>
<script>
$(document).ready(function(){
$('.tabs').tabs();
const validateEmail = $email => {
const regexEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
return regexEmail.test($email);
}
const form = document.querySelector("#publishForm");
function showErrors(form, errors) {
// We loop through all the inputs and show the errors for that input
//_.each(form.querySelectorAll("input[name], select[name]"), function(input) {
// Since the errors can be null if no errors were found we need to handle
// that
showErrorsForInput(input, errors && errors[input.name]);
// });
}
// Shows the errors for a specific input
function showErrorsForInput(input, errors) {
// This is the root of the input
var formGroup = closestParent(input.parentNode, "form-group"),
// Find where the error messages will be insert into
messages = formGroup.querySelector(".messages");
// First we remove any old messages and resets the classes
resetFormGroup(formGroup);
// If we have errors
if (errors) {
// we first mark the group has having errors
formGroup.classList.add("has-error");
// then we append all the errors
$.each(errors, function(error) {
addError(messages, errors[error]);
});
} else {
// otherwise we simply mark it as success
formGroup.classList.add("has-success");
}
}
// Recusively finds the closest parent that has the specified class
function closestParent(child, className) {
if (!child || child == document) {
return null;
}
if (child.classList.contains(className)) {
return child;
} else {
return closestParent(child.parentNode, className);
}
}
function resetFormGroup(formGroup) {
formGroup.classList.remove("has-error");
formGroup.classList.remove("has-success");
$.each(formGroup.querySelectorAll(".help-block.error"), function(el) {
el.parentNode.removeChild(el);
});
}
// Adds the specified error with the following markup
// <p class="help-block error">[message]</p>
function addError(messages, error) {
var block = document.createElement("p");
block.classList.add("help-block");
block.classList.add("error");
block.innerText = error;
messages.appendChild(block);
}
$("#submit").click( function () {
const mapBounds = map.getBounds();
const currentLocation = marker.getPosition();
$("#north").val(mapBounds.getNorthEast().lat());
$("#south").val(mapBounds.getSouthWest().lat());
$("#east").val(mapBounds.getNorthEast().lng());
@@ -47,8 +117,20 @@
document.getElementById("autocompleteInput").value
);
const errors = validateEmail($("#email").val());
if (errors) {
$("#publishForm").submit();
}
else {
const errorMsgs = ["Unesite validan email."];
const email = document.querySelector("#email");
$("#publishForm").submit();
showErrorsForInput( email, errorMsgs)
}
});
});

187
help.js Normal file
View File

@@ -0,0 +1,187 @@
(function() {
// Before using it we must add the parse and format functions
// Here is a sample implementation using moment.js
validate.extend(validate.validators.datetime, {
// The value is guaranteed not to be null or undefined but otherwise it
// could be anything.
parse: function(value, options) {
return +moment.utc(value);
},
// Input is a unix timestamp
format: function(value, options) {
var format = options.dateOnly ? "YYYY-MM-DD" : "YYYY-MM-DD hh:mm:ss";
return moment.utc(value).format(format);
}
});
// These are the constraints used to validate the form
var constraints = {
email: {
// Email is required
presence: true,
// and must be an email (duh)
email: true
},
password: {
// Password is also required
presence: true,
// And must be at least 5 characters long
length: {
minimum: 5
}
},
"confirm-password": {
// You need to confirm your password
presence: true,
// and it needs to be equal to the other password
equality: {
attribute: "password",
message: "^The passwords does not match"
}
},
username: {
// You need to pick a username too
presence: true,
// And it must be between 3 and 20 characters long
length: {
minimum: 3,
maximum: 20
},
format: {
// We don't allow anything that a-z and 0-9
pattern: "[a-z0-9]+",
// but we don't care if the username is uppercase or lowercase
flags: "i",
message: "can only contain a-z and 0-9"
}
},
birthdate: {
// The user needs to give a birthday
presence: true,
// and must be born at least 18 years ago
date: {
latest: moment().subtract(18, "years"),
message: "^You must be at least 18 years old to use this service"
}
},
country: {
// You also need to input where you live
presence: true,
// And we restrict the countries supported to Sweden
inclusion: {
within: ["SE"],
// The ^ prevents the field name from being prepended to the error
message: "^Sorry, this service is for Sweden only"
}
},
zip: {
// Zip is optional but if specified it must be a 5 digit long number
format: {
pattern: "\\d{5}"
}
},
"number-of-children": {
presence: true,
// Number of children has to be an integer >= 0
numericality: {
onlyInteger: true,
greaterThanOrEqualTo: 0
}
}
};
// Hook up the form so we can prevent it from being posted
var form = document.querySelector("form#main");
form.addEventListener("submit", function(ev) {
ev.preventDefault();
handleFormSubmit(form);
});
// Hook up the inputs to validate on the fly
var inputs = document.querySelectorAll("input, textarea, select");
for (var i = 0; i < inputs.length; ++i) {
inputs.item(i).addEventListener("change", function(ev) {
var errors = validate(form, constraints) || {};
showErrorsForInput(this, errors[this.name]);
});
}
function handleFormSubmit(form, input) {
// validate the form against the constraints
var errors = validate(form, constraints);
// then we update the form to reflect the results
showErrors(form, errors || {});
if (!errors) {
showSuccess();
}
}
// Updates the inputs with the validation errors
function showErrors(form, errors) {
// We loop through all the inputs and show the errors for that input
_.each(form.querySelectorAll("input[name], select[name]"), function(input) {
// Since the errors can be null if no errors were found we need to handle
// that
showErrorsForInput(input, errors && errors[input.name]);
});
}
// Shows the errors for a specific input
function showErrorsForInput(input, errors) {
// This is the root of the input
var formGroup = closestParent(input.parentNode, "form-group"),
// Find where the error messages will be insert into
messages = formGroup.querySelector(".messages");
// First we remove any old messages and resets the classes
resetFormGroup(formGroup);
// If we have errors
if (errors) {
// we first mark the group has having errors
formGroup.classList.add("has-error");
// then we append all the errors
_.each(errors, function(error) {
addError(messages, error);
});
} else {
// otherwise we simply mark it as success
formGroup.classList.add("has-success");
}
}
// Recusively finds the closest parent that has the specified class
function closestParent(child, className) {
if (!child || child == document) {
return null;
}
if (child.classList.contains(className)) {
return child;
} else {
return closestParent(child.parentNode, className);
}
}
function resetFormGroup(formGroup) {
// Remove the success and error classes
formGroup.classList.remove("has-error");
formGroup.classList.remove("has-success");
// and remove any old messages
_.each(formGroup.querySelectorAll(".help-block.error"), function(el) {
el.parentNode.removeChild(el);
});
}
// Adds the specified error with the following markup
// <p class="help-block error">[message]</p>
function addError(messages, error) {
var block = document.createElement("p");
block.classList.add("help-block");
block.classList.add("error");
block.innerText = error;
messages.appendChild(block);
}
function showSuccess() {
// We made it \:D/
alert("Success!");
}
})();

112
help2.js Normal file
View File

@@ -0,0 +1,112 @@
const validatorFunction = () => {
// These are the constraints used to validate the form --just email for now!
const constraints = {
email: {
email: {
message: "Proba"
},
// Email is required
presence: true,
// and must be an email (duh)
email: true
}
};
// Hook up the inputs to validate on the fly
const inputs = document.querySelectorAll("#email");
// inputs.on("change", ev => {
// const errors = validate(form, constraints) || {};
// showErrorsForInput(this, errors[this.name]);
// });
// var inputs = document.querySelectorAll("input, textarea, select");
for (var i = 0; i < inputs.length; ++i) {
inputs.item(i).addEventListener("change", function(ev) {
var errors = validate(form, constraints) || {};
showErrorsForInput(this, errors[this.name]);
});
}
const handleFormSubmit = (form, input) => {
// validate the form against the constraints
const errors = validate(form, constraints);
//
console.log("handleFormSubmit error:", errors);
// then we update the form to reflect the results
showErrors(form, errors || {});
if (!errors) {
showSuccess();
}
};
// Updates the inputs with the validation errors
const showErrors = (form, errors) => {
// We loop through all the inputs and show the errors for that input
$.each(form.querySelectorAll("input[name], select[name]"), input => {
// Since the errors can be null if no errors were found we need to handle
// that
showErrorsForInput(input, errors && errors[input.name]);
});
//showErrorsForInput(email, errors && errors[email]);
};
// Shows the errors for a specific input
const showErrorsForInput = (input, errors) => {
// This is the root of the input
const formGroup = closestParent(input.parentNode, "form-group"),
// Find where the error messages will be insert into
messages = formGroup.querySelector(".messages");
// First we remove any old messages and resets the classes
resetFormGroup(formGroup);
// If we have errors
if (errors) {
//
console.log("errors:", errors);
// we first mark the group has having errors
formGroup.classList.add("has-error");
// then we append all the errors
$.each(errors, error => {
addError(messages, errors[error]);
});
} else {
// otherwise we simply mark it as success
formGroup.classList.add("has-success");
}
};
// Recusively finds the closest parent that has the specified class
const closestParent = (child, className) => {
if (!child || child == document) {
return null;
}
if (child.classList.contains(className)) {
return child;
} else {
return closestParent(child.parentNode, className);
}
};
const resetFormGroup = formGroup => {
// Remove the success and error classes
formGroup.classList.remove("has-error");
formGroup.classList.remove("has-success");
// and remove any old messages
$.each(formGroup.querySelectorAll(".help-block.error"), el => {
el.parentNode.removeChild(el);
});
};
// Adds the specified error with the following markup
// <p class="help-block error">[message]</p>
const addError = (messages, error) => {
const block = document.createElement("p");
block.classList.add("help-block");
block.classList.add("error");
block.innerText = error;
messages.appendChild(block);
};
const showSuccess = () => {
// We made it \:D/
alert("Success!");
};
};

View File

@@ -5,6 +5,9 @@ const layout = require("express-layout");
const compression = require("compression");
const forceSSL = require("./app/helpers/forceSSL");
const validate = require("validate.js");
const {
APP_PORT,
CRAWLER_INTERVAL,

5
package-lock.json generated
View File

@@ -4309,6 +4309,11 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"validate.js": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/validate.js/-/validate.js-0.13.1.tgz",
"integrity": "sha512-PnFM3xiZ+kYmLyTiMgTYmU7ZHkjBZz2/+F0DaALc/uUtVzdCt1wAosvYJ5hFQi/hz8O4zb52FQhHZRC+uVkJ+g=="
},
"validator": {
"version": "10.11.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",

View File

@@ -51,7 +51,8 @@
"prettier": "^1.19.1",
"react-step-wizard": "^5.1.0",
"sequelize": "^5.18.4",
"sequelize-cli": "^5.5.0"
"sequelize-cli": "^5.5.0",
"validate.js": "^0.13.1"
},
"devDependencies": {
"nodemon": "^1.19.0"

804
sourcecode.txt Normal file
View File

@@ -0,0 +1,804 @@
<!doctype>
<html>
<head>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id="></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '');
</script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/13.1.5/nouislider.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/validate.js/0.13.1/validate.min.js"></script>
<meta charset="UTF-8" />
<link rel="stylesheet" href="/assets/main.css">
<link rel="stylesheet" href="/assets/segment.css">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png">
<link rel="manifest" href="/assets/site.webmanifest">
<link rel="mask-icon" href="/assets/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<meta name="title" content="Kivi.ba">
<meta name="description" content="Neka dom nađe vas">
<meta property="og:title" content="Kivi.ba">
<meta property="og:description" content="Neka dom nađe vas">
<meta property="og:image" content="http://www.kivi.ba/assets/images/thumbnail-big.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="627">
<meta property="og:url" content="https://www.kivi.ba">
<meta name="twitter:card" content="summary_large_image">
<meta property="og:site_name" content="Kivi.ba">
<meta name="twitter:image:alt" content="Kivi.ba - Neka dom nađe vas">
<title> Podaci o nekretnini - Kivi.ba</title>
</head>
<body>
<nav style="background-color: #02adba; margin: auto;">
<div class="row center-align">
<h6 class="title">Podaci o nekretnini</h6>
</div>
</nav>
<div class="container">
<br>
<form id="publishForm" method="POST" novalidate>
<div class="row">
<div class="col s12">
<ul class="tabs">
<li class="tab col s3"><a href="#publishBasicData">Osnovni podaci</a></li>
<li class="tab col s3"><a href="#publishAdditionalData">Dodatni podaci</a></li>
<li class="tab col s3"><a href="#publishLocation">Lokacija</a></li>
<li class="tab col s3"><a href="#publishEnd">Kraj</a></li>
</ul>
</div>
<div id="publishBasicData" class="col s12">
<br>
<div class="row">
<div class="input-field col s3 m4 l5">
<input
id="price"
name="price"
type="text"
value=""
>
<label for="price">Cijena (KM)</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="area"
name="area"
type="text"
value=""
>
<label for="area">Površina (m²)</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="gardenSize"
name="gardenSize"
type="text"
value=""
>
<label for="gardenSize">Površina okućnice (m²)</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="numberOfRooms"
name="numberOfRooms"
type="text"
value=""
>
<label for="numberOfRooms">Broj soba</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="numberOfFloors"
name="numberOfFloors"
type="text"
value=""
>
<label for="numberOfFloors">Broj spratova</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="title"
name="title"
type="text"
value=""
>
<label for="title">Naslov</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="shortDescription"
name="shortDescription"
type="text"
value=""
>
<label for="shortDescription">Opis</label>
</div>
<div class="input-field col s3 m4 l5">
<input
id="streetName"
name="streetName"
type="text"
value=""
>
<label for="streetName">Adresa</label>
</div>
</div>
<br>
<div class="row">
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="balcony"
>
<span>Balkon</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="newBuilding"
>
<span>Novogradnja</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="recentlyAdapted"
>
<span>Nedavno adaptirano</span>
</label>
</p>
</div>
<br>
<div>
<label class="checkbox-label">Namješten?: </label><br><br>
<span class="segmented small">
<label>
<input type="radio" name="furnishingType" value="NOT_FURNISHED"
>
<span class="label">Nenamješten</span>
</label>
<label>
<input type="radio" name="furnishingType" value="HALF_FURNISHED"
>
<span class="label">Polunamješten</span>
</label>
<label>
<input type="radio" name="furnishingType" value="FURNISHED"
>
<span class="label">Namješten</span>
</label>
</span>
</div>
</div>
<div id="publishAdditionalData" class="col s12">
<br>
<div class="row">
<div class="input-field col s3 m4 l5">
<textarea
id="longDescription"
form="publishForm"
name="longDescription"
cols="80" rows="15"
value=""
></textarea>
<label for="longDescription">Detaljan opis</label>
</div>
</div>
<br>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="water"
>
<span>Voda</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="electricity"
>
<span>Struja</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="drainageSystem"
>
<span>Kanalizacija</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="registeredInZkBooks"
>
<span>Uknjiženo</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="parking"
>
<span>Parking</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="garage"
>
<span>Garaža</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="gas"
>
<span>Plin</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="antiTheftDoor"
>
<span>Blindirana vrata</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="airCondition"
>
<span>Klimatizirano</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="phoneConnection"
>
<span>Telefon</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="cableTV"
>
<span>Kablovska</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="internet"
>
<span>Internet</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="basementAttic"
>
<span>Podrum-Tavan</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="storeRoom"
>
<span>Ostava</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="videoSurveillance"
>
<span>Video nadzor</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="alarm"
>
<span>Alarm</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="suitableForStudents"
>
<span>Za studente</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="includingBills"
>
<span>Uključen trošak režija</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="animalsAllowed"
>
<span>Kućni ljubimci dozvoljeni</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="pool"
>
<span>Bazen</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="exchange"
>
<span>Zamjena</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="urbanPlanPermit"
>
<span>Urbanistička dozvola</span>
</label>
</p>
<p>
<label class="checkbox-label">
<input type="checkbox" class="filled-in" name="buildingPermit"
>
<span>Građevinska dozvola</span>
</label>
</p>
<br>
<div>
<label class="checkbox-label">Pristupni put: </label><br><br>
<span class="segmented small">
<label>
<input type="radio" name="accessRoadType" value="ANY"
>
<span class="label">Svi</span>
</label>
<label>
<input type="radio" name="accessRoadType" value="ASPHALT"
>
<span class="label">Asfalt</span>
</label>
<label>
<input type="radio" name="accessRoadType" value="CONCRETE"
>
<span class="label">Beton</span>
</label>
<label>
<input type="radio" name="accessRoadType" value="MACADAM"
>
<span class="label">Makadam</span>
</label>
<label>
<input type="radio" name="accessRoadType" value="OTHER"
>
<span class="label">Drugo</span>
</label>
</span>
</div>
<div>
<label class="checkbox-label">Grijanje: </label><br><br>
<span class="segmented small">
<label>
<input type="radio" name="heatingType" value="ANY"
>
<span class="label">Svi</span>
</label>
<label>
<input type="radio" name="heatingType" value="NO_HEATING"
>
<span class="label">Nije uvedeno</span>
</label>
<label>
<input type="radio" name="heatingType" value="ELECTRICITY"
>
<span class="label">Struja</span>
</label>
<label>
<input type="radio" name="heatingType" value="GAS"
>
<span class="label">Plin</span>
</label>
<label>
<input type="radio" name="heatingType" value="WOOD"
>
<span class="label">Drva</span>
</label>
<label>
<input type="radio" name="heatingType" value="CENTRAL_CITY"
>
<span class="label">Centralno (gradsko)</span>
</label>
<label>
<input type="radio" name="heatingType" value="CENTRAL_BOILER"
>
<span class="label">Centralno (kotlovnica)</span>
</label>
<label>
<input type="radio" name="heatingType" value="CENTRAL_GAS"
>
<span class="label">Centralno (plin)</span>
</label>
<label>
<input type="radio" name="heatingType" value="HEAT_PUMP"
>
<span class="label">Toplotna pumpa</span>
</label>
<label>
<input type="radio" name="heatingType" value="OTHER"
>
<span class="label">Drugo</span>
</label>
</span>
</div>
</div>
<div id="publishLocation" class="col s12">
<div class="row center-align">
<h3>
Izaberite lokaciju nekretnine na mapi.
</h3>
</div>
<div class="row center-align">
<div class="col s12 m12 l12 xl12">
<input
id="autocompleteInput"
placeholder="Unesite grad, naselje ili ulicu..."
type="text"
/>
</div>
</div>
<div class="row center-align">
<div class="col s12">
<div id="map"></div>
</div>
</div>
<input type="hidden" name="north" id="north" />
<input type="hidden" name="south" id="south" />
<input type="hidden" name="east" id="east" />
<input type="hidden" name="west" id="west" />
<input type="hidden" name="lat" id="lat" />
<input type="hidden" name="lng" id="lng" />
<input type="hidden" name="locationInput" id="locationInput" />
<input type="hidden" name="locationInputData" id="locationInputData" />
<script>
let autocomplete;
let map;
let places;
let geocoder;
let marker =false; //Initialy no marker on map
function locateMe() {
if (navigator.geolocation) {
function onLocationSuccess(position) {
const coordinates =
position && position.coords ? position.coords : null;
if (coordinates) {
const longitude = coordinates.longitude || null;
const latitude = coordinates.latitude || null;
if (longitude && latitude && map) {
map.setCenter({ lat: latitude, lng: longitude });
map.setZoom(16);
}
}
}
navigator.geolocation.getCurrentPosition(onLocationSuccess);
}
}
function initMap() {
const BOSNIA_BOUNDS = {
north: 45.7,
south: 41.69,
west: 15.55,
east: 20.77
};
const SARAJEVO_COORDINATES = {
lat: 43.85,
lng: 18.41
};
const mapElement = document.getElementById("map");
const restrictMapPanningToBosniaOnly = {
latLngBounds: BOSNIA_BOUNDS,
strictBounds: true
};
const initialMapParams = {
center: SARAJEVO_COORDINATES,
zoom: 12,
restriction: restrictMapPanningToBosniaOnly,
mapTypeControl: false,
panControl: false,
zoomControl: true,
streetViewControl: false
};
map = new google.maps.Map(mapElement, initialMapParams);
const inputElement = document.getElementById("autocompleteInput");
const restrictAutocompleteResultsToBosniaOnly = { country: "ba" };
const initialAutocompleteParams = {
types: ["geocode"],
componentRestrictions: restrictAutocompleteResultsToBosniaOnly,
fields: ["geometry", "types", "address_components"]
};
autocomplete = new google.maps.places.Autocomplete(
inputElement,
initialAutocompleteParams
);
autocomplete.bindTo("bounds", map);
autocomplete.addListener("place_changed", onPlaceChanged);
pacSelectFirst(inputElement);
addLocateMeButton(map);
//Add event listener to position marker on map
google.maps.event.addListener(map, 'click', positionMarker);
}
function positionMarker(event) {
let clickedLocation = event.latLng;
if(marker === false){
marker = new google.maps.Marker({
position: clickedLocation,
map: map,
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function(event){
markerLocation();
});
} else{
marker.setPosition(clickedLocation);
}
}
function addLocateMeButton(map) {
var parent = document.createElement("div");
parent.className = "locate-me-container";
var a = document.createElement("a");
a.id = "locateMe";
a.className = "btn-floating";
var i = document.createElement("i");
i.innerText = "gps_fixed";
i.className = "material-icons right";
a.appendChild(i);
a.addEventListener("click", locateMe);
parent.appendChild(a);
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(parent);
}
function onPlaceChanged() {
const place = autocomplete.getPlace();
if (place.geometry) {
map.fitBounds(place.geometry.viewport);
map.setZoom(map.getZoom() + 1);
$("#locationInputData").val(JSON.stringify(place));
}
}
function pacSelectFirst(input) {
// store the original event binding function
const _addEventListener = input.addEventListener
? input.addEventListener
: input.attachEvent;
function addEventListenerWrapper(type, listener) {
// Simulate a 'down arrow' keypress on hitting 'return' when no pac suggestion is selected,
// and then trigger the original listener.
if (type == "keydown") {
const originalListener = listener;
listener = function(event) {
const suggestionSelected = $(".pac-item-selected").length > 0;
if (event.key == "Enter" && !suggestionSelected) {
const simulatedDownArrow = $.Event("keydown", {
keyCode: 40,
which: 40
});
originalListener.apply(input, [simulatedDownArrow]);
}
originalListener.apply(input, [event]);
};
}
_addEventListener.apply(input, [type, listener]);
}
input.addEventListener = addEventListenerWrapper;
input.attachEvent = addEventListenerWrapper;
}
</script>
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBuqZ6MWvDrquwc-TN6rPS6188D608Zj3Q&language=bs&libraries=places&callback=initMap"
async
defer
></script>
</div>
<div id="publishEnd" class="col s12">
<br>
<div class="row center-align">
<h3>Vaš oglas je spreman!</h3>
Unesite kontakt email i objavite oglas.
<br>
<div class="row center-align input-field col s3 m4 l5 form-group">
<input
id="email"
name="email"
type="email"
>
<div class="messages"></div>
<label for="email">Email</label>
</div>
</div>
<br>
<div class="row center-align">
<div class="col s6 push-s3">
<a id="submit" href="#" form="publishForm" class="welcome-center-button waves-effect waves-light btn">Objavi oglas</a>
</div>
</div>
<br>
</div>
</div>
</form>
<script>
$(document).ready(function(){
$('.tabs').tabs();
$("#submit").click( function () {
const mapBounds = map.getBounds();
const currentLocation = marker.getPosition();
$("#north").val(mapBounds.getNorthEast().lat());
$("#south").val(mapBounds.getSouthWest().lat());
$("#east").val(mapBounds.getNorthEast().lng());
$("#west").val(mapBounds.getSouthWest().lng());
$("#lat").val(currentLocation.lat());
$("#lng").val(currentLocation.lng());
$("#locationInput").val(
document.getElementById("autocompleteInput").value
);
const validateEmail = email => {
const regexEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
return regexEmail.test(String(email).toLowerCase());
}
const errors = validateEmail($("#email").val());
if (!errors) {
$("#publishForm").submit();
}
else {
console.log('Error!');
}
});
});
</script>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/13.1.5/nouislider.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/wnumb/1.1.0/wNumb.min.js"></script>
</body>
</html>