Adding border depending on the item state and preferences.
Some cleaning and refactor.
This commit is contained in:
parent
6de714b445
commit
88f50657c2
@ -5,13 +5,12 @@ import banner from 'browserify-banner';
|
||||
const STATIC_BANNER = "// ==UserScript==\n" +
|
||||
"// @name Idealista Enhancer\n" +
|
||||
"// @description Just some information for idealista.com\n" +
|
||||
"// @version 0.1.0\n" +
|
||||
"// @version 0.2.0\n" +
|
||||
"// @author Midefos\n" +
|
||||
"// @namespace https://github.com/Midefos\n" +
|
||||
"// @match https://www.idealista.com/*\n" +
|
||||
"// @license MIT\n" +
|
||||
"// ==/UserScript==\n" +
|
||||
"/* jshint esversion: 6 */\n\n";
|
||||
"// ==/UserScript==\n\n";
|
||||
|
||||
browserify("./app.js")
|
||||
.transform("babelify", { presets: ["@babel/preset-env"] })
|
||||
|
17
src/CheckboxHTML.js
Normal file
17
src/CheckboxHTML.js
Normal file
@ -0,0 +1,17 @@
|
||||
import Log from "./Log.js";
|
||||
|
||||
export default class CheckboxHTML {
|
||||
|
||||
static create(id, value) {
|
||||
const inputElement = document.createElement('input');
|
||||
if (value) {
|
||||
Log.debug(`Creating checkbox ${id}, value: ${value}`)
|
||||
inputElement.setAttribute('checked', true);
|
||||
}
|
||||
|
||||
inputElement.id = id;
|
||||
inputElement.type = 'checkbox';
|
||||
return inputElement.outerHTML;
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import ButtonClass from "./ButtonClass.js";
|
||||
import CheckboxHTML from "./CheckboxHTML.js";
|
||||
import Preferences from "./Preferences.js";
|
||||
|
||||
export default class ConfigurationHTML {
|
||||
@ -25,32 +26,32 @@ export default class ConfigurationHTML {
|
||||
|
||||
<h3>Configuración global:</h3>
|
||||
<label>
|
||||
<input type='checkbox' id='enabled' checked='${Preferences.get('enabled')}'>
|
||||
${CheckboxHTML.create('enabled', Preferences.get('enabled'))}
|
||||
<span>Habilitado</span>
|
||||
</label>
|
||||
|
||||
<h3>Busqueda:</h3>
|
||||
|
||||
<label>
|
||||
<input type='checkbox' id='percentages' checked='${Preferences.get('percentages')}'>
|
||||
${CheckboxHTML.create('percentages', Preferences.get('percentages'))}
|
||||
<span>Porcentajes</span>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
<input type='checkbox' id='garage' checked='${Preferences.get('garage')}'>
|
||||
${CheckboxHTML.create('garage', Preferences.get('garage'))}
|
||||
<span>Garaje</span>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
<input type='checkbox' id='exterior' checked='${Preferences.get('exterior')}'>
|
||||
${CheckboxHTML.create('exterior', Preferences.get('exterior'))}
|
||||
<span>Exterior</span>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
<input type='checkbox' id='lift' checked='${Preferences.get('lift')}'>
|
||||
${CheckboxHTML.create('lift', Preferences.get('lift'))}
|
||||
<span>Ascensor</span>
|
||||
</label>
|
||||
<br>
|
||||
@ -71,7 +72,7 @@ export default class ConfigurationHTML {
|
||||
<button class='${ButtonClass.IDEALISTA_BUTTON_CLASS} ${this.SAVE_CONFIG_CLASS_NAME}'>Guardar</button>
|
||||
<button class='${ButtonClass.IDEALISTA_BUTTON_CLASS} ${this.OPEN_CONFIG_CLASS_NAME}'>Cerrar</button>
|
||||
</div>
|
||||
</div>`
|
||||
</div>`
|
||||
}
|
||||
|
||||
}
|
36
src/Item.js
36
src/Item.js
@ -4,6 +4,7 @@ export default class Item {
|
||||
|
||||
static NAME_SELECTOR = '.item-link';
|
||||
static PRICE_SELECTOR = '.item-price';
|
||||
|
||||
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)';
|
||||
@ -19,6 +20,7 @@ export default class Item {
|
||||
this.additionalInfo = this._extractAdditionalInfo();
|
||||
this.hasLift = this._extractLift();
|
||||
this.isExterior = this._extractExterior();
|
||||
this.isInterior = this._extractInterior();
|
||||
}
|
||||
|
||||
get _data() {
|
||||
@ -31,30 +33,43 @@ export default class Item {
|
||||
}
|
||||
|
||||
isDataRendered() {
|
||||
const nextElement = this._data;
|
||||
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.outerHTML += ItemHTML.createInformation(this);
|
||||
this._node.insertAdjacentHTML('afterend', ItemHTML.createInformation(this));
|
||||
}
|
||||
|
||||
isFlat() {
|
||||
return this.name.includes('Piso');
|
||||
return this._nameIncludes('Piso');
|
||||
}
|
||||
|
||||
isHouse() {
|
||||
return this.name.includes('Casa');
|
||||
return this._nameIncludes('Casa')
|
||||
|| this._nameIncludes('Chalet');
|
||||
}
|
||||
|
||||
isGround() {
|
||||
return this.name.includes('Bajo');
|
||||
return this._nameIncludes('Bajo');
|
||||
}
|
||||
|
||||
_nameIncludes(name) {
|
||||
return this.name.toLowerCase().includes(name.toLowerCase());
|
||||
}
|
||||
|
||||
_extractName() {
|
||||
@ -79,8 +94,10 @@ export default class Item {
|
||||
}
|
||||
|
||||
_extractAdditionalInfo() {
|
||||
const additionalInfo = this._node.querySelector(Item.ADDITIONAL_INFORMATION_SELECTOR);
|
||||
if (!additionalInfo) return null;
|
||||
let additionalInfo = this._node.querySelector(Item.ADDITIONAL_INFORMATION_SELECTOR);
|
||||
if (!additionalInfo) {
|
||||
additionalInfo = this._node.querySelector(Item.METERS_SELECTOR);
|
||||
}
|
||||
return additionalInfo.textContent;
|
||||
}
|
||||
|
||||
@ -94,4 +111,9 @@ export default class Item {
|
||||
return this.additionalInfo.includes('exterior');
|
||||
}
|
||||
|
||||
_extractInterior() {
|
||||
if (!this.additionalInfo) return false;
|
||||
return this.additionalInfo.includes('interior');
|
||||
}
|
||||
|
||||
}
|
135
src/ItemHTML.js
135
src/ItemHTML.js
@ -2,115 +2,168 @@ import Preferences from "./Preferences.js";
|
||||
|
||||
export default class ItemHTML {
|
||||
|
||||
static SUCCESS_CLASS_NAME = 'success';
|
||||
static WARNING_CLASS_NAME = 'warning';
|
||||
static ERROR_CLASS_NAME = 'error';
|
||||
|
||||
static CONTAINER_CLASS_NAME = 'midefos-idealista-container';
|
||||
static get CONTAINER_SELECTOR() {
|
||||
return `.${this.CONTAINER_CLASS_NAME}`;
|
||||
}
|
||||
|
||||
static INFORMATION_CLASS_NAME = 'information'
|
||||
static get INFORMATION_SELECTOR() {
|
||||
return `.${this.INFORMATION_CLASS_NAME}`;
|
||||
}
|
||||
|
||||
static ITEM_STATE_CLASS_NAME(item) {
|
||||
const desiredPrice = Preferences.get('max-price');
|
||||
if (desiredPrice && !item.isProperPrice(desiredPrice)) {
|
||||
return this.ERROR_CLASS_NAME;
|
||||
}
|
||||
|
||||
const desiredPricePerMeter = Preferences.get('max-price-per-meter');
|
||||
if (desiredPricePerMeter && !item.isProperPriceMeter(desiredPricePerMeter)) {
|
||||
return this.ERROR_CLASS_NAME;
|
||||
}
|
||||
|
||||
if (this._shouldCheckLift(item) && !item.hasLift) {
|
||||
return this.ERROR_CLASS_NAME;
|
||||
}
|
||||
|
||||
if (this._shouldCheckExterior(item) && !item.isExterior) {
|
||||
return this.ERROR_CLASS_NAME;
|
||||
}
|
||||
return this.SUCCESS_CLASS_NAME;
|
||||
}
|
||||
|
||||
static createInformation(item) {
|
||||
return `
|
||||
<div class='${this.CONTAINER_CLASS_NAME}'>
|
||||
<div class='${this.CONTAINER_CLASS_NAME} ${this.ITEM_STATE_CLASS_NAME(item)}'>
|
||||
${this._createPercentagePriceHTML(item)}
|
||||
${this._createPriceHTML(item)}
|
||||
${this._createPriceMeterHTML(item)}
|
||||
${this._createLiftHTML(item)}
|
||||
${this._createInteriorHTML(item)}
|
||||
${this._createExteriorHTML(item)}
|
||||
</div>`
|
||||
}
|
||||
|
||||
|
||||
static _createPercentagePriceHTML(item) {
|
||||
if (!Preferences.get('percentages')) return ``;
|
||||
|
||||
|
||||
const twentyPercent = Math.round(item.price * 20 / 100);
|
||||
const thirtyPercent = Math.round(item.price * 30 / 100);
|
||||
const fiftyPercent = Math.round(item.price * 50 / 100);
|
||||
return `
|
||||
<div>
|
||||
<span><strong>20%:</strong> ${twentyPercent}€</span>
|
||||
<span><strong>30%:</strong> ${thirtyPercent}€</span>
|
||||
<span><strong>50%:</strong> ${fiftyPercent}€</span>
|
||||
<div class='${this.INFORMATION_CLASS_NAME}'>
|
||||
${this._createIndividual('20%', twentyPercent)}
|
||||
${this._createIndividual('30%', thirtyPercent)}
|
||||
${this._createIndividual('50%', fiftyPercent)}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static _createPriceHTML(item) {
|
||||
const desiredPrice = Preferences.get('max-price');
|
||||
if (!desiredPrice) return ``;
|
||||
|
||||
const desiredTwentyFivePercentMore = Math.round(desiredPrice * 1.25);
|
||||
|
||||
if (item.price <= desiredPrice) {
|
||||
|
||||
if (item.isProperPrice(desiredPrice)) {
|
||||
return this._createSuccess('Precio');
|
||||
} else if (item.price <= desiredTwentyFivePercentMore) {
|
||||
} else if (item.isProperPrice(desiredTwentyFivePercentMore)) {
|
||||
return this._createWarning('Precio');
|
||||
}
|
||||
return this._createError('Precio');
|
||||
}
|
||||
|
||||
|
||||
|
||||
static _createPriceMeterHTML(item) {
|
||||
const desiredPricePerMeter = Preferences.get('max-price-per-meter');
|
||||
if (!desiredPricePerMeter) return `<span><strong>m²:</strong> ${item.priceMeter}€</span>`;
|
||||
if (!desiredPricePerMeter) return this._createIndividual('m²', item.priceMeter);
|
||||
|
||||
const desiredTwentyFivePercentMore = Math.round(desiredPricePerMeter * 1.25);
|
||||
|
||||
|
||||
if (item.priceMeter <= desiredPricePerMeter) {
|
||||
return `<span class='success'><strong>m²:</strong> ${item.priceMeter}€</span>`;
|
||||
return this._createTextSuccess('m²', item.priceMeter)
|
||||
} else if (item.priceMeter <= desiredTwentyFivePercentMore) {
|
||||
return `<span class='warning'><strong>m²:</strong> ${item.priceMeter}€</span>`;
|
||||
return this._createTextWarning('m²', item.priceMeter)
|
||||
}
|
||||
return `<span class='error'><strong>m²:</strong> ${item.priceMeter}€</span>`;
|
||||
return this._createTextError('m²', item.priceMeter)
|
||||
}
|
||||
|
||||
|
||||
static _createLiftHTML(item) {
|
||||
if (!Preferences.get('lift')) return ``;
|
||||
|
||||
if (!this._shouldCheckLift(item)) {
|
||||
return ``;
|
||||
}
|
||||
|
||||
if (!item.additionalInfo) {
|
||||
if (item.isFlat()) return ``;
|
||||
return this._createMissing('Ascensor');
|
||||
}
|
||||
|
||||
|
||||
if (item.hasLift) {
|
||||
return this._createSuccess('Ascensor',);
|
||||
return this._createSuccess('Ascensor');
|
||||
}
|
||||
return this._createError('Ascensor');
|
||||
}
|
||||
|
||||
static _createInteriorHTML(item) {
|
||||
if (!Preferences.get('exterior')) return ``;
|
||||
|
||||
if (!item.additionalInfo) {
|
||||
if (!item.isFlat()) return ``;
|
||||
return this._createMissing('Exterior');
|
||||
|
||||
static _shouldCheckLift(item) {
|
||||
return Preferences.get('lift')
|
||||
&& !item.isHouse()
|
||||
&& !item.isGround();
|
||||
}
|
||||
|
||||
static _createExteriorHTML(item) {
|
||||
if (!this._shouldCheckExterior(item)) {
|
||||
return ``;
|
||||
}
|
||||
|
||||
|
||||
if (item.isExterior) {
|
||||
return this._createSuccess('Exterior');
|
||||
}
|
||||
return this._createError('Exterior');
|
||||
|
||||
if (item.isInterior) {
|
||||
return this._createError('Exterior');
|
||||
}
|
||||
return this._createMissing('Exterior');
|
||||
}
|
||||
|
||||
static _shouldCheckExterior(item) {
|
||||
return Preferences.get('exterior')
|
||||
&& !item.isHouse();
|
||||
}
|
||||
|
||||
static _createSuccess(infoText) {
|
||||
return this.__createIndividual('✓', infoText, 'success');
|
||||
return this._createTextSuccess('✔️', infoText);
|
||||
}
|
||||
|
||||
static _createTextSuccess(strongText, infoText) {
|
||||
return this._createIndividual(strongText, infoText, this.SUCCESS_CLASS_NAME);
|
||||
}
|
||||
|
||||
static _createWarning(infoText) {
|
||||
return this.__createIndividual('✓', infoText, 'warning');
|
||||
return this._createTextWarning('⚠️', infoText);
|
||||
}
|
||||
|
||||
static _createMissing(infoText) {
|
||||
return this.__createIndividual('?', infoText, 'warning');
|
||||
return this._createTextWarning('?', infoText);
|
||||
}
|
||||
|
||||
static _createTextWarning(strongText, infoText) {
|
||||
return this._createIndividual(strongText, infoText, this.WARNING_CLASS_NAME);
|
||||
}
|
||||
|
||||
static _createError(infoText) {
|
||||
return this.__createIndividual('✓', infoText, 'error');
|
||||
return this._createTextError('🚫', infoText);
|
||||
}
|
||||
|
||||
static _createTextError(strongText, infoText) {
|
||||
return this._createIndividual(strongText, infoText, this.ERROR_CLASS_NAME);
|
||||
}
|
||||
|
||||
static _createNeutral(infoText) {
|
||||
return this.__createIndividual('ⓘ', infoText)
|
||||
return this._createIndividual('ⓘ', infoText)
|
||||
}
|
||||
|
||||
static __createIndividual(strongText, infoText, className = '') {
|
||||
static _createIndividual(strongText, infoText, className = '') {
|
||||
return `<span class='${className}'><strong>${strongText}</strong> ${infoText}</span>`;
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,34 @@ export default class Styles {
|
||||
|
||||
background-color: white;
|
||||
box-shadow: 0 3px 6px rgba(225, 245, 110, 0.16), 0 3px 6px rgba(225, 245, 110, 0.23);
|
||||
|
||||
border: 3px solid transparent;
|
||||
}
|
||||
|
||||
.${ItemHTML.INFORMATION_CLASS_NAME} {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.${ItemHTML.SUCCESS_CLASS_NAME} {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.${ItemHTML.CONTAINER_CLASS_NAME}.${ItemHTML.SUCCESS_CLASS_NAME} {
|
||||
border-color: rgba(61, 217, 61, 0.3);
|
||||
}
|
||||
|
||||
.${ItemHTML.WARNING_CLASS_NAME} {
|
||||
color: darkorange;
|
||||
}
|
||||
|
||||
.${ItemHTML.ERROR_CLASS_NAME} {
|
||||
color: darkred;
|
||||
}
|
||||
|
||||
.${ItemHTML.CONTAINER_CLASS_NAME}.${ItemHTML.ERROR_CLASS_NAME} {
|
||||
border-color: rgba(217, 61, 61, 0.3);
|
||||
}
|
||||
|
||||
.${MenuHTML.CONTAINER_CLASS_NAME} {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -46,16 +72,6 @@ export default class Styles {
|
||||
border: 5px solid rgb(225, 245, 110);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: darkgreen;
|
||||
}
|
||||
.warning {
|
||||
color: darkorange;
|
||||
}
|
||||
.error {
|
||||
color: darkred;
|
||||
}
|
||||
`;
|
||||
|
||||
static add(style = null) {
|
||||
|
Loading…
Reference in New Issue
Block a user