I would like to write something like the following html and js code in which I can call the Walking function many times in the text of the html, and for the function to make a calculation and place the result in place of the script tags.
But I cannot find an appropriate js function to write the html in the correct place without having to define for example a span element with a given ID that I would have to pass through to the function each time.
function Walking(distance, ascent, descent) {
// Calculate walking time from distance, ascent and descent
// and display this and other info at point the function is called.
}
Walk for
<script>
Walking(1000, 100, 0);
</script> until you arrive at ... Then walk steeply uphill for
<script>
Walking(2500, 1100, 0);
</script> to reach the summit.
CodePudding user response:
It is not trivial, but you can learn a lot from the code below.
Components:
- Event handling
- document.querySelectorAll
- data-attributes
- template literals
- ternary/conditional operaot
- destructuring
const avgWalk = 4; // km/h
const ascWalk = 2;
const dscWalk = 4.5;
const decimalHoursToHHMM = num => {
let n = new Date(0,0);
n.setSeconds( num * 60 * 60); // convert to seconds
let [HH,MM] = n.toTimeString().slice(0, 5).split(":"); // convert to HH:MM and spread the result to HH and MM
return HH === 0 ? `${ MM}m` : `${ HH}h${ MM}m`; // using template literals
};
// Calculate walking time from distance, ascent and descent
// and display this and other info at point the function is called.
const Walking = ([distance, ascent, descent]) => decimalHoursToHHMM(
(distance/1000)/avgWalk -
(ascent/1000)/ascWalk
(descent/1000)/dscWalk);
window.addEventListener("DOMContentLoaded", () => { // when page has loaded
document.querySelectorAll(".calc") // all elements with class "calc"
.forEach(span => span.textContent = Walking(JSON.parse(span.dataset.parms))); // use the data-parms for values and set the textContent
})
Walk for <span data-parms="[1000, 100, 0]"></span> until you arrive at ... Then walk steeply uphill for
<span data-parms="[2500, 1100, 0]"></span> to reach the summit.
Return trip should last <span data-parms="[5000, 0, 5000]"></span>.
CodePudding user response:
You can use document.currentScript
and replaceWith()
, to replace the function-calling script element (e.g. with text):
<script>
function addText() {
document.currentScript.replaceWith(" and added text");
}
</script>
Default text<script>addText();</script>.
Note that the function needs to be defined earlier than where the call happens.