Necesito ayuda ya que soy bastante nuevo en JavaScript.
Deseo crear una función que calcule una cuota de membresía
Intenté crear una función en JavaScript que verifica si solo se ha seleccionado una opción, pero no tengo idea de cómo hacerlo para poder calcular la tarifa si un usuario es elegible para más de uno o todos los descuentos. Todavía no hay JS actual para la condición de edad (entre 60 y 80) ya que no estoy seguro de cómo hacerlo.
function feeCalc() { var ans = document.getElementById("answer"); if (document.getElementById('medicalCond-yes').checked) { ans.value = calculate('medicalCond-yes'); } if (document.getElementById('empstatus-yes').checked) { ans.value = calculate('empstatus-yes'); } if (document.getElementById('empstatus-no').checked) { ans.value = calculate('empstatus-no'); } if (document.getElementById('medicalCond-no').checked) { ans.value = calculate('medicalCond-no'); } } function calculate(action) { var standardRate = 10; var ageRate = 0.1; var medicalRate = 0.4; var unemployedRate = 0.3; var result; switch (action) { case 'medicalcond-yes': discount = (standardRate * studentRate); result = standardRate - discount; break; case 'empstatus-yes': discount = (standardRate * unemployedRate); result = standardRate - discount; break; case 'empstatus-no': result = standardRate; break; case 'medicalcond-no': result = standardRate; break; } return result; } <div class="form"> <label> Age </label> <input type="range" value="50" min="1" max="100" class="slider" id="age"/> </div> <div class="form"> <label> Do you have any long-term medical conditions that can affect daily life </label> <br/> <input type="radio" name="status" value="yes" id="medicalCond-yes"/>Yes <input type="radio" name="status" value="no" id="medicalCond-no"/>No </div> <div class="form"> <label> Are you currently employed? </label> <br/> <input type="radio" name="empstatus" value="yes" id="empstatus-yes"/>Yes <input type="radio" name="empstatus" value="no" id="empstatus-no"/>No </div> <div class="form"> <label> Membership Fee </label> <br/> Total Fee: <input type="text" id="answer" readonly/> <input type="button" value="Calculate" onclick="feeCalc()"/> </div>En lugar de cambiar el enrutamiento de casos a una sola sucursal, probablemente desee verificar todos los casos de una sola vez.
function feeCalc() { var ans = document.getElementById("answer"); ans.value = calculateRate(); } function calculateRate() { let discount = 0; const age = Number(document.getElementById('age').value); if (age >= 60 && age <= 80) { discount += 0.1; } if (document.getElementById('medicalCond-yes').checked) { discount += 0.4; } if (document.getElementById('empstatus-no').checked) { discount += 0.3; } return 1 - discount; } <div class="form"> <label> Age </label> <input type="range" value="50" min="1" max="100" class="slider" id="age"/> </div> <div class="form"> <label> Do you have any long-term medical conditions that can affect daily life </label> <br/> <input type="radio" name="status" value="yes" id="medicalCond-yes"/>Yes <input type="radio" name="status" value="no" id="medicalCond-no"/>No </div> <div class="form"> <label> Are you currently employed? </label> <br/> <input type="radio" name="empstatus" value="yes" id="empstatus-yes"/>Yes <input type="radio" name="empstatus" value="no" id="empstatus-no"/>No </div> <div class="form"> <label> Membership Fee </label> <br/> Total Fee: <input type="text" id="answer" readonly/> <input type="button" value="Calculate" onclick="feeCalc()"/> </div>Aunque para el problema del OP parece un exceso de ingeniería, el código proporcionado por el OP es lo suficientemente pequeño como para demostrar las ventajas de los enfoques (más) genéricos que son ...
Especialmente el código JavaScript que implementa un enfoque/comportamiento de causa genérico es más grande desde el principio que su competidor escrito muy explícitamente. Pero el primero no tiende a crecer o ni siquiera necesita ser tocado para nuevas opciones de descuento o valores de descuento modificados. Esta parte queda cubierta por subestructuras más limpias y genéricas (por lo tanto, reutilizables) de la superestructura de la calculadora también genérica.
Además, este enfoque basado en componentes genéricos permite automáticamente el uso de más de un componente en/dentro de un mismo documento.
function parseJson(str) { let result; try { result = JSON.parse(str); } catch (exc) { result = null; } return result; } function getDevaluationFactorFromRange(formControl, range) { let factor = 0; range = parseJson(range); if (range !== null) { const controlValue = parseFloat(formControl.value); Object .entries(range) .some(([devaluationKey, { min, max }]) => { let isStopIteration = false; if ( (controlValue >= parseFloat(min)) && (controlValue <= parseFloat(max)) ) { factor = parseFloat(devaluationKey); isStopIteration = true; } return isStopIteration }); } return Number.isFinite(factor) ? factor : 0; } function getDevaluationFactor(formControl) { const { dataset } = formControl; let rawRange = dataset.devaluationRange ?? null; let rawFactor = dataset.devaluationFactor ?? null; let factor = (rawRange !== null) ? getDevaluationFactorFromRange(formControl, rawRange) : 0; factor = ( (factor === 0) && (rawFactor !== null) && parseFloat(rawFactor) ) || factor; factor = Number.isFinite(factor) ? factor : 0; if (factor !== 0) { const { type } = formControl; if ((type === 'radio') || (type === 'checkbox')) { factor = formControl.checked ? factor : 0; } } return factor; } function computeCurrentFee(rootNode, elmFee, baseFee) { return Array // array from `HTMLFormControlsCollection` .from(rootNode.elements) // calculate currrent fee from each form element's data .reduce((currentFee, formControl) => { return currentFee - (baseFee * getDevaluationFactor(formControl)); }, baseFee); } function updateCurrentValueAtBoundFeeContext(/*evt*/) { const { rootNode, elmFee, baseFee } = this; elmFee.value = computeCurrentFee(rootNode, elmFee, baseFee); } function displayCurrentValueAtBoundAgeContext(/*evt*/) { const { elmRange, elmOutput } = this; elmOutput.value = elmRange.value; } function initializeCurrentAgeDisplay(rootNode) { const ageNode = rootNode.querySelector('[data-age-range]'); if (ageNode) { const elmRange = ageNode.querySelector('input[type="range"]'); const elmOutput = ageNode.querySelector('output'); if (elmRange && elmOutput) { const target = { elmRange, elmOutput }; const boundContextHandler = displayCurrentValueAtBoundAgeContext.bind(target); elmRange.addEventListener('input', boundContextHandler); rootNode.addEventListener('reset', () => // decouple custom dom refresh from the system's one. setTimeout(boundContextHandler, 0) ); // display initial age value. // // displayCurrentValueAtBoundAgeContext.call(target); boundContextHandler(); } } } function initializeMembershipFeeCalculator(rootNode) { const DEFAULT_BASE_FEE = 10; initializeCurrentAgeDisplay(rootNode); const elmFeeValue = rootNode.querySelector('[data-fee-value]'); if (elmFeeValue) { const baseFee = parseFloat(rootNode.dataset.baseFee); const target = { rootNode, elmFee: elmFeeValue, baseFee: Number.isFinite(baseFee) ? baseFee : DEFAULT_BASE_FEE, }; const boundContextHandler = updateCurrentValueAtBoundFeeContext.bind(target); rootNode.addEventListener('input', boundContextHandler); rootNode.addEventListener('reset', () => // decouple custom dom refresh from the system's one. setTimeout(boundContextHandler, 0) ); // compute initial fee value. // // updateCurrentValueAtBoundFeeContext.call(target); boundContextHandler(); rootNode.addEventListener('submit', evt => { evt.preventDefault(); return false; }); } } function main() { document .querySelectorAll('form[data-membership-fee-calculator]') .forEach(initializeMembershipFeeCalculator); } main(); body, form { margin: 0; padding: 0; } form { float: left; width: 50%; margin-top: -2px; } fieldset { position: relative; margin: 0 0 2px 0; padding: 0 10px 2px 10px; } fieldset p { margin: 1px 0 2px 0; } fieldset output { color: #333; font-weight: bolder; } label { display: inline-block; } input[type="range"] { width: 70%; } [data-age-range] output { display: inline-block; overflow: hidden; max-width: 25%; max-height: 1.2em; position: relative; top: 1px; } [type="reset"] { position: absolute; right: 4px; top: -4px; } <form data-membership-fee-calculator data-base-fee="10"> <fieldset data-age-range> <legend> Age </legend> <input type="range" name="age" id="age" value="50" min="1" max="100" data-devaluation-range='{"0.1":{"min":60,"max":80}}' /> <output for="age">### not yet computed ###</output> </fieldset> <fieldset> <p> Do you have any long-term medical conditions that can affect daily life? </p> <label> <input type="radio" name="status" value="yes" data-devaluation-factor="0.4" /> <span class="label-copy"> Yes </span> </label> <label> <input type="radio" name="status" value="no" /> <span class="label-copy"> No </span> </label> </fieldset> <fieldset> <p> Are you currently employed? </p> <label> <input type="radio" name="empstatus" value="yes" data-devaluation-factor="0.3" /> <span class="label-copy"> Yes </span> </label> <label> <input type="radio" name="empstatus" value="no" /> <span class="label-copy"> No </span> </label> </fieldset> <fieldset> <legend> Membership Fee </legend> <label> <span class="label-copy"> Total Fee: </span> <output data-fee-value>### not yet computed ###</output> </label> <button type="reset">Restore base fee</button> </fieldset> </form> <form data-membership-fee-calculator data-base-fee="20"> <fieldset data-age-range> <legend> Age </legend> <input type="range" name="age" id="age" value="21" min="1" max="100" data-devaluation-range= '{"0.05":{"min":60,"max":69},"0.1":{"min":70,"max":79},"0.2":{"min":80,"max":120}}' /> <output for="age">### not yet computed ###</output> </fieldset> <fieldset> <p> Do you have any long-term medical conditions that can affect daily life? </p> <label> <input type="radio" name="status" value="yes" data-devaluation-factor="0.3" /> <span class="label-copy"> Yes </span> </label> <label> <input type="radio" name="status" value="no" /> <span class="label-copy"> No </span> </label> </fieldset> <fieldset> <p> Are you currently employed? </p> <label> <input type="radio" name="empstatus" value="yes" data-devaluation-factor="0.3" /> <span class="label-copy"> Yes </span> </label> <label> <input type="radio" name="empstatus" value="no" /> <span class="label-copy"> No </span> </label> </fieldset> <fieldset> <legend> Membership Fee </legend> <label> <span class="label-copy"> Total Fee: </span> <output data-fee-value>### not yet computed ###</output> </label> <button type="reset">Restore base fee</button> </fieldset> </form>