Beispiel:BMI-Rechner.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>BMI-Rechner</title> <script>

     "use strict"
     // Custom-Element self-slider anlegen
     customElements.define('self-slider', class extends HTMLElement {
       // self-slider soll Formularelement sein
       static formAssociated = true;
       // Festlegen, welche Attribute überwacht werden sollen
       static get observedAttributes() {
         return ['legend', 'label', 'min', 'max', 'step', 'value'];
       }
       constructor() {
         // Element wird anlgelegt
         // super muss als erstes im constructor aufgerufen werden, super ruft den construcor der Elternklasse auf
         super(); 
         // Zugriff auf die ElementInternals, wird benötigt, um auf die Werte zuzugreifen, die mit dem Formular versendet werden.
         this.internals = this.attachInternals();
         // Schatten-DOM anlegen
           // mode: 'open' : Vom Dokument aus ist der Zugriff auf das Schatten-Dom möglich.
           // mode: 'closed' : Der Zugriff auf das Schatten-Dom ist nicht möglich.
         const shadow = this.attachShadow({mode: 'closed'});
         // Element für Inhalt, hier ein fieldset, anlegen und ins Schatten-DOM einhängen
         this.slider = document.createElement('fieldset');
         this.slider.setAttribute('part', 'fieldset');
         shadow.appendChild(this.slider);
         // CSS anlegen und ins Schatten-Dom einhängen
         // :host selektiert das Custom Element
         const style = document.createElement('style');
         style.textContent = `
           :host fieldset { max-inline-size: fit-content; }
           :host fieldset * { display: inline-block; vertical-align: top; margin: 0; padding: .1em}
           :host input { font-size: .9em; }
         `;
         shadow.appendChild(style);
         // Defaultwerte der Attribute setzen
         this.legendAttribute = ;
         this.labelAttribute = ;
         this.minAttribute = 0;
         this.maxAttribute = 100;
         this.stepAttribute = 1;
         this.valueAttribute = 0;
       }
       connectedCallback() {
         // Element wurde ins DOM eingehängt
         // Schatten-DOM aufbauen
         // Zufällige ID für das Number-Input, wird fürs Label benötigt
         const numberID = Math.random().toString().replace('0.',);
         // Legende
         this.legend = document.createElement('legend');
         this.legend.setAttribute('part', 'legend');
         if(this.legendAttribute.length) {
           this.legend.innerHTML = this.legendAttribute;
         }
         else {
           this.legend.setAttribute('hidden', 'hidden');
         }
         this.slider.appendChild(this.legend);
         // Label
         this.label = document.createElement('label');
         this.label.setAttribute('for', numberID);
         this.label.setAttribute('part', 'label');
         if(this.labelAttribute.length) {
           this.label.innerHTML = this.labelAttribute;
         }
         else {
           this.label.setAttribute('hidden', 'hidden');            
         }
         this.slider.appendChild(this.label);
         // Range-Input
         this.range = document.createElement('input');
         this.range.setAttribute('type', 'range');
         this.range.setAttribute('min', this.minAttribute);
         this.range.setAttribute('max', this.maxAttribute);
         this.range.setAttribute('step', this.stepAttribute);
         this.range.setAttribute('value', this.valueAttribute);
         this.range.setAttribute('part', 'range');
         this.slider.appendChild(this.range);
         // Number-Input
         this.number = document.createElement('input');
         this.number.setAttribute('id', numberID);
         this.number.setAttribute('type', 'number');
         this.number.setAttribute('min', this.minAttribute);
         this.number.setAttribute('max', this.maxAttribute);
         this.number.setAttribute('step', this.stepAttribute);
         this.number.setAttribute('value', this.valueAttribute);
         this.number.setAttribute('part', 'number');
         this.slider.appendChild(this.number);
         // Start-Value speichern und ans Formular übergeben
         this.currentValue = this.valueAttribute;
         this.internals.setFormValue(this.currentValue);
         // Eventhandler, um die beiden Inputs zu synchronisieren und den Wert zu speichern und ans Formular zu übergeben
         this.slider.addEventListener('input', event => {
           if(event.target.type == 'range') {
             this.number.value = event.target.value;
           }
           else if(event.target.type == 'number') {
             this.range.value = event.target.value;
           }
           this.currentValue= event.target.value;
           this.internals.setFormValue(this.currentValue);
         });
       }
       attributeChangedCallback(name, oldValue, newValue) {
         // Elementparameter wurden geändert
         // Achtung attributeChangedCallback wird vor connectedCallback aufgerufen, daher prüfen, ob Elemente schon vorhanden sind
         switch(name) { 
           case 'legend':
             this.legendAttribute = newValue;
             if(this.legend) {
               if(this.legendAttribute && this.legendAttribute.length) {
                 this.legend.removeAttribute('hidden');
                 this.legend.innerHTML = this.legendAttribute;
               }
               else {
                 this.legend.setAttribute('hidden','hidden');
               }
             }
             break;
           case 'label':
             this.labelAttribute = newValue;
             if(this.label) {
               if(this.labelAttribute && this.labelAttribute.length) {
                 this.label.removeAttribute('hidden');
                 this.label.innerHTML = this.labelAttribute;
               }
               else {
                 this.label.setAttribute('hidden','hidden');
               }
             }
             break;
           case 'min':
             this.minAttribute = newValue;
             if(this.number) this.number.setAttribute('min', this.minAttribute);
             if(this.range) this.range.setAttribute('min', this.minAttribute);
             break;
           case 'max':
             this.maxAttribute = newValue;
             if(this.number) this.number.setAttribute('max', this.maxAttribute);
             if(this.range) this.range.setAttribute('max', this.maxAttribute);
             break;
           case 'step':
             this.stepAttribute = newValue;
             if(this.number) this.number.setAttribute('step', this.stepAttribute);
             if(this.range) this.range.setAttribute('step', this.stepAttribute);
             break;
           case 'value':
             this.currentValue = newValue;
             this.valueAttribute = newValue;
             if(this.number) this.number.setAttribute('value', this.valueAttribute);
             if(this.range) this.range.setAttribute('value', this.valueAttribute);
             this.internals.setFormValue(this.currentValue);
             break;
         }
       }
       // Setter und Getter für value.
       set value(value) {
         this.currentValue = value;
         this.number.value = value;
         this.range.value = value;
         this.internals.setFormValue(value);
       }
       get value() {
         return this.currentValue;
       }
     } );   

</script>

<style> self-slider::part(label) { display: block; } self-slider::part(number) { width: 4em; text-align: right;} self-slider::part(range) { width: 20em; } self-slider::part(fieldset) { border: none; }

     meter { width: 20rem; }
     .safari {
       .extreme { 
         -webkit-appearance: none;
         appearance: none;
         box-sizing: border-box
       }
       .extreme::-webkit-meter-suboptimum-value {
         background: red;
         border-radius: 14px;
       }
       .extreme::-webkit-meter-bar {
         background: rgb(232 232 232);
         border-radius: 14px;
         height: 14px;
         margin-top: 1px;
       }
     }
     .firefox {
       .extreme { 
         appearance: none; /* Firefox */
         border: 1px solid #888;
         border-radius: 12px;
         background: rgb(232 232 232);
         height: 12px;
         position: relative;
         top: -2px;
         box-sizing: border-box;
       }
       .extreme::-moz-meter-bar {
         background: red;
         border-top-left-radius: 12px; ;
         border-bottom-left-radius: 12px; ;
         height: 12px;
       }
     }
     .chrome, .egde {
       .extreme::-webkit-meter-suboptimum-value {
         border-top-right-radius: 0;
         border-bottom-right-radius: 0;
       }
     }
     .extreme::-webkit-meter-suboptimum-value {
       background: red;
     }
     p { max-width: 30em;}
     

</style>

<script> "use strict"

// Browser-Check // Source - https://stackoverflow.com/a/52445821 // Posted by Christopher Martin // Retrieved 2026-07-17, License - CC BY-SA 4.0 // Modified by selfhtml

     function checkBrowser() {
       if(navigator.vendor.match(/google/i)) {
         document.body.classList.add("chrome");
       }
       else if(navigator.vendor.match(/apple/i)) {
         document.body.classList.add("safari");
       }
       else if(navigator.userAgent.match(/firefox\//i)) {
         document.body.classList.add("firefox");
       }
         else if(navigator.userAgent.match(/edge\//i)) {
           document.body.classList.add("edge");
       }
     }
     document.addEventListener('DOMContentLoaded', () => {   
       checkBrowser();

const weight_in = document.querySelector("#weight_in"); const height_in = document.querySelector("#height_in"); const weight_out = document.querySelector("#weight_out"); const height_out = document.querySelector("#height_out"); const bmi_out = document.querySelector("#bmi_out"); const bmi_meter = document.querySelector("#bmi_meter"); const category_out = document.querySelector("#category_out");

document.body.addEventListener("input", (input_event) => { calc_bmi(); });

       calc_bmi();

});

function calc_bmi() { let weight = Number(weight_in.value); let height = Number(height_in.value); let bmi = weight / Math.pow(height,2);

       let category;
       if (bmi <17 ) {
        category = "Du hast Magersucht.";
         bmi_meter.classList.add("extreme");
       }
       else if (bmi < 20) {
         category = "Du hast Untergewicht.";
         bmi_meter.classList.remove("extreme");
       } else if (bmi < 25) {
         category = "Du hast Normalgewicht.";
         bmi_meter.classList.remove("extreme");
       } else if (bmi < 30) {
         category = "Du hast Übergewicht.";
         bmi_meter.classList.remove("extreme");
       } else {
         category = "Du bist Fettleibig.";
         bmi_meter.classList.add("extreme");
       }

weight_out.innerText = weight.toLocaleString( undefined, {minimumFractionDigits: 1, maximumFractionDigits: 1}); height_out.innerText = height.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); bmi_out.innerText = bmi.toLocaleString(undefined, {minimumFractionDigits: 1, maximumFractionDigits: 1});

       bmi_meter.value = bmi;
       bmi_meter.innerText = bmi.toLocaleString(undefined, {minimumFractionDigits: 1, maximumFractionDigits: 1});
       category_out.innerText = category;

} </script>

</head>

<body>

BMI-Rechner

<self-slider id="weight_in" label="Gewicht in kg" min="40" max="200" value="70" step="0.5"></self-slider>

<self-slider id="height_in" label="Größe in m" min="1.2" max="2.2" value="1.8" step="0.01"></self-slider>

Bei einem Gewicht von <output id="weight_out">--</output> kg und einer Größe von <output id="height_out">--</output> m beträgt der BMI <output id="bmi_out">--</output>.

   <meter id="bmi_meter" min="10" low="20" high="25" max="40"">BMI</meter>

<output id="category_out">--</output>

Diese Seite ist ein Beispiel für das Erfassen, Verarbeiten und Anzeigen von Daten. Der Autor besitzt kein medizinisches Fachwissen und die Interpretation der Werte erfolgt nach diversen Quellen aus dem Internet, deren Glaubwürdigkeit nicht geprüft wurde.

</body> </html>