Last active
March 28, 2022 13:15
-
-
Save jricardo27/f215c111ec7bbf18f60830cb9dd3d5f2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Flight Centre Extra Filter | |
// @author Ricardo Perez | |
// @namespace jricardo27/FlightCentreExtraFilter | |
// @version 0.1 | |
// @description Hide unwanted flights from search | |
// @include *://*.flightcentre.com.au/* | |
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js | |
// @grant none | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
const FILTER_BY_MAXIMUM_STOPS = "FILTER_BY_MAXIMUM_STOPS"; | |
const FILTER_BY_MAXIMUM_TIME = "FILTER_BY_MAXIMUM_TIME"; | |
/* ------------------------------------------------------- */ | |
/* Values to configure */ | |
const MAXIMUM_STOPS = 2; | |
const MAXIMUM_HOURS_GO = 50; // hours, leave blank if not want to filter | |
const MAXIMUM_HOURS_BACK = 60; // hours, leave blank if not want to filter | |
// List of airport abbreviatures to include, leave blank if not want to filter. | |
const OUTBOUND_AIRPORTS = ["MEL", "BOG", "AKL", "SCL"]; | |
const INBOUND_AIRPORTS = ["MEL", "BOG", "LAX"]; // "JFK", "EWR", "SFO" | |
const FILTER_BY = []; | |
/* ------------------------------------------------------- */ | |
function customObserver(target, callback, config) { | |
this.target = target || document; | |
this.config = config || {childList: true, characterData: true, attributes: true, subtree: true}; | |
const that = this; | |
this.ob = new MutationObserver(function (mut, obsSelf) { | |
callback(that, mut, obsSelf); | |
}); | |
} | |
customObserver.prototype = { | |
connect: function () { | |
this.ob.observe(this.target, this.config); | |
}, | |
disconnect: function () { | |
this.ob.disconnect(); | |
} | |
}; | |
/* ------------------------------------------------------- */ | |
const FLIGHT_RESULTS = "#flightResults" | |
const FLIGHT_BOX = ".test-combinedTrip"; | |
const OUTBOUND_BOX = ".test-outboundJourney"; | |
const INBOUND_BOX = ".test-inboundJourney"; | |
const STOPS_BOX = ".jss414"; | |
const DURATION_BOX = ".test-duration"; | |
const AIRPORT_BOX = ".test-journeyStopAirport" | |
const applyFilter = () => { | |
let messageShown = false; | |
let outboundExcludedAiports = new Set(); | |
let inboundExcludedAiports = new Set(); | |
let aiportAbbrv = null; | |
$(FLIGHT_BOX).each((index, rawElem) => { | |
const boxElem = $(rawElem); | |
const outboundBox = $(boxElem.find(OUTBOUND_BOX)[0]); | |
const inboundBox = $(boxElem.find(INBOUND_BOX)[0]); | |
if (FILTER_BY.includes(FILTER_BY_MAXIMUM_STOPS)) { | |
if (!messageShown) { | |
console.log(`Filtering by number of stops. Hiding any over ${MAXIMUM_STOPS} stops.`); | |
messageShown = true | |
} | |
hideFlightsOverMaximumStops(boxElem); | |
} | |
if(FILTER_BY.includes(FILTER_BY_MAXIMUM_TIME)) { | |
if (!messageShown) { | |
console.log(`Filtering by duration. Hiding any over ${MAXIMUM_HOURS_GO}h going and ${MAXIMUM_HOURS_BACK}h back.`); | |
messageShown = true | |
} | |
hideFlightsOverMaximumTime(boxElem); | |
} | |
aiportAbbrv = hideExcludedAiports(boxElem, outboundBox, OUTBOUND_AIRPORTS); | |
if (aiportAbbrv) { | |
outboundExcludedAiports.add(aiportAbbrv); | |
} | |
aiportAbbrv = hideExcludedAiports(boxElem, inboundBox, INBOUND_AIRPORTS); | |
if (aiportAbbrv) { | |
inboundExcludedAiports.add(aiportAbbrv); | |
} | |
}); | |
if (outboundExcludedAiports.size > 0) { | |
console.log(`Hiding flights stoping in outbound aiports: ${Array.from(outboundExcludedAiports)}`); | |
} | |
if (inboundExcludedAiports.size > 0) { | |
console.log(`Hiding flights stoping in inbound aiports: ${Array.from(inboundExcludedAiports)}`); | |
} | |
}; | |
const hideBox = (boxElem) => { | |
// boxElem.hide(); | |
boxElem.css("background-color", "crimson"); | |
} | |
const hideFlightsOverMaximumStops = (boxElem) => { | |
boxElem.find(STOPS_BOX).each(function () { | |
const stopElem = $(this); | |
const stops = parseInt(stopElem.text()); | |
if (stops > MAXIMUM_STOPS) { | |
hideBox(boxElem); | |
} | |
}); | |
}; | |
const getHours = (elem) => { | |
return parseInt(elem.text().split("h")[0]); | |
}; | |
const hideFlightsOverMaximumTime = (boxElem) => { | |
const durationElems = boxElem.find(DURATION_BOX); | |
const hours1 = getHours($(durationElems[0])); | |
const hours2 = getHours($(durationElems[1])); | |
if (MAXIMUM_HOURS_GO && hours1 > MAXIMUM_HOURS_GO) { | |
hideBox(boxElem); | |
} | |
if (MAXIMUM_HOURS_BACK && hours2 > MAXIMUM_HOURS_BACK) { | |
hideBox(boxElem); | |
} | |
}; | |
const hideExcludedAiports = (boxElem, flightBox, includedAirports) => { | |
let airportAbbrv = null; | |
if(includedAirports.length > 0) { | |
flightBox.find(AIRPORT_BOX).each(function () { | |
const airportElem = $(this); | |
airportAbbrv = airportElem.text(); | |
if (!includedAirports.includes(airportAbbrv)) { | |
hideBox(boxElem); | |
return false; // Break loop. | |
} | |
airportAbbrv = null; | |
}); | |
} | |
return airportAbbrv; | |
} | |
/** | |
Userscript will run from here. | |
**/ | |
document.onreadystatechange = () => { | |
// Wait until fligths are loaded. | |
const observer = new customObserver($(FLIGHT_RESULTS)[0], (obs, mutations) => { | |
console.log("Flights loaded"); | |
if ($(".test-combinedResultsScreen")) { | |
console.log("Executing extra filter"); | |
applyFilter(); | |
} | |
}, {childList: true, subtree: true}); | |
observer.connect(); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment