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; } }