From c63c870059dd5f7f15daf8736cffff42bdfa89d7 Mon Sep 17 00:00:00 2001 From: Jorge Bolois Guerrero Date: Mon, 4 Jul 2022 18:37:25 +0200 Subject: [PATCH] Adding WIP version app code from GreasyFork. --- app.js | 338 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 app.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..735e113 --- /dev/null +++ b/app.js @@ -0,0 +1,338 @@ +// ==UserScript== +// @name Idealista Enhancer +// @description Just some information for idealista.com +// @version 0.1.0 +// @author Midefos +// @namespace https://github.com/Midefos +// @match https://www.idealista.com/* +// @require https://code.jquery.com/jquery-3.6.0.slim.min.js +// @license MIT +// ==/UserScript== + +/* jshint esversion: 6 */ +this.$ = this.jQuery = jQuery.noConflict(true); + +// Idealista selectors. +const ITEM_SELECTOR = 'article.item'; +const NAME_SELECTOR = '.item-link'; +const PRICE_SELECTOR = '.item-price'; +const ROOM_SELECTOR = '.item-detail-char .item-detail:nth-child(1)'; +const METERS_SELECTOR = '.item-detail-char .item-detail:nth-child(2)'; +const ADDITIONAL_INFORMATION_SELECTOR = '.item-detail-char .item-detail:nth-child(3)'; + +// Own selectors. +const CONFIG_CLASS = 'midefos-idealista-config' + +const DEFAULT_CONFIG = { + enabled: true, + percentages: true, + garage: false, + exterior: true, + lever: true, + 'max-price': 120_000, + 'max-price-per-meter': 1_500 +} + + +const STYLES = ` + .midefos-idealista-container { + display: flex; + align-items: center; + justify-content: space-around; + + width: 100%; + height: 55px; + margin-top: 5px; + + background-color: white; + box-shadow: 0 3px 6px rgba(225, 245, 110, 0.16), 0 3px 6px rgba(225, 245, 110, 0.23); + + } + .midefos-idealista-menu { + display: flex; + align-items: center; + justify-content: space-around; + + width: 100%; + height: 40px; + + background-color: white; + box-shadow: 0 3px 6px rgba(225, 245, 110, 0.16), 0 3px 6px rgba(225, 245, 110, 0.23); + } + .${CONFIG_CLASS} { + display: none; + position: fixed; + z-index: 3; + + background-color: rgba(225, 245, 110, 0.90); + width: 95%; + height: 95%; + top: 2.5%; + left: 2.5%; + + padding: 2rem; + } + + .success { + color: darkgreen; + } + .warning { + color: darkorange; + } + .error { + color: darkred; + } +`; + +let currentConfig; + +function init() { + currentConfig = getConfig() + addStyles(); + + createMenu(); + createInformation(); +} + +function getConfig() { + const storageConfig = localStorage.getItem('midefos-idealista'); + if (!storageConfig) return DEFAULT_CONFIG; + + return JSON.parse(storageConfig); +} + +function setConfig(config) { + localStorage.setItem('midefos-idealista', JSON.stringify(config)); + currentConfig = config; +} + +function createMenu() { + if (window.location.href.includes('mapa-google')) return; + + + $('body').on('click', '#reload-midefos-idealista', () => { + createInformation(); + }); + + $('body').on('click', '.config-open', () => { + $(`.${CONFIG_CLASS}`).toggle(); + }); + + $('body').on('click', '.config-save', () => { + const $configNode = $(`.${CONFIG_CLASS}`); + + const configNode = $configNode[0]; + const newConfig = { + enabled: configNode.querySelector('#enabled').checked, + percentages: configNode.querySelector('#percentages').checked, + garage: configNode.querySelector('#garage').checked, + exterior: configNode.querySelector('#exterior').checked, + lever: configNode.querySelector('#lever').checked, + 'max-price': configNode.querySelector('#max-price').value, + 'max-price-per-meter': configNode.querySelector('#max-price-per-meter').value + } + setConfig(newConfig); + + createInformation(); + $configNode.toggle(); + }); + + document.querySelector('#main-header').innerHTML += createConfigHTML(); + + + const mainContent = document.querySelector('#main-content'); + mainContent.innerHTML = createMenuHTML() + mainContent.innerHTML; +} + +function createInformation() { + const items = document.querySelectorAll(ITEM_SELECTOR); + for (const item of items) { + const currentInformation = item.querySelector('.midefos-idealista-container'); + if (currentInformation) currentInformation.remove(); + item.innerHTML += createItemInformationHTML(item); + } +} + +function createConfigHTML() { + return ` +
+

Midefos Idealista

+ +

Configuración global:

+ + +

Busqueda:

+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + +
` +} + +function createMenuHTML() { + return ` +
+ + +
`; +} + + +function createItemInformationHTML(item) { + + return ` +
+ ${createPercentagePriceHTML(item)} + ${createPriceHTML(item)} + ${createPriceMeterHTML(item)} + ${createLeverHTML(item)} + ${createInteriorHTML(item)} +
` +} + +function findPrice(item) { + const priceText = item.querySelector(PRICE_SELECTOR).textContent; + return Number(priceText.replace('€', '').replace('.', '').replace(',', '')); +} + +function findMeters(item) { + let metersText = item.querySelector(METERS_SELECTOR).textContent; + if (!metersText.includes('m²')) metersText = item.querySelector(ROOM_SELECTOR).textContent; + return Number(metersText.replace('m²', '')); +} + +function findPriceMeter(item) { + const meters = findMeters(item); + const price = findPrice(item); + return Math.round(price / meters); +} + + +function createPercentagePriceHTML(item) { + if (!currentConfig.percentages) return ``; + + const price = findPrice(item); + + const twentyPercent = Math.round(price * 20 / 100); + const thirtyPercent = Math.round(price * 30 / 100); + return ` + + 20%: ${twentyPercent}€
+ 30%: ${thirtyPercent}€ +
`; +} + + +function createPriceHTML(item) { + const price = findPrice(item); + + const desiredPrice = currentConfig['max-price']; + const desiredTwentyFivePercentMore = Math.round(desiredPrice * 1.25); + + if (price <= desiredPrice) { + return ` Precio`; + } else if (price <= desiredTwentyFivePercentMore) { + return ` Precio`; + } + return `X Precio`; +} + + +function createPriceMeterHTML(item) { + const priceMeter = findPriceMeter(item); + + const desiredPricePerMeter = currentConfig['max-price-per-meter']; + const desiredTwentyFivePercentMore = Math.round(desiredPricePerMeter * 1.25); + + if (priceMeter <= desiredPricePerMeter) { + return `m²: ${priceMeter}€`; + } else if (priceMeter <= desiredTwentyFivePercentMore) { + return `m²: ${priceMeter}€`; + } + return `m²: ${priceMeter}€`; +} + +function createLeverHTML(item) { + if (!currentConfig.lever) return ``; + + const additionalInfo = item.querySelector(ADDITIONAL_INFORMATION_SELECTOR); + if (!additionalInfo) { + if (!isFlat(item)) return ``; + return `? Ascensor` + } + + const leverText = additionalInfo.textContent; + const hasLever = leverText.includes('con ascensor'); + if (hasLever) { + return ` Ascensor` + } + return `X Ascensor`; +} + +function createInteriorHTML(item) { + if (!currentConfig.exterior) return ``; + + const additionalInfo = item.querySelector(ADDITIONAL_INFORMATION_SELECTOR); + if (!additionalInfo) { + if (!isFlat(item)) return ``; + return `? Exterior` + } + + const interiorText = additionalInfo.textContent; + const hasLever = interiorText.includes('exterior'); + if (hasLever) { + return ` Exterior` + } + return `X Exterior`; +} + +function isFlat(item) { + return item.querySelector(NAME_SELECTOR) + .textContent.includes('Piso'); +} + +init(); + +function addStyles() { + const style = document.createElement('style'); + style.textContent = STYLES; + document.head.appendChild(style); +} \ No newline at end of file