185 lines
5.2 KiB
JavaScript
185 lines
5.2 KiB
JavaScript
import ItemHTML from './ItemHTML.js';
|
|
import Locations from './Locations.js';
|
|
|
|
export default class Item {
|
|
|
|
static NAME_SELECTOR = '.item-link';
|
|
static DESCRIPTION_SELECTOR = '.item-description';
|
|
static PRICE_SELECTOR = '.item-price';
|
|
static GARAGE_SELECTOR = '.item-parking';
|
|
|
|
static ROOM_SELECTOR = '.item-detail-char .item-detail:nth-child(1)';
|
|
static METERS_SELECTOR = '.item-detail-char .item-detail:nth-child(2)';
|
|
static ADDITIONAL_INFORMATION_SELECTOR = '.item-detail-char .item-detail:nth-child(3)';
|
|
|
|
constructor(htmlNode) {
|
|
this._node = htmlNode;
|
|
|
|
this.name = this._extractName();
|
|
this.description = this._extractDescription();
|
|
this.locationName = this._extractLocationName();
|
|
|
|
this.price = this._extractPrice();
|
|
this.meters = this._extractMeters();
|
|
this.priceMeter = this._extractPriceMeter();
|
|
|
|
this.additionalInfo = this._extractAdditionalInfo();
|
|
|
|
this.hasGarage = this._extractGarage();
|
|
|
|
this.hasLift = this._extractLift();
|
|
this.isNoLift = this._extractIsNoLift();
|
|
|
|
this.isExterior = this._extractExterior();
|
|
this.isInterior = this._extractInterior();
|
|
}
|
|
|
|
get _data() {
|
|
return this._node.nextElementSibling;
|
|
}
|
|
|
|
async extractAsyncData() {
|
|
this.location = await this._extractLocation();
|
|
this.refreshData();
|
|
}
|
|
|
|
refreshData() {
|
|
this.removeData();
|
|
this.addData();
|
|
}
|
|
|
|
isDataRendered() {
|
|
const nextElement = this._data;
|
|
return nextElement.className
|
|
&& nextElement.className.includes(ItemHTML.CONTAINER_CLASS_NAME);
|
|
}
|
|
|
|
isProperPrice(price) {
|
|
return this.price <= price;
|
|
}
|
|
|
|
isProperPriceMeter(priceMeter) {
|
|
return this.priceMeter <= priceMeter;
|
|
}
|
|
|
|
removeData() {
|
|
if (!this.isDataRendered()) return;
|
|
this._data.remove();
|
|
}
|
|
|
|
addData() {
|
|
this._node.insertAdjacentHTML('afterend', ItemHTML.createInformation(this));
|
|
}
|
|
|
|
isFlat() {
|
|
return this._nameIncludes('Piso');
|
|
}
|
|
|
|
isHouse() {
|
|
return this._nameIncludes('Casa')
|
|
|| this._nameIncludes('Chalet')
|
|
|| this._nameIncludes('Finca');
|
|
}
|
|
|
|
// TODO: This may be included in isFlat.
|
|
isGround() {
|
|
return this._nameIncludes('Bajo');
|
|
}
|
|
|
|
_nameIncludes(name) {
|
|
return this.name.toLowerCase().includes(name.toLowerCase());
|
|
}
|
|
|
|
_descriptionIncludes(description) {
|
|
return this.description.toLowerCase().includes(description.toLowerCase());
|
|
}
|
|
|
|
_extractName() {
|
|
return this._node.querySelector(Item.NAME_SELECTOR).textContent;
|
|
}
|
|
|
|
_extractDescription() {
|
|
return this._node.querySelector(Item.DESCRIPTION_SELECTOR).textContent;
|
|
}
|
|
|
|
_extractLocationName() {
|
|
if (this.name.lastIndexOf(',') != -1) {
|
|
return this.name
|
|
.substring(this.name.lastIndexOf(','), this.name.length)
|
|
.replaceAll('\n', '').replaceAll('.', '')
|
|
.replaceAll(',', '').replaceAll(' ', '');
|
|
}
|
|
return this.name
|
|
.substring(this.name.lastIndexOf(' en ') + ' en '.length, this.name.length)
|
|
.replaceAll('\n', '').replaceAll('.', '')
|
|
.replaceAll(' ', '');
|
|
}
|
|
|
|
async _extractLocation() {
|
|
return Locations.get(this.locationName);
|
|
}
|
|
|
|
_extractPrice() {
|
|
const priceText = this._node.querySelector(Item.PRICE_SELECTOR).textContent;
|
|
return Number(priceText.replace('€', '').replaceAll('.', '').replaceAll(',', ''));
|
|
}
|
|
|
|
_extractMeters() {
|
|
let metersNode = this._node.querySelector(Item.METERS_SELECTOR);
|
|
|
|
|
|
let metersText;
|
|
if (!metersNode || !metersNode.textContent.includes('m²')) {
|
|
metersText = this._node.querySelector(Item.ROOM_SELECTOR).textContent;
|
|
} else {
|
|
metersText = metersNode.textContent;
|
|
}
|
|
|
|
return Number(metersText
|
|
.replace('m²', '')
|
|
.replaceAll('.', '')
|
|
);
|
|
}
|
|
|
|
_extractPriceMeter() {
|
|
return Math.round(this.price / this.meters);
|
|
}
|
|
|
|
_extractAdditionalInfo() {
|
|
let additionalInfo = this._node.querySelector(Item.ADDITIONAL_INFORMATION_SELECTOR);
|
|
if (!additionalInfo) {
|
|
additionalInfo = this._node.querySelector(Item.METERS_SELECTOR);
|
|
}
|
|
if (!additionalInfo) return null;
|
|
return additionalInfo.textContent;
|
|
}
|
|
|
|
_extractLift() {
|
|
if (!this.additionalInfo) return false;
|
|
return this.additionalInfo.includes('con ascensor');
|
|
}
|
|
|
|
_extractIsNoLift() {
|
|
if (!this.additionalInfo) return false;
|
|
return this.additionalInfo.includes('sin ascensor');
|
|
}
|
|
|
|
_extractExterior() {
|
|
const text = 'exterior';
|
|
if (this.additionalInfo && this.additionalInfo.includes(text)) return true;
|
|
if (this._descriptionIncludes(text)) return true;
|
|
return false;
|
|
}
|
|
|
|
_extractInterior() {
|
|
const text = 'interior';
|
|
if (this.additionalInfo && this.additionalInfo.includes(text)) return true;
|
|
if (this._descriptionIncludes(text)) return true;
|
|
return false;
|
|
}
|
|
|
|
_extractGarage() {
|
|
return this._node.querySelector(Item.GARAGE_SELECTOR) !== null;
|
|
}
|
|
|
|
} |