|
// ==UserScript== |
|
// @name Mediamarkt Handy Tarife Calculator |
|
// @namespace https://gist.github.com/muhdiboy |
|
// @version 1.1 |
|
// @downloadURL https://gist.github.com/muhdiboy/27568d2f55f3e2b4b622668a07287e1b/raw/mediamarkt-handy-tarife-calculator.user.js |
|
// @updateURL https://gist.github.com/muhdiboy/27568d2f55f3e2b4b622668a07287e1b/raw/mediamarkt-handy-tarife-calculator.user.js |
|
// @description Calculate and display the total sum and average monthly cost of subscription prices on the webpage, taking into account all bonuses and the option to sell the device |
|
// @author muhdiboy |
|
// @match https://tarife.mediamarkt.de/smartphones/*/* |
|
// @grant none |
|
// ==/UserScript== |
|
|
|
(function() { |
|
// Set default values |
|
const months = 24; |
|
let subtractValue = 0; |
|
|
|
// Add the buttons to the page |
|
addLoadButton(); |
|
addCalculateButton(); |
|
addReorderButton(); |
|
addContainerDiv(); |
|
|
|
// Function to append the sum and new monthly to the value of priceElement |
|
function appendSumToPrice() { |
|
|
|
// Find the elements that represent subscription options |
|
const subscriptionOptions = document.querySelectorAll('[class*="OfferList__StyledCol"]'); |
|
|
|
// Create an array to store the option elements and sums |
|
const optionSums = []; |
|
|
|
// Iterate over the subscription options and calculate the sum per option |
|
subscriptionOptions.forEach((option, index) => { |
|
// Remove any previously appended sum |
|
const existingSumElement = option.querySelector('.sum'); |
|
if (existingSumElement) { |
|
existingSumElement.remove(); |
|
} |
|
|
|
// Remove any previously appended monthly cost |
|
const existingmonthlyCostElement = option.querySelector('.monthly'); |
|
if (existingmonthlyCostElement) { |
|
existingmonthlyCostElement.remove(); |
|
} |
|
|
|
// Extract the price information from each option |
|
const priceElement = option.querySelector('[class*="Price__StyledPrice"]'); |
|
const pricePart1 = parseFloat(priceElement.textContent.trim()); |
|
const pricePart2Element = priceElement.querySelector('sup'); |
|
const pricePart2 = parseFloat(pricePart2Element.textContent.trim()); |
|
|
|
// Calculate the sum for each subscription option |
|
let sum = pricePart1 + (pricePart2 / 100); |
|
|
|
sum *= months; |
|
|
|
// Extract single-time payments |
|
const singlePaymentElements = option.querySelectorAll('[class*="PriceDisplay__Span"]'); |
|
|
|
// Iterate over the single-time payments and add them to the sum |
|
singlePaymentElements.forEach((singlePaymentElement) => { |
|
const singlePaymentText = singlePaymentElement.textContent.trim(); |
|
// Exclude elements containing a specific text |
|
if (singlePaymentText.includes('Monatlicher Grundpreis')) return; // Skip this element |
|
const singlePayment = parseFloat(singlePaymentText.replace(/[^\d.]/g, '')); |
|
|
|
sum += singlePayment; |
|
}); |
|
|
|
// Extract the change bonus |
|
const changeBonusElements = option.querySelectorAll('[class*="Bulletlist__List-sc"]'); |
|
|
|
// Iterate over the change bonus and cut them from the sum |
|
changeBonusElements.forEach((changeBonusElement) => { |
|
const changeBonusText = changeBonusElement.textContent.trim(); |
|
// Exclude elements containing a specific text |
|
if (!changeBonusText.includes('Wechselbonus')) return; // Skip this element |
|
const changeBonus = parseFloat(changeBonusText.match(/\d+€/)); |
|
sum -= changeBonus; |
|
}); |
|
|
|
// Extract the delivery costs |
|
const deliveryPriceElement = document.querySelector('span[data-codeception="deliveryPrice"] > span[data-codeception="price"]'); |
|
const deliveryPriceParts = deliveryPriceElement.textContent.trim().split('\n'); |
|
const deliveryPrice = parseFloat(deliveryPriceParts[0].match(/[\d,]/g).join('').replace(',', '.')); |
|
|
|
// Subtract the delivery costs |
|
sum += deliveryPrice; |
|
|
|
// Store the calculated sum in a separate attribute |
|
priceElement.setAttribute('data-sum', sum); |
|
|
|
// Create a new element to display the sum |
|
const sumElement = document.createElement('span'); |
|
sumElement.classList.add('sum'); |
|
sumElement.style.cssText = priceElementStyles; |
|
sumElement.textContent = `Σ: ${sum.toFixed(2)}`; |
|
|
|
// Append the sum element after the price element |
|
priceElement.insertAdjacentElement('afterend', sumElement); |
|
|
|
// Calculate monthly cost |
|
const monthlyCost = sum / months; |
|
|
|
// Create a container for the monthly cost |
|
const monthlyCostElement = document.createElement('span'); |
|
monthlyCostElement.classList.add('monthly'); |
|
monthlyCostElement.style.cssText = priceElementStyles; |
|
monthlyCostElement.textContent = `Ø: ${monthlyCost.toFixed(2)}`; |
|
|
|
// Append the monthly cost container after the sum element |
|
sumElement.insertAdjacentElement('afterend', monthlyCostElement); |
|
|
|
// Modify the font size of the price |
|
pricePart2Element.style.fontSize = '18px'; |
|
priceElement.style.fontSize = '24px'; |
|
}); |
|
} |
|
|
|
// Function to reorder the based on the value of sum |
|
function reorderOptions() { |
|
appendSumToPrice(); // Call appendSumToPrice to calculate the sums |
|
|
|
const optionSums = Array.from(document.querySelectorAll('[class*="OfferList__StyledCol"]')).map(option => { |
|
const priceElement = option.querySelector('[class*="Price__StyledPrice"]'); |
|
const sum = parseFloat(priceElement.getAttribute('data-sum')); |
|
return { option, sum }; |
|
}); |
|
|
|
// Sort the optionSums array based on the sum in ascending order |
|
optionSums.sort((a, b) => a.sum - b.sum); |
|
|
|
// Create a temporary container to hold the sorted option elements |
|
const tempContainer = document.createElement('div'); |
|
|
|
// Append the option elements to the temporary container in the new order |
|
optionSums.forEach(({ option }) => { |
|
tempContainer.appendChild(option); |
|
}); |
|
|
|
// Clear the existing options container |
|
const optionsContainer = document.querySelectorAll('[class*="FilterSection__StyledRow"] > [class*="Col-sc"] > div > [class*="Row-sc"]'); |
|
optionsContainer.innerHTML = ''; |
|
|
|
// Append the sorted option elements back to the options container |
|
optionsContainer.forEach((container) => { |
|
optionSums.forEach(({ option }) => { |
|
container.appendChild(option); |
|
}); |
|
}); |
|
} |
|
|
|
// Function to subtract the entered value from sum and monthly |
|
function subtractFromSum() { |
|
appendSumToPrice(); // Call appendSumToPrice to calculate the sums |
|
|
|
const subtractInput = document.querySelector('input[type="number"]'); |
|
subtractValue = parseFloat(subtractInput.value); |
|
const priceElements = document.querySelectorAll('[class*="OfferList__StyledCol"]'); |
|
|
|
// Iterate over the price elements and subtract the specified value from the sums |
|
priceElements.forEach(function (priceElement) { |
|
const sumElement = priceElement.querySelector('.sum'); |
|
const monthlyCostElement = priceElement.querySelector('.monthly'); |
|
|
|
if (sumElement) { |
|
const sum = parseFloat(sumElement.textContent.replace(/[^\d.]/g, '')); |
|
const newSum = sum - subtractValue; |
|
sumElement.textContent = `Σ: ${newSum.toFixed(2)}`; |
|
|
|
const monthlyCost = parseFloat(monthlyCostElement.textContent.replace(/[^\d.]/g, '')); |
|
const newMonthlyCost = newSum / months; |
|
monthlyCostElement.textContent = `Ø: ${newMonthlyCost.toFixed(2)}`; |
|
} |
|
}); |
|
} |
|
|
|
// Function to load all options |
|
function clickLoadButton() { |
|
const loadButton = document.querySelector('[class*="OfferList__StyledButton"]'); |
|
if (loadButton) { |
|
loadButton.click(); |
|
setTimeout(clickLoadButton, 100); |
|
} |
|
} |
|
|
|
// Buttons, containers and styles |
|
function createSubtractContainer() { |
|
const subtractContainer = document.createElement('div'); |
|
subtractContainer.style.display = 'flex'; |
|
subtractContainer.style.alignItems = 'center'; |
|
|
|
const subtractLabel = document.createElement('label'); |
|
subtractLabel.textContent = 'Selling Price: '; |
|
subtractContainer.appendChild(subtractLabel); |
|
|
|
const inputContainer = document.createElement('div'); |
|
inputContainer.style.position = 'relative'; |
|
|
|
const subtractInput = document.createElement('input'); |
|
subtractInput.type = 'number'; |
|
subtractInput.min = '0'; |
|
subtractInput.style.width = '70px'; |
|
subtractInput.style.marginLeft = '10px'; |
|
subtractInput.style.border = 'groove'; |
|
subtractInput.addEventListener('input', function(event) { |
|
subtractValue = parseFloat(event.target.value); |
|
}); |
|
subtractContainer.appendChild(subtractInput); |
|
|
|
const subtractButton = document.createElement('button'); |
|
subtractButton.textContent = 'Subtract'; |
|
subtractButton.style.position = 'fixed'; |
|
subtractButton.style.top = '100%'; |
|
subtractButton.style.right = '10px'; |
|
subtractButton.addEventListener('click', subtractFromSum); |
|
subtractContainer.appendChild(subtractButton); |
|
|
|
subtractContainer.appendChild(inputContainer); |
|
|
|
return subtractContainer; |
|
} |
|
|
|
function addLoadButton() { |
|
const loadButton = document.createElement('button'); |
|
loadButton.textContent = 'Load all'; |
|
loadButton.style.position = 'fixed'; |
|
loadButton.style.top = '50%'; |
|
loadButton.style.right = '20px'; |
|
loadButton.style.transform = 'translateY(-50%)'; |
|
loadButton.addEventListener('click', clickLoadButton); |
|
document.body.appendChild(loadButton); |
|
} |
|
|
|
function addCalculateButton() { |
|
const calculateButton = document.createElement('button'); |
|
calculateButton.textContent = 'Calculate'; |
|
calculateButton.style.position = 'fixed'; |
|
calculateButton.style.top = '53%'; |
|
calculateButton.style.right = '20px'; |
|
calculateButton.style.transform = 'translateY(-50%)'; |
|
calculateButton.addEventListener('click', appendSumToPrice); |
|
document.body.appendChild(calculateButton); |
|
} |
|
|
|
function addReorderButton() { |
|
const reorderButton = document.createElement('button'); |
|
reorderButton.textContent = 'Order € > €€'; |
|
reorderButton.style.position = 'fixed'; |
|
reorderButton.style.top = '56%'; |
|
reorderButton.style.right = '20px'; |
|
reorderButton.style.transform = 'translateY(-50%)'; |
|
reorderButton.addEventListener('click', reorderOptions); |
|
document.body.appendChild(reorderButton); |
|
} |
|
|
|
function addContainerDiv() { |
|
const containerDiv = document.createElement('div'); |
|
containerDiv.style.position = 'fixed'; |
|
containerDiv.style.top = '60%'; |
|
containerDiv.style.right = '20px'; |
|
containerDiv.style.transform = 'translateY(-50%)'; |
|
containerDiv.style.padding = '10px'; |
|
|
|
const subtractContainer = createSubtractContainer(); |
|
containerDiv.appendChild(subtractContainer); |
|
|
|
document.body.appendChild(containerDiv); |
|
} |
|
|
|
// CSS styles |
|
const priceElementStyles = ` |
|
font-family: MMPrice, sans-serif; |
|
letter-spacing: 0.09em; |
|
font-size: 18px; |
|
padding-left: 10px; |
|
text-shadow: rgb(255, 255, 255) 0.04em 0px 0px, rgb(255, 255, 255) -0.04em 0px 0px, rgb(255, 255, 255) 0px -0.04em 0px, rgb(255, 255, 255) 0px 0.04em 0px, rgb(255, 255, 255) 0.04em 0.04em 0px, rgb(255, 255, 255) 0.04em -0.04em 0px, rgb(255, 255, 255) -0.04em -0.04em 0px, rgb(255, 255, 255) -0.04em 0.04em 0px, rgba(0, 0, 0, 0.2) 0.1em 0px 0.05em, rgba(0, 0, 0, 0.2) 0px 0.1em 0.05em, rgba(0, 0, 0, 0.2) 0.1em 0.1em 0.05em; |
|
`; |
|
})(); |