class Search {
constructor() {
this.searchDebounced = _.debounce((query) => {
if (query.length < 3)
return;
this.socket.emit('get_hints', {
id: this.updateRequestId(),
query
});
}, 150);
let field = document.getElementById('queryInput');
let btn = document.getElementById('querySubmit');
this.autoComplete = new Autocomplete(field, {
data: [],
maximumItems: 10,
onInput: (value) => {
this.searchDebounced(value);
},
onSelectItem: ({label}) => {
// console.log('selected:', label)
},
highlightClass: 'text-danger'
});
btn.addEventListener('click', this.onSubmit);
field.addEventListener('keydown', this.onInputKeyDown);
this.btn = btn;
this.field = field;
this.socket = io();
this.socket.on('hints', this.onHints);
this.socket.on('offers', this.onOffers)
}
updateRequestId() {
this.requestId = requestId();
return this.requestId;
}
onInputKeyDown = (e) => {
if (e.keyCode === 10 || e.keyCode === 13)
this.onSubmit();
}
onSubmit = (e) => {
if (this.isLocked())
return;
this.lockButton('Загрузка...');
gMaps.removeAllPoints();
this.socket.emit('get_offers', {
id: this.updateRequestId(),
query: this.field.value
});
}
onHints = (data) => {
if (data.id !== this.requestId)
return;
this.unlockButton();
if (data.error) {
console.warn(data.error);
return;
}
this.autoComplete.setData(data.response.map(item => {
return {label: item, value: ''};
}));
this.autoComplete.renderIfNeeded();
}
onOffers = (data) => {
if (data.id !== this.requestId)
return;
if (data.end) {
this.unlockButton();
return;
} else {
this.lockButton(data.pages > 1 ? `${data.page} из ${data.pages}` : null);
}
for (let offer of data.offers)
gMaps.addOffer(offer);
}
isLocked() {
return this.btn.classList.contains('disabled');
}
lockButton(text) {
if (text !== null)
this.btn.innerText = text;
this.btn.classList.add('disabled');
}
unlockButton() {
this.btn.classList.remove('disabled');
this.btn.innerText = 'Поиск';
}
}
class Maps {
constructor() {
/**
* @type {ymaps.Map}
*/
this.map = null;
ymaps.ready(this.onInit);
this.places = {};
}
onInit = () => {
this.map = new ymaps.Map("mapContainer", {
center: [59.94, 30.32],
zoom: 11
});
this.map.controls.remove('searchControl');
}
addPoint({geo, offersRef, hint, pharmacyName, pharmacyAddress, pharmacyPhone}) {
let mark = new ymaps.Placemark(geo, {
hintContent: hint,
}, {
preset: 'islands#dotIcon',
openEmptyBalloon: true,
iconColor: '#3caa3c'
});
mark.events.add('balloonopen', e => {
let lines = offersRef.map(offer => {
return `${offer.name} (${offer.price} руб.)`
});
let html = `${pharmacyName}
`;
html += `${pharmacyAddress}
`;
html += `тел: ${pharmacyPhone}
`;
html += lines.join('\n');
mark.properties.set('balloonContent', html);
});
this.map.geoObjects.add(mark);
return mark;
}
removeAllPoints() {
this.map.geoObjects.removeAll();
}
addOffer(offer) {
// console.log('[addOffer]', offer);
let hash = offer.pharmacy.hash;
if (hash in this.places)
this.places[hash].offers.push(offer);
else {
this.places[hash] = {
offers: [offer],
};
this.places[hash].mark = this.addPoint({
geo: offer.pharmacy.geo,
hint: offer.pharmacy.name,
pharmacyName: offer.pharmacy.name,
pharmacyAddress: offer.pharmacy.address,
pharmacyPhone: offer.pharmacy.phone,
offersRef: this.places[hash].offers
});
}
}
}
function requestId() {
return _.random(1, 99999999);
}
let gMaps, gSearch;
window.addEventListener('DOMContentLoaded', function() {
gSearch = new Search();
gMaps = new Maps();
// document.getElementById('test').addEventListener('click', () => {
// gMaps.addTestPoint();
// });
});