|  | // ==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; | 
        
          |  | `; | 
        
          |  | })(); |