remove all logging noise

This commit is contained in:
Bilal Catic
2019-09-06 12:01:25 +02:00
parent 1d29f6c8ac
commit b0f9c2c47b
6 changed files with 753 additions and 752 deletions

View File

@@ -1,11 +1,8 @@
const { allMarketAlertsByRequest } = require("../helpers/db/dbHelper"); const { allMarketAlertsByRequest } = require("../helpers/db/dbHelper");
const getRealEstates = async (req, res) => { const getRealEstates = async (req, res) => {
console.log("Enter get realestates");
const request = req.params["request_id"]; const request = req.params["request_id"];
console.log(req.params["request_id"]);
const realEstates = await allMarketAlertsByRequest(request); const realEstates = await allMarketAlertsByRequest(request);
console.log(realEstates);
const title = "Ovo su nekretnine koje smo pronašli za vas"; const title = "Ovo su nekretnine koje smo pronašli za vas";
res.render("realEstates", { realEstates, title }); res.render("realEstates", { realEstates, title });

View File

@@ -198,8 +198,6 @@ const sendBulkEmail = async marketAlerts => {
ReplacementTemplateData: repData ReplacementTemplateData: repData
}); });
} }
console.log("AWS EMAIL : Bulk email replacement data:");
console.log(destinations);
var params = { var params = {
Destinations: destinations, Destinations: destinations,
@@ -214,8 +212,6 @@ const sendBulkEmail = async marketAlerts => {
.sendBulkTemplatedEmail(params) .sendBulkTemplatedEmail(params)
.promise(); .promise();
const awsResult = await sendPromise; const awsResult = await sendPromise;
console.log("AWS SES bulk email response");
console.log(awsResult);
} catch (e) { } catch (e) {
console.log("Could not send bulk email", e); console.log("Could not send bulk email", e);
} }

View File

@@ -1,375 +1,364 @@
const fetch = require('node-fetch'); const fetch = require("node-fetch");
const cheerio = require('cheerio'); const cheerio = require("cheerio");
const { allRERequest, findPointInsideBoundingBox } = require('../db/dbHelper'); const { allRERequest, findPointInsideBoundingBox } = require("../db/dbHelper");
const { getRealEstateTypeEnum } = require('../enums'); const { getRealEstateTypeEnum } = require("../enums");
const { getRegion, getMunicipality } = require('../codes') const { getRegion, getMunicipality } = require("../codes");
const Promise = require("bluebird"); const Promise = require("bluebird");
module.exports = class OlxCrawler { module.exports = class OlxCrawler {
//TODO figure best way to handle paging //TODO figure best way to handle paging
constructor(hrefs = []) { constructor(hrefs = []) {
this.hrefs = hrefs; this.hrefs = hrefs;
} }
async indexPages(urls) { async indexPages(urls) {
const indexers = []; const indexers = [];
urls.forEach(url => { urls.forEach(url => {
indexers.push(new Indexer(url)); indexers.push(new Indexer(url));
}); });
return Promise.map(indexers, function (indexer) { return Promise.map(indexers, function(indexer) {
return indexer.indexWithPagination(); return indexer.indexWithPagination();
}).then(async (results) => { }).then(async results => {
return results return results;
}) });
} }
async crawl() { async crawl() {
console.log("OLX CRAWLER: start crawl"); const filteredResults = [];
const realestateRequests = await allRERequest();
const urls = this.createRequestUrls(realestateRequests);
let results = await this.indexPages(
urls,
this.fromPage,
this.toPage,
this.maxResults
);
const flatResults = results.flat();
if (flatResults) {
for (const finalResult of flatResults) {
if (null !== finalResult) {
if (
finalResult.lat !== undefined &&
finalResult.lat !== null &&
finalResult.lat !== ""
) {
const pointInsideBoundingBox = await findPointInsideBoundingBox(
[finalResult.lng, finalResult.lat],
finalResult.email,
finalResult.uuid
);
const filteredResults = []; if (pointInsideBoundingBox[0].length !== 0) {
const realestateRequests = await allRERequest(); finalResult.hasLocation = true;
console.log("OLX CRAWLER: found " + realestateRequests.length + "subscribed RealEstateRequests"); filteredResults.push(finalResult);
const urls = this.createRequestUrls(realestateRequests); } else {
let results = await this.indexPages(urls, this.fromPage, this.toPage, this.maxResults); finalResult.hasLocation = false;
console.log("Final crawler results"); filteredResults.push(finalResult);
const flatResults = results.flat();
console.log(flatResults);
if (flatResults) {
console.log(flatResults.length);
for (const finalResult of flatResults) {
if (null !== finalResult) {
if (finalResult.lat !== undefined && finalResult.lat !== null && finalResult.lat !== "") {
const pointInsideBoundingBox = await findPointInsideBoundingBox([finalResult.lng, finalResult.lat], finalResult.email, finalResult.uuid);
if (pointInsideBoundingBox[0].length !== 0) {
finalResult.hasLocation = true
filteredResults.push(finalResult);
} else {
finalResult.hasLocation = false
filteredResults.push(finalResult);
}
}
}
} }
}
console.log("OLX CRAWLER: number of olx crawler results, after geo location filtering: " + filteredResults.length);
return filteredResults;
} }
return [] }
return filteredResults;
}
return [];
}
createRequestUrls(realestateRequests) {
const urls = [];
for (const request of realestateRequests) {
const realsestateType =
"kategorija=" +
getRealEstateTypeEnum(request.realEstateType).olxCategory;
const region = "kanton=" + getRegion(request.region).olxid;
const municipality =
"grad%5B%5D=" +
getMunicipality(request.region, request.municipality).olxid;
const sizeMin = "kvadrata_min=" + request.sizeMin;
const sizeMax = "kvadrata_max=" + request.sizeMax;
const priceMin = "od=" + request.priceMin;
const priceMax = "do=" + request.priceMax;
const olxUrl = {
url: `https://www.olx.ba/pretraga?${realsestateType}&id=2&stanje=0&vrstapregleda=tabela&sort_order=desc&${region}&${municipality}&${priceMin}&${priceMax}&vrsta=samoprodaja&${sizeMin}&${sizeMax}&stranica=`,
email: request.email,
uuid: request.uniqueId,
hrefs: this.hrefs
};
urls.push(olxUrl);
} }
createRequestUrls(realestateRequests) { return urls;
const urls = [] }
for (const request of realestateRequests) {
const realsestateType = "kategorija=" + getRealEstateTypeEnum(request.realEstateType).olxCategory;
const region = "kanton=" + getRegion(request.region).olxid;
const municipality = "grad%5B%5D=" + getMunicipality(request.region, request.municipality).olxid;
const sizeMin = "kvadrata_min=" + request.sizeMin;
const sizeMax = "kvadrata_max=" + request.sizeMax;
const priceMin = "od=" + request.priceMin;
const priceMax = "do=" + request.priceMax;
const olxUrl = {
url: `https://www.olx.ba/pretraga?${realsestateType}&id=2&stanje=0&vrstapregleda=tabela&sort_order=desc&${region}&${municipality}&${priceMin}&${priceMax}&vrsta=samoprodaja&${sizeMin}&${sizeMax}&stranica=`,
email: request.email,
uuid: request.uniqueId,
hrefs: this.hrefs
}
console.log(olxUrl.url);
urls.push(olxUrl);
}
return urls;
}
}; };
class Indexer { class Indexer {
/**
*
* @param {String|Array} olxUrl single or array of objects containing url email and uuid
* @param {Array} hrefResutls array contaning urls from crawler results
*/
/** constructor(olxUrl, hrefResutls) {
* this.olxUrl = olxUrl;
* @param {String|Array} olxUrl single or array of objects containing url email and uuid this.hrefResutls = hrefResutls;
* @param {Array} hrefResutls array contaning urls from crawler results }
*/
constructor(olxUrl, hrefResutls) { async indexWithPagination(pageNumber = 1) {
this.olxUrl = olxUrl; const pageNr = this.olxUrl.url.match(/\d+$/);
this.hrefResutls = hrefResutls; const indexers = this.prepareIndexers(pageNumber ? [pageNumber] : pageNr);
}
async indexWithPagination(pageNumber = 1) { try {
return Promise.map(indexers.indexers, function(indexer) {
return indexer.indexPage(pageNumber);
}).then(async results => {
let hasResults = false;
console.log("This is olxUrl:" + this.olxUrl.url); results.forEach(result => {
const pageNr = this.olxUrl.url.match(/\d+$/); if (!hasResults) {
const indexers = this.prepareIndexers(pageNumber ? [pageNumber] : pageNr); hasResults = result.hasResults;
}
});
try { if (!hasResults) {
const singlePageIndexers = this.prepareHrefIndexers(results);
if (singlePageIndexers.length === 0) {
return [];
}
return Promise.map(indexers.indexers, function (indexer) { return Promise.map(singlePageIndexers, function(indexer) {
return indexer.indexPage(pageNumber); return indexer.indexSingle();
}).then(async (results) => { }).then(async results => {
let hasResults = false; return results;
});
results.forEach(result => {
if (!hasResults) {
console.log("No results detected")
hasResults = result.hasResults
}
});
if (!hasResults) {
console.log("HAS NO MORE RESULTS, stop the paging, there are some results and they should contain only HREFS");
console.log(results.length);
const singlePageIndexers = this.prepareHrefIndexers(results);
if (singlePageIndexers.length === 0) {
console.log("THERE IS NOT EVEN SINGLE RESULT");
return []
}
return Promise.map(singlePageIndexers, function (indexer) {
return indexer.indexSingle();
}).then(async (results) => {
console.log("SinglePageMethod in HAS NO RESULTS, MarketAralms");
console.log(results.length);
return results;
});
} else {
console.log("HAS MORE RESULTS, should only contain HREFS");
console.log(results.length);
const newResults = await this.indexWithPagination(results[0].pageNumber + 5);
const singlePageIndexers = this.prepareHrefIndexers(results);
const newerResults = await Promise.map(singlePageIndexers, function (indexer) {
return indexer.indexSingle();
}).then(async (results) => {
console.log("SinglePageMethod HAS RESULTS, should contain MarketAlerts only");
console.log(results.length);
return results;
});
Array.prototype.push.apply(newResults, newerResults);
return newResults;
}
});
} catch (e) {
console.error("Error has accured", e);
}
}
prepareIndexers(pageNr) {
console.log("Entering prepareIndexers : page nr - " + pageNr);
const indexers = [];
let lastPageNumber;
if (pageNr) {
for (let index = Number(pageNr[0]); index <= Number(pageNr[0]) + 5; index++) {
lastPageNumber = index;
const newOlxUrl = {
url: this.olxUrl.url.replace(/\d+$/, "") + index,
email: this.olxUrl.email,
uuid: this.olxUrl.uuid,
hrefs: this.olxUrl.hrefs
}
indexers.push(new Indexer(newOlxUrl));
}
} else { } else {
for (let index = 1; index <= 5; index++) { const newResults = await this.indexWithPagination(
lastPageNumber = index; results[0].pageNumber + 5
const newOlxUrl = { );
url: this.olxUrl.url + index, const singlePageIndexers = this.prepareHrefIndexers(results);
email: this.olxUrl.email,
uuid: this.olxUrl.uuid, const newerResults = await Promise.map(singlePageIndexers, function(
hrefs: this.olxUrl.hrefs indexer
} ) {
indexers.push(new Indexer(newOlxUrl)); return indexer.indexSingle();
} }).then(async results => {
return results;
});
Array.prototype.push.apply(newResults, newerResults);
return newResults;
} }
return { });
indexers: indexers, } catch (e) {
lastPageNumber: lastPageNumber console.error("Error has accured", e);
}
}
prepareIndexers(pageNr) {
const indexers = [];
let lastPageNumber;
if (pageNr) {
for (
let index = Number(pageNr[0]);
index <= Number(pageNr[0]) + 5;
index++
) {
lastPageNumber = index;
const newOlxUrl = {
url: this.olxUrl.url.replace(/\d+$/, "") + index,
email: this.olxUrl.email,
uuid: this.olxUrl.uuid,
hrefs: this.olxUrl.hrefs
}; };
indexers.push(new Indexer(newOlxUrl));
}
} else {
for (let index = 1; index <= 5; index++) {
lastPageNumber = index;
const newOlxUrl = {
url: this.olxUrl.url + index,
email: this.olxUrl.email,
uuid: this.olxUrl.uuid,
hrefs: this.olxUrl.hrefs
};
indexers.push(new Indexer(newOlxUrl));
}
} }
return {
indexers: indexers,
lastPageNumber: lastPageNumber
};
}
prepareHrefIndexers(results) { prepareHrefIndexers(results) {
const indexers = [] const indexers = [];
if (!Array.isArray(results)) { if (!Array.isArray(results)) {
results.hrefs.forEach(href => { results.hrefs.forEach(href => {
const newOlxUrl = { const newOlxUrl = {
url: href, url: href,
email: results.olxUrl.email, email: results.olxUrl.email,
uuid: results.olxUrl.uuid, uuid: results.olxUrl.uuid,
hrefs: this.olxUrl.hrefs hrefs: this.olxUrl.hrefs
} };
indexers.push(new Indexer(newOlxUrl)); indexers.push(new Indexer(newOlxUrl));
}); });
} else {
} else { results.forEach(result => {
if (result !== null && result.hasOwnProperty("hrefs")) {
result.hrefs.forEach(href => {
results.forEach(result => { const newOlxUrl = {
url: href,
if (result !== null && result.hasOwnProperty('hrefs')) { email: result.olxUrl.email,
result.hrefs.forEach(href => { uuid: result.olxUrl.uuid,
const newOlxUrl = { hrefs: this.olxUrl.hrefs
url: href,
email: result.olxUrl.email,
uuid: result.olxUrl.uuid,
hrefs: this.olxUrl.hrefs
}
indexers.push(new Indexer(newOlxUrl));
})
}
});
}
return indexers;
}
async indexPage(pageNumber) {
console.log("Page number in index page, max page number :")
console.log(pageNumber);
try {
console.log("Indexing page: " + this.olxUrl.url);
const res = await fetch(this.olxUrl.url);
const body = await res.text();
const $ = cheerio.load(body);
const hrefs = [];
let hasResults = false
$('#rezultatipretrage').find('.listitem').each((i, elem) => {
hasResults = true
const href = $(elem).find('a').first().attr('href');
hrefs.push(href);
});
console.log("this is hrefs for olxUrl" + this.olxUrl.url);
console.log("NUMBER OF HREFS " + hrefs.length);
return {
hrefs: hrefs,
hasResults: hasResults,
pageNumber: pageNumber,
olxUrl: this.olxUrl
}
} catch (e) {
console.error('Exception caught:' + e);
}
}
async indexSingle() {
try {
console.log("Index single");
console.log(this.olxUrl.url);
if (this.olxUrl.url === undefined) {
return {}
}
// if (global.hrefs) {
if (this.olxUrl.hrefs[this.olxUrl.uuid] && this.olxUrl.hrefs[this.olxUrl.uuid].includes(this.olxUrl.url)) {
console.log("We found duplicate URL");
return null
}
// }
const res = await fetch(this.olxUrl.url);
const body = await res.text();
const $ = cheerio.load(body);
const title = $('#naslovartikla').text().trim();
const realEstateType = $('#artikal_glavni_div > div.artikal_lijevo > div:nth-child(3) > div > span:nth-child(3) > a > span').text();
const price = $('#pc > p:nth-child(2)').text();
const size = $('#dodatnapolja1 > div:nth-child(1) > div.df2').text();
const rooms = $('#dodatnapolja1 > div:nth-child(2) > div.df2').text();
const address = $('#dodatnapolja1 > div:nth-child(5) > div.df2').text();
const gardenSize = $('#dodatnapolja1 > div:nth-child(6) > div.df2').text();
const location = $('#artikal_glavni_div > div.artikal_lijevo > div.op.pop.mobile-lokacija').attr('data-content');
const time = $('time').attr('datetime');
const olxId = $('#artikal_glavni_div > div.artikal_lijevo > div:nth-child(15) > div:nth-child(4) > div.df2').text();
const descriptions = $('.artikal_detaljniopis_tekst');
const latLngRe = /LatLng\(([0-9]+\.[0-9]+)\,\s+([0-9]+\.[0-9]+)\)/g;
const imgRe = /href":("[^"]*")/g;
const matches = latLngRe.exec(body);
let lng = '',
lat = '';
const parsePrice = (price) => parseFloat(price.replace(".", ""))
if (matches && matches.length >= 3) {
lat = matches[1];
lng = matches[2];
}
const parsedPrice = parsePrice(price);
const locationArray = location.split(",");
const region = locationArray[0];
const municipality = locationArray[1];
const data = {
realEstateType: this.getCategoryId(realEstateType),
email: this.olxUrl.email,
uuid: this.olxUrl.uuid,
olxId: olxId,
url: this.olxUrl.url,
title,
price: isNaN(parsedPrice) ? 0 : parsedPrice,
size: parseFloat(size),
gardenSize: isNaN(parseFloat(gardenSize)) ? 0 : parseFloat(gardenSize),
address,
region,
municipality,
time,
shortDescription: descriptions.first().text(),
longDescription: descriptions.last().text(),
lat,
lng,
loc: [parseFloat(lat), parseFloat(lng)],
}; };
return data; indexers.push(new Indexer(newOlxUrl));
} catch (e) { });
console.error('Exception caught: ' + e.message);
} }
});
}
return indexers;
}
async indexPage(pageNumber) {
try {
const res = await fetch(this.olxUrl.url);
const body = await res.text();
const $ = cheerio.load(body);
const hrefs = [];
let hasResults = false;
$("#rezultatipretrage")
.find(".listitem")
.each((i, elem) => {
hasResults = true;
const href = $(elem)
.find("a")
.first()
.attr("href");
hrefs.push(href);
});
return {
hrefs: hrefs,
hasResults: hasResults,
pageNumber: pageNumber,
olxUrl: this.olxUrl
};
} catch (e) {
console.error("Exception caught:" + e);
}
}
async indexSingle() {
try {
if (this.olxUrl.url === undefined) {
return {};
}
// if (global.hrefs) {
if (
this.olxUrl.hrefs[this.olxUrl.uuid] &&
this.olxUrl.hrefs[this.olxUrl.uuid].includes(this.olxUrl.url)
) {
return null; return null;
}
// }
const res = await fetch(this.olxUrl.url);
const body = await res.text();
const $ = cheerio.load(body);
const title = $("#naslovartikla")
.text()
.trim();
const realEstateType = $(
"#artikal_glavni_div > div.artikal_lijevo > div:nth-child(3) > div > span:nth-child(3) > a > span"
).text();
const price = $("#pc > p:nth-child(2)").text();
const size = $("#dodatnapolja1 > div:nth-child(1) > div.df2").text();
const rooms = $("#dodatnapolja1 > div:nth-child(2) > div.df2").text();
const address = $("#dodatnapolja1 > div:nth-child(5) > div.df2").text();
const gardenSize = $(
"#dodatnapolja1 > div:nth-child(6) > div.df2"
).text();
const location = $(
"#artikal_glavni_div > div.artikal_lijevo > div.op.pop.mobile-lokacija"
).attr("data-content");
const time = $("time").attr("datetime");
const olxId = $(
"#artikal_glavni_div > div.artikal_lijevo > div:nth-child(15) > div:nth-child(4) > div.df2"
).text();
const descriptions = $(".artikal_detaljniopis_tekst");
const latLngRe = /LatLng\(([0-9]+\.[0-9]+)\,\s+([0-9]+\.[0-9]+)\)/g;
const imgRe = /href":("[^"]*")/g;
const matches = latLngRe.exec(body);
let lng = "",
lat = "";
const parsePrice = price => parseFloat(price.replace(".", ""));
if (matches && matches.length >= 3) {
lat = matches[1];
lng = matches[2];
}
const parsedPrice = parsePrice(price);
const locationArray = location.split(",");
const region = locationArray[0];
const municipality = locationArray[1];
const data = {
realEstateType: this.getCategoryId(realEstateType),
email: this.olxUrl.email,
uuid: this.olxUrl.uuid,
olxId: olxId,
url: this.olxUrl.url,
title,
price: isNaN(parsedPrice) ? 0 : parsedPrice,
size: parseFloat(size),
gardenSize: isNaN(parseFloat(gardenSize)) ? 0 : parseFloat(gardenSize),
address,
region,
municipality,
time,
shortDescription: descriptions.first().text(),
longDescription: descriptions.last().text(),
lat,
lng,
loc: [parseFloat(lat), parseFloat(lng)]
};
return data;
} catch (e) {
console.error("Exception caught: " + e.message);
} }
getCategoryId(category) { return null;
}
switch (category) { getCategoryId(category) {
case 'Stanovi': switch (category) {
return 'stan'; case "Stanovi":
return "stan";
case 'Vikendice': case "Vikendice":
return 'vikendica' return "vikendica";
case 'Kuće': case "Kuće":
return 'kuca'; return "kuca";
default: default:
return ''; return "";
}
} }
}
} }

View File

@@ -4,8 +4,6 @@ const db = require("../models/index");
const { allMarketAlerts } = require("../helpers/db/dbHelper"); const { allMarketAlerts } = require("../helpers/db/dbHelper");
async function crawlAll() { async function crawlAll() {
console.log("CRAWLER SERVICE: crawlAll");
try { try {
const marketAlertsFromDb = await allMarketAlerts(true); const marketAlertsFromDb = await allMarketAlerts(true);
const hrefs = []; const hrefs = [];
@@ -18,8 +16,6 @@ async function crawlAll() {
hrefs[marketAlert.request].push(marketAlert.url); hrefs[marketAlert.request].push(marketAlert.url);
}); });
console.log("CRAWLER SERVICE: GLOBAL HREFS");
console.log(hrefs);
const olxCrawler = new OlxCrawler(hrefs); const olxCrawler = new OlxCrawler(hrefs);
const crawlers = [olxCrawler]; const crawlers = [olxCrawler];
@@ -30,11 +26,6 @@ async function crawlAll() {
try { try {
const marketAlertsFromDb = await allMarketAlerts(false, true); const marketAlertsFromDb = await allMarketAlerts(false, true);
console.log(
"CRAWLER SERVICE: number of existing MarketAlerts from db: " +
marketAlertsFromDb.length
);
const marketAlerts = []; const marketAlerts = [];
const mergedResults = [].concat.apply([], results); const mergedResults = [].concat.apply([], results);
@@ -56,9 +47,6 @@ async function crawlAll() {
hasLocation: result.hasLocation hasLocation: result.hasLocation
}); });
} }
console.log(
"CRAWLER SERVICE: Number of crawler results: " + marketAlerts.length
);
try { try {
const filteredMarketAlerts = marketAlerts.filter( const filteredMarketAlerts = marketAlerts.filter(
@@ -67,10 +55,6 @@ async function crawlAll() {
return elem.url === url && elem.request === request; return elem.url === url && elem.request === request;
}) })
); );
console.log(
"CRAWLER SERVICE: Number of new crawler results: " +
filteredMarketAlerts.length
);
await db.MarketAlert.bulkCreate(filteredMarketAlerts); await db.MarketAlert.bulkCreate(filteredMarketAlerts);
} catch (e) { } catch (e) {

View File

@@ -8,15 +8,9 @@ const {
async function processNotifications() { async function processNotifications() {
try { try {
const marketAlerts = await allMarketAlerts(false, false); const marketAlerts = await allMarketAlerts(false, false);
console.log(marketAlerts.length);
await createMarketAlertEmailTemplate(); await createMarketAlertEmailTemplate();
if (marketAlerts.length > 0) { if (marketAlerts.length > 0) {
console.log(
"NOTIFICATION SERVICE: Number of new alerts: " + marketAlerts.length
);
await sendBulkEmail(marketAlerts); await sendBulkEmail(marketAlerts);
} else {
console.log("NOTIFICATION SERVICE: No new alerts");
} }
await db.MarketAlert.update( await db.MarketAlert.update(

View File

@@ -1,389 +1,430 @@
<!DOCTYPE> <!DOCTYPE >
<html> <html>
<head> <head>
<script src="https://code.jquery.com/jquery-3.4.0.js"></script> <script src="https://code.jquery.com/jquery-3.4.0.js"></script>
</head> </head>
<body> <body>
<select name="kanton" id="kanton" class="drop-select" onchange="pronadji_gradove()"> <select
<option value="">Iz svih lokacija</option> name="kanton"
id="kanton"
<option value="" disabled="">Federacija BiH</option> class="drop-select"
<option value="9">&nbsp;Sarajevo</option> onchange="pronadji_gradove()"
<option value="3">&nbsp;Tuzlanski</option> >
<option value="4">&nbsp;Zeničko-Dobojski</option> <option value="">Iz svih lokacija</option>
<option value="1">&nbsp;Unsko-Sanski</option>
<option value="2">&nbsp;Posavski</option> <option value="" disabled="">Federacija BiH</option>
<option value="5">&nbsp;Bosansko-podrinjski</option> <option value="9">&nbsp;Sarajevo</option>
<option value="6">&nbsp;Srednjobosanski</option> <option value="3">&nbsp;Tuzlanski</option>
<option value="7">&nbsp;Hercegovačko-Neretvanski</option> <option value="4">&nbsp;Zeničko-Dobojski</option>
<option value="8">&nbsp;Zapadno-Hercegovački</option> <option value="1">&nbsp;Unsko-Sanski</option>
<option value="10">&nbsp;Livanjski</option> <option value="2">&nbsp;Posavski</option>
<option value="5">&nbsp;Bosansko-podrinjski</option>
<option value="" disabled="">Republika Srpska</option> <option value="6">&nbsp;Srednjobosanski</option>
<option value="14">&nbsp;Banjalučka</option> <option value="7">&nbsp;Hercegovačko-Neretvanski</option>
<option value="15">&nbsp;Dobojsko-Bijeljinska</option> <option value="8">&nbsp;Zapadno-Hercegovački</option>
<option value="16">&nbsp;Sarajevsko-Zvornička</option> <option value="10">&nbsp;Livanjski</option>
<option value="17">&nbsp;Trebinjsko-Fočanska</option>
<option value="" disabled="">Republika Srpska</option>
<option value="12">Disktrikt Brčko</option> <option value="14">&nbsp;Banjalučka</option>
</select> <option value="15">&nbsp;Dobojsko-Bijeljinska</option>
<option value="16">&nbsp;Sarajevsko-Zvornička</option>
<option value="17">&nbsp;Trebinjsko-Fočanska</option>
<div style="height:40px;">
<option value="12">Disktrikt Brčko</option>
<span class="drop-container" style="width: 168px;"> </select>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<select name="unskosanski" id="unskosanski" class="drop-select" onchange="stavi_grad()"> <div style="height:40px;">
<option value="0">Mjesto</option> <span class="drop-container" style="width: 168px;">
<option value="75">Bihać</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="373">Bosanska Krupa</option> <select
<option value="504">Bosanski Petrovac</option> name="unskosanski"
<option value="374">Bužim</option> id="unskosanski"
<option value="857">Cazin</option> class="drop-select"
<option value="2362">Ključ</option> onchange="stavi_grad()"
<option value="3738">Sanski Most</option> >
<option value="5122">Velika Kladuša</option> <option value="0">Mjesto</option>
</select> <option value="75">Bihać</option>
</span> <option value="373">Bosanska Krupa</option>
</div> <option value="504">Bosanski Petrovac</option>
<option value="374">Bužim</option>
<option value="857">Cazin</option>
<div style="height:40px;"> <option value="2362">Ključ</option>
<option value="3738">Sanski Most</option>
<span class="drop-container" style="width: 168px;"> <option value="5122">Velika Kladuša</option>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> </select>
<select name="posavski" id="posavski" class="drop-select" onchange="stavi_grad()"> </span>
<option value="0">Mjesto</option> </div>
<option value="6144">Domaljevac</option>
<option value="424">Odžak</option> <div style="height:40px;">
<option value="3252">Orašje</option> <span class="drop-container" style="width: 168px;">
<option value="540">Šamac</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
</select> <select
</span> name="posavski"
</div> id="posavski"
class="drop-select"
onchange="stavi_grad()"
<div style="height:40px;"> >
<option value="0">Mjesto</option>
<span class="drop-container" style="width: 168px;"> <option value="6144">Domaljevac</option>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <option value="424">Odžak</option>
<select name="tuzlanski" id="tuzlanski" class="drop-select" onchange="stavi_grad()"> <option value="3252">Orašje</option>
<option value="0">Mjesto</option> <option value="540">Šamac</option>
<option value="2">Banovići</option> </select>
<option value="1090">Doboj-Istok</option> </span>
<option value="1854">Gradačac</option> </div>
<option value="1826">Gračanica</option>
<option value="2129">Kalesija</option> <div style="height:40px;">
<option value="2319">Kladanj</option> <span class="drop-container" style="width: 168px;">
<option value="2840">Lukavac</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="5699">Sapna</option> <select
<option value="4391">Srebrenik</option> name="tuzlanski"
<option value="5010">Teočak</option> id="tuzlanski"
<option value="4944">Tuzla</option> class="drop-select"
<option value="2801">Čelić</option> onchange="stavi_grad()"
<option value="5774">Živinice</option> >
</select> <option value="0">Mjesto</option>
</span> <option value="2">Banovići</option>
</div> <option value="1090">Doboj-Istok</option>
<option value="1854">Gradačac</option>
<option value="1826">Gračanica</option>
<div style="height:40px;"> <option value="2129">Kalesija</option>
<option value="2319">Kladanj</option>
<span class="drop-container" style="width: 168px;"> <option value="2840">Lukavac</option>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <option value="5699">Sapna</option>
<select name="zenickodobojski" id="zenickodobojski" class="drop-select" onchange="stavi_grad()"> <option value="4391">Srebrenik</option>
<option value="0">Mjesto</option> <option value="5010">Teočak</option>
<option value="704">Breza</option> <option value="4944">Tuzla</option>
<option value="1122">Doboj-Jug</option> <option value="2801">Čelić</option>
<option value="2022">Kakanj</option> <option value="5774">Živinice</option>
<option value="2941">Maglaj</option> </select>
<option value="1925">Olovo</option> </span>
<option value="4594">Tešanj</option> </div>
<option value="1087">Usora</option>
<option value="5037">Vareš</option> <div style="height:40px;">
<option value="5171">Visoko</option> <span class="drop-container" style="width: 168px;">
<option value="5548">Zavidovići</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="4571">Zenica</option> <select
<option value="2940">Žepče</option> name="zenickodobojski"
</select> id="zenickodobojski"
</span> class="drop-select"
</div> onchange="stavi_grad()"
>
<option value="0">Mjesto</option>
<div style="height:40px;"> <option value="704">Breza</option>
<option value="1122">Doboj-Jug</option>
<span class="drop-container" style="width: 168px;"> <option value="2022">Kakanj</option>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <option value="2941">Maglaj</option>
<select name="" id="bosanskopodrinjski" class="drop-select" onchange="stavi_grad()"> <option value="1925">Olovo</option>
<option value="0">Mjesto</option> <option value="4594">Tešanj</option>
<option value="1289">Foča</option> <option value="1087">Usora</option>
<option value="1588">Goražde</option> <option value="5037">Vareš</option>
<option value="3546">Pale</option> <option value="5171">Visoko</option>
</select> <option value="5548">Zavidovići</option>
</span> <option value="4571">Zenica</option>
</div> <option value="2940">Žepče</option>
</select>
</span>
<div style="height:40px;"> </div>
<span class="drop-container" style="width: 168px;"> <div style="height:40px;">
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <span class="drop-container" style="width: 168px;">
<select name="" id="srednjobosanski" class="drop-select" onchange="stavi_grad()"> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="0">Mjesto</option> <select
<option value="732">Bugojno</option> name=""
<option value="810">Busovača</option> id="bosanskopodrinjski"
<option value="4151">Dobretići</option> class="drop-select"
<option value="1160">Donji Vakuf</option> onchange="stavi_grad()"
<option value="1407">Fojnica</option> >
<option value="1775">Gornji Vakuf - Uskoplje</option> <option value="0">Mjesto</option>
<option value="1960">Jajce</option> <option value="1289">Foča</option>
<option value="2237">Kiseljak</option> <option value="1588">Goražde</option>
<option value="2608">Kreševo</option> <option value="3546">Pale</option>
<option value="3477">Novi Travnik</option> </select>
<option value="4678">Travnik</option> </span>
<option value="5422">Vitez</option> </div>
</select>
</span> <div style="height:40px;">
</div> <span class="drop-container" style="width: 168px;">
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<select
<div style="height:40px;"> name=""
id="srednjobosanski"
<span class="drop-container" style="width: 168px;"> class="drop-select"
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> onchange="stavi_grad()"
<select name="" id="hercegovackoneretvanski" class="drop-select" onchange="stavi_grad()"> >
<option value="0">Mjesto</option> <option value="0">Mjesto</option>
<option value="3017">Grad Mostar</option> <option value="732">Bugojno</option>
<option value="1930">Jablanica</option> <option value="810">Busovača</option>
<option value="2169">Konjic</option> <option value="4151">Dobretići</option>
<option value="3111">Neum</option> <option value="1160">Donji Vakuf</option>
<option value="3421">Prozor</option> <option value="1407">Fojnica</option>
<option value="4769">Ravno</option> <option value="1775">Gornji Vakuf - Uskoplje</option>
<option value="4439">Stolac</option> <option value="1960">Jajce</option>
<option value="947">Čapljina</option> <option value="2237">Kiseljak</option>
<option value="1009">Čitluk</option> <option value="2608">Kreševo</option>
</select> <option value="3477">Novi Travnik</option>
</span> <option value="4678">Travnik</option>
</div> <option value="5422">Vitez</option>
</select>
</span>
<div style="height:40px;"> </div>
<span class="drop-container" style="width: 168px;"> <div style="height:40px;">
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <span class="drop-container" style="width: 168px;">
<select name="" id="zapadnohercegovacki" class="drop-select" onchange="stavi_grad()"> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="0">Mjesto</option> <select
<option value="1892">Grude</option> name=""
<option value="2905">Ljubuški</option> id="hercegovackoneretvanski"
<option value="3268">Posušje</option> class="drop-select"
<option value="2708">Široki Brijeg</option> onchange="stavi_grad()"
</select> >
</span> <option value="0">Mjesto</option>
</div> <option value="3017">Grad Mostar</option>
<option value="1930">Jablanica</option>
<option value="2169">Konjic</option>
<div style="height:40px;"> <option value="3111">Neum</option>
<option value="3421">Prozor</option>
<span class="drop-container" style="width: 168px;"> <option value="4769">Ravno</option>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <option value="4439">Stolac</option>
<select name="" id="sarajevo" class="drop-select" onchange="stavi_grad()"> <option value="947">Čapljina</option>
<option value="0">Mjesto</option> <option value="1009">Čitluk</option>
<option value="3817">Hadžići</option> </select>
<option value="3879">Ilidža</option> </span>
<option value="3892">Ilijaš</option> </div>
<option value="3812">Sarajevo - Centar</option>
<option value="3969">Sarajevo-Novi Grad</option> <div style="height:40px;">
<option value="5896">Sarajevo-Novo Sarajevo</option> <span class="drop-container" style="width: 168px;">
<option value="4048">Sarajevo-Stari Grad</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="4063">Trnovo</option> <select
<option value="4126">Vogošća</option> name=""
</select> id="zapadnohercegovacki"
</span> class="drop-select"
</div> onchange="stavi_grad()"
>
<option value="0">Mjesto</option>
<div style="height:40px;"> <option value="1892">Grude</option>
<option value="2905">Ljubuški</option>
<span class="drop-container" style="width: 168px;"> <option value="3268">Posušje</option>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <option value="2708">Široki Brijeg</option>
<select name="" id="livanjski" class="drop-select" onchange="stavi_grad()"> </select>
<option value="0">Mjesto</option> </span>
<option value="560">Bosansko Grahovo</option> </div>
<option value="4640">Drvar</option>
<option value="1533">Glamoč</option> <div style="height:40px;">
<option value="2635">Kupres</option> <span class="drop-container" style="width: 168px;">
<option value="2741">Livno</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="1228">Tomislavgrad</option> <select
</select> name=""
</span> id="sarajevo"
</div> class="drop-select"
onchange="stavi_grad()"
>
<div style="height:40px;"> <option value="0">Mjesto</option>
<option value="3817">Hadžići</option>
<span class="drop-container" style="width: 168px;"> <option value="3879">Ilidža</option>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <option value="3892">Ilijaš</option>
<select name="" id="grad11" class="drop-select" onchange="stavi_grad()"> <option value="3812">Sarajevo - Centar</option>
<option value="0">Mjesto</option> <option value="3969">Sarajevo-Novi Grad</option>
<option value="645">distriktbrcko</option> <option value="5896">Sarajevo-Novo Sarajevo</option>
</select> <option value="4048">Sarajevo-Stari Grad</option>
</span> <option value="4063">Trnovo</option>
</div> <option value="4126">Vogošća</option>
</select>
</span>
<div style="height:40px;"> </div>
<span class="drop-container" style="width: 168px;"> <div style="height:40px;">
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <span class="drop-container" style="width: 168px;">
<select name="" id="banjalučka" class="drop-select" onchange="stavi_grad()"> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="0">Mjesto</option> <select
<option value="21">Banja Luka</option> name=""
<option value="305">Gradiška</option> id="livanjski"
<option value="4662">Istočni Drvar</option> class="drop-select"
<option value="1965">Jezero</option> onchange="stavi_grad()"
<option value="4147">Kneževo</option> >
<option value="6142">Kostajnica</option> <option value="0">Mjesto</option>
<option value="2574">Kotor Varoš</option> <option value="560">Bosansko Grahovo</option>
<option value="244">Kozarska Dubica</option> <option value="4640">Drvar</option>
<option value="382">Krupa na uni</option> <option value="1533">Glamoč</option>
<option value="2654">Kupres </option> <option value="2635">Kupres</option>
<option value="2671">Laktaši</option> <option value="2741">Livno</option>
<option value="3073">Mrkonjić Grad</option> <option value="1228">Tomislavgrad</option>
<option value="444">Novi Grad</option> </select>
<option value="3737">Oštra Luka</option> </span>
<option value="515">Petrovac</option> </div>
<option value="3287">Prijedor</option>
<option value="3358">Prnjavor</option> <div style="height:40px;">
<option value="2365">Ribnik</option> <span class="drop-container" style="width: 168px;">
<option value="4271">Srbac</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="979">Čelinac</option> <select name="" id="grad11" class="drop-select" onchange="stavi_grad()">
<option value="4509">Šipovo</option> <option value="0">Mjesto</option>
</select> <option value="645">distriktbrcko</option>
</span> </select>
</div> </span>
</div>
<div style="height:40px;"> <div style="height:40px;">
<span class="drop-container" style="width: 168px;">
<span class="drop-container" style="width: 168px;"> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> <select
<select name="" id="dobojskobijeljinska" class="drop-select" onchange="stavi_grad()"> name=""
<option value="0">Mjesto</option> id="banjalučka"
<option value="123">Bijeljina</option> class="drop-select"
<option value="421">Bosanski Brod</option> onchange="stavi_grad()"
<option value="1030">Derventa</option> >
<option value="1088">Doboj</option> <option value="0">Mjesto</option>
<option value="3254">Donji Žabar</option> <option value="21">Banja Luka</option>
<option value="2800">Lopare</option> <option value="305">Gradiška</option>
<option value="6029">Lukavac</option> <option value="4662">Istočni Drvar</option>
<option value="2996">Modriča</option> <option value="1965">Jezero</option>
<option value="1856">Pelagićevo</option> <option value="4147">Kneževo</option>
<option value="1827">Petrovo</option> <option value="6142">Kostajnica</option>
<option value="1148">Stanari</option> <option value="2574">Kotor Varoš</option>
<option value="4549">Teslić</option> <option value="244">Kozarska Dubica</option>
<option value="4636">Tešanj</option> <option value="382">Krupa na uni</option>
<option value="4692">Travnik</option> <option value="2654">Kupres </option>
<option value="4966">Tuzla</option> <option value="2671">Laktaši</option>
<option value="5009">Ugljevik</option> <option value="3073">Mrkonjić Grad</option>
<option value="3197">Vukosavlje</option> <option value="444">Novi Grad</option>
<option value="539">Šamac</option> <option value="3737">Oštra Luka</option>
</select> <option value="515">Petrovac</option>
</span> <option value="3287">Prijedor</option>
</div> <option value="3358">Prnjavor</option>
<option value="2365">Ribnik</option>
<option value="4271">Srbac</option>
<div style="height:40px;"> <option value="979">Čelinac</option>
<option value="4509">Šipovo</option>
<span class="drop-container" style="width: 168px;"> </select>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span> </span>
<select name="" id="sarajevskozvornicka" class="drop-select" onchange="stavi_grad()"> </div>
<option value="0">Mjesto</option>
<option value="595">Bratunac</option> <div style="height:40px;">
<option value="1904">Han Pijesak</option> <span class="drop-container" style="width: 168px;">
<option value="3947">Ilijaš</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="4049">Istočni Stari Grad</option> <select
<option value="3880">Kasindo</option> name=""
<option value="2325">Kladanj</option> id="dobojskobijeljinska"
<option value="3971">Lukavica</option> class="drop-select"
<option value="6143">Milići</option> onchange="stavi_grad()"
<option value="3221">Olovo</option> >
<option value="2128">Osmaci</option> <option value="0">Mjesto</option>
<option value="3978">Pale</option> <option value="123">Bijeljina</option>
<option value="3529">Rogatica</option> <option value="421">Bosanski Brod</option>
<option value="3648">Rudo</option> <option value="1030">Derventa</option>
<option value="6069">Sarajevo-Novi Grad</option> <option value="1088">Doboj</option>
<option value="4183">Sokolac</option> <option value="3254">Donji Žabar</option>
<option value="4310">Srebrenica</option> <option value="2800">Lopare</option>
<option value="4067">Trnovo</option> <option value="6029">Lukavac</option>
<option value="1593">Ustiprača</option> <option value="2996">Modriča</option>
<option value="5259">Višegrad</option> <option value="1856">Pelagićevo</option>
<option value="5456">Vlasenica</option> <option value="1827">Petrovo</option>
<option value="5684">Zvornik</option> <option value="1148">Stanari</option>
<option value="4475">Šekovi</option> <option value="4549">Tesl</option>
<option value="1906">Žepa</option> <option value="4636">Tešanj</option>
</select> <option value="4692">Travnik</option>
</span> <option value="4966">Tuzla</option>
</div> <option value="5009">Ugljevik</option>
<option value="3197">Vukosavlje</option>
<option value="539">Šamac</option>
<div style="height:40px;"> </select>
</span>
<span class="drop-container" style="width: 168px;"> </div>
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<select name="" id="trebinjskofocanska" class="drop-select" onchange="stavi_grad()"> <div style="height:40px;">
<option value="0">Mjesto</option> <span class="drop-container" style="width: 168px;">
<option value="4441">Berkovići</option> <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
<option value="183">Bileća</option> <select
<option value="1287">Foča</option> name=""
<option value="1462">Gacko</option> id="sarajevskozvornicka"
<option value="3038">Istočni Mostar</option> class="drop-select"
<option value="2164">Kalinovik</option> onchange="stavi_grad()"
<option value="2884">Ljubinje</option> >
<option value="3138">Nevesinje</option> <option value="0">Mjesto</option>
<option value="4766">Trebinje</option> <option value="595">Bratunac</option>
<option value="911">Čajniče</option> <option value="1904">Han Pijesak</option>
</select> <option value="3947">Ilijaš</option>
</span> <option value="4049">Istočni Stari Grad</option>
</div> <option value="3880">Kasindo</option>
<option value="2325">Kladanj</option>
<script> <option value="3971">Lukavica</option>
<option value="6143">Milići</option>
const stavi_grad = () => {}; <option value="3221">Olovo</option>
const gradovi = [ <option value="2128">Osmaci</option>
{"ime":" Sarajevo","id":"sarajevo"}, <option value="3978">Pale</option>
{"ime":" Unsko-sanski","id":"unskosanski"}, <option value="3529">Rogatica</option>
{"ime":" Posavski","id":"posavski"}, <option value="3648">Rudo</option>
{"ime":" Tuzlanski","id":"tuzlanski"}, <option value="6069">Sarajevo-Novi Grad</option>
{"ime":" Zeničko-dobojski","id":"zenickodobojski"}, <option value="4183">Sokolac</option>
{"ime":" Bosansko-podrinjski","id":"bosanskopodrinjski"}, <option value="4310">Srebrenica</option>
{"ime":" Srednjobosanski","id":"srednjobosanski"}, <option value="4067">Trnovo</option>
{"ime":" Hercegovačko-neretvanski","id":"hercegovackoneretvanski"}, <option value="1593">Ustiprača</option>
{"ime":" Zapadno-hercegovački","id":"zapadnohercegovacki"}, <option value="5259">Višegrad</option>
{"ime":" Livanjski","id":"livanjski"}, <option value="5456">Vlasenica</option>
{"ime":" Banjalučka","id":"banjalučka"}, <option value="5684">Zvornik</option>
{"ime":" Dobojsko-Bijeljinska","id":"dobojskobijeljinska"}, <option value="4475">Šekovići</option>
{"ime":" Sarajevsko-Zvornička","id":"sarajevskozvornicka"}, <option value="1906">Žepa</option>
{"ime":" Trebinjsko-Fočanska","id":"trebinjskofocanska"}, </select>
{"ime":"Distrikt Brčko","id":"distriktbrcko"}, </span>
]; </div>
for (let grad of gradovi) { <div style="height:40px;">
const mjesta = []; <span class="drop-container" style="width: 168px;">
$('#' + grad.id).children().each( function() { <span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
const mjesto = $(this).text(); <select
mjesta.push( { name=""
ime: mjesto, id="trebinjskofocanska"
id: mjesto.toLowerCase().replace(/[^a-z]/g,''), class="drop-select"
olxid: $(this).val() onchange="stavi_grad()"
}); >
}); <option value="0">Mjesto</option>
grad.mjesta = mjesta; <option value="4441">Berkovići</option>
} <option value="183">Bileća</option>
<option value="1287">Foča</option>
console.log(JSON.stringify(gradovi)); <option value="1462">Gacko</option>
<option value="3038">Istočni Mostar</option>
</script> <option value="2164">Kalinovik</option>
<option value="2884">Ljubinje</option>
</body> <option value="3138">Nevesinje</option>
</html> <option value="4766">Trebinje</option>
<option value="911">Čajniče</option>
</select>
</span>
</div>
<script>
const stavi_grad = () => {};
const gradovi = [
{ ime: " Sarajevo", id: "sarajevo" },
{ ime: " Unsko-sanski", id: "unskosanski" },
{ ime: " Posavski", id: "posavski" },
{ ime: " Tuzlanski", id: "tuzlanski" },
{ ime: " Zeničko-dobojski", id: "zenickodobojski" },
{ ime: " Bosansko-podrinjski", id: "bosanskopodrinjski" },
{ ime: " Srednjobosanski", id: "srednjobosanski" },
{ ime: " Hercegovačko-neretvanski", id: "hercegovackoneretvanski" },
{ ime: " Zapadno-hercegovački", id: "zapadnohercegovacki" },
{ ime: " Livanjski", id: "livanjski" },
{ ime: " Banjalučka", id: "banjalučka" },
{ ime: " Dobojsko-Bijeljinska", id: "dobojskobijeljinska" },
{ ime: " Sarajevsko-Zvornička", id: "sarajevskozvornicka" },
{ ime: " Trebinjsko-Fočanska", id: "trebinjskofocanska" },
{ ime: "Distrikt Brčko", id: "distriktbrcko" }
];
for (let grad of gradovi) {
const mjesta = [];
$("#" + grad.id)
.children()
.each(function() {
const mjesto = $(this).text();
mjesta.push({
ime: mjesto,
id: mjesto.toLowerCase().replace(/[^a-z]/g, ""),
olxid: $(this).val()
});
});
grad.mjesta = mjesta;
}
</script>
</body>
</html>