Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. Eigene Widget mit HTML/CSS/JAVASCRIPT + AI

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Eigene Widget mit HTML/CSS/JAVASCRIPT + AI

    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      smartysmart last edited by

      Hey Leute,
      mir fehlen leider die Programmierkentnnise um das HTML Widget selber zu machen also habe ich mir mit Claude.ai etwas Hilfe geholt.

      Ich bin auch fast am Ziel meines Vorhabens allerdings bekomme ich einen Fehler seit Stunden nicht heraus.

      Ich habe mir ein Widget gemacht wo ich Jalousien direkt hoch und runter fahren kann. Und links davon der aktuelle Status von der Jalousie angezeigt werden soll
      ab1d8a68-cfc6-4ab4-a7d0-d280c0a7da5e-image.png
      Hier ist bereits der erste Fehler weil da 0% angezeigt wird statt der echte Wert.

      Wenn ich auf das Widget klicke wird ein PopUp geöffnet mit mehr Funktionen, auch hier werden die aktuellen Werte nicht angezeigt.
      237926cc-d26e-41d9-a35a-0c3f7266ee23-image.png

      Der Regler funktioniert und die Prozente werden beim bedienen angezeigt,
      5045dbd3-7d92-4d87-b56b-0a1c45356a0e-image.png allerdings nur solange das PopUp offen ist. sobal ich das schliese und neu öffne steht oben wieder 0

      P.S im Editor wird die Jalousien Position agezeigt
      529238eb-dc74-4794-8b44-0555e47a277e-image.png

      Ich gehe aktuell also davon aus, dass auch die Werte im PopUp im Editor angezeigt werden und das das Problem nur in der VIS Ansicht ist.

      Das ist der Code dazu

      <style>
        .jalousie-widget-container {
          width: 100%;
          height: 100%;
          box-sizing: border-box;
          border-radius: 20px;
          padding: 0;
          background: #f5f5f5;
          font-family: sans-serif;
          position: relative;
          margin: 0 auto;
          border: 1px solid #e0e0e0;
          display: flex;
          flex-direction: column;
        }
        
        .jalousie-widget-header {
          display: flex;
          align-items: center;
          padding: calc(min(10px, 3%));
          border-bottom: 1px dotted #ccc;
          flex: 0 0 auto;
        }
        
        .jalousie-widget-icon {
          width: calc(min(24px, 15%));
          height: calc(min(24px, 15%));
          margin-right: calc(min(10px, 3%));
          min-width: 16px;
          min-height: 16px;
        }
        
        .jalousie-widget-title {
          font-size: calc(min(14px, 4vw));
          margin: 0;
          padding: calc(min(8px, 3%)) 0;
          text-align: left;
          border-bottom: 1px dotted #ccc;
          padding-left: calc(min(10px, 3%));
          flex: 0 0 auto;
        }
        
        .jalousie-widget-status {
          display: flex;
          align-items: center;
          padding: calc(min(10px, 3%)) calc(min(12px, 4%));
          justify-content: space-between;
          flex: 1 0 auto;
        }
        
        .jalousie-status-text {
          font-size: calc(min(16px, 4.5vw));
          margin: 0;
          font-weight: 500;
        }
        
        .jalousie-widget-buttons {
          display: flex;
        }
      
        .jalousie-widget-button {
          width: calc(min(44px, 35%));
          height: calc(min(44px, 35%));
          display: flex;
          align-items: center;
          justify-content: center;
          border: 1px solid #ccc;
          background: white;
          border-radius: 50%;
          margin-left: 8px;
          cursor: pointer;
          font-size: calc(min(26px, 8vw));
          padding: 0;
          min-width: 40px;
          min-height: 40px;
          font-weight: bold;
          color: #333;
        }
      
        .jalousie-popup-overlay {
          position: fixed;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background: rgba(0, 0, 0, 0.5);
          display: none;
          z-index: 9998;
          touch-action: none;
        }
      
        .jalousie-popup {
          display: none;
          position: fixed;
          top: 5%;
          left: 5%;
          width: 90%;
          height: 90%;
          max-height: 90vh;
          background: white;
          border-radius: 8px;
          box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
          z-index: 9999;
          font-family: sans-serif;
          overflow: hidden;
          touch-action: none;
        }
        
        .jalousie-popup.active {
          display: flex;
          flex-direction: column;
        }
        
        .jalousie-popup-header {
          padding: 15px;
          border-bottom: 1px solid #eee;
          font-size: 18px;
          font-weight: 500;
          display: flex;
          justify-content: space-between;
          align-items: center;
        }
        
        .jalousie-popup-status {
          padding: 15px;
          border-bottom: 1px solid #eee;
          display: flex;
          justify-content: space-between;
          align-items: center;
          background: #f9f9f9;
        }
        
        .jalousie-popup-status-item {
          display: flex;
          align-items: center;
        }
        
        .jalousie-popup-status-label {
          font-size: 14px;
          color: #666;
          margin-right: 10px;
        }
        
        .jalousie-popup-status-value {
          font-size: 16px;
          font-weight: bold;
        }
        
        .jalousie-popup-content {
          flex: 1;
          display: flex;
          padding: 20px;
          justify-content: center;
          overflow: hidden;
          touch-action: none;
        }
        
        .jalousie-sliders-container {
          display: flex;
          width: 100%;
          max-width: 600px;
          justify-content: space-around;
          align-items: flex-start;
        }
        
        .jalousie-slider-column {
          display: flex;
          flex-direction: column;
          align-items: center;
          width: 45%;
        }
        
        .jalousie-slider-wrapper {
          display: flex;
          flex-direction: column;
          align-items: center;
          width: 100%;
          height: 100%;
          max-height: 500px;
        }
        
        .jalousie-slider-icon {
          margin-bottom: 10px;
          width: 24px;
          height: 24px;
        }
        
        .jalousie-slider-vertical {
          -webkit-appearance: slider-vertical;
          appearance: slider-vertical;
          height: 80%;
          min-height: 200px;
          width: 50px;
          margin: 20px 0;
          transform: rotate(180deg);
          background: #e0e0e0;
          border-radius: 25px;
          outline: none;
          cursor: pointer;
        }
        
        .jalousie-slider-vertical::-webkit-slider-thumb {
          -webkit-appearance: none;
          appearance: none;
          width: 60px;
          height: 60px;
          background: #007bff;
          border-radius: 50%;
          cursor: pointer;
          box-shadow: 0 0 5px rgba(0,0,0,0.2);
        }
        
        .jalousie-slider-vertical::-moz-range-thumb {
          width: 60px;
          height: 60px;
          background: #007bff;
          border-radius: 50%;
          cursor: pointer;
          box-shadow: 0 0 5px rgba(0,0,0,0.2);
          border: none;
        }
        
        .jalousie-slider-label {
          font-size: 16px;
          margin-top: 10px;
          text-align: center;
        }
        
        .jalousie-slider-buttons {
          display: flex;
          gap: 10px;
          margin-top: 15px;
        }
        
        .jalousie-slider-button {
          width: 50px;
          height: 50px;
          display: flex;
          align-items: center;
          justify-content: center;
          border: 1px solid #ccc;
          background: white;
          border-radius: 50%;
          cursor: pointer;
          font-size: 24px;
          padding: 0;
          font-weight: bold;
          touch-action: manipulation;
          color: #333;
        }
        
        .jalousie-slider-button:hover {
          background: #f5f5f5;
        }
        
        .jalousie-slider-button:active {
          background: #e0e0e0;
        }
        
        .jalousie-popup-footer {
          padding: 15px;
          border-top: 1px solid #eee;
          display: flex;
          justify-content: space-between;
        }
        
        .jalousie-popup-button {
          padding: 10px 20px;
          background: #f5f5f5;
          border: 1px solid #ddd;
          border-radius: 4px;
          font-size: 14px;
          cursor: pointer;
          color: #333;
        }
        
        .jalousie-popup-button:hover {
          background: #eee;
        }
        
        .jalousie-value-display {
          font-size: 20px;
          font-weight: bold;
          margin-top: 10px;
          margin-bottom: 20px;
        }
      </style>
      
      <div class="jalousie-widget-container" id="dg-buero-jalousie-widget">
        <div class="jalousie-widget-header">
          <svg id="dg-buero-jalousie-icon" class="jalousie-widget-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="cursor: pointer;">
            <rect x="4" y="4" width="16" height="16" rx="2" />
            <line x1="4" y1="12" x2="20" y2="12" />
            <line x1="7" y1="8" x2="17" y2="8" />
            <line x1="7" y1="16" x2="17" y2="16" />
          </svg>
        </div>
        
        <div class="jalousie-widget-title">
          DG Büro
        </div>
        
        <div class="jalousie-widget-status">
          <div class="jalousie-status-text">
            <span id="dg-buero-jalousie-status">0</span>%
          </div>
          
          <div class="jalousie-widget-buttons">
            <button id="dg-buero-btn-up" class="jalousie-widget-button">↑</button>
            <button id="dg-buero-btn-down" class="jalousie-widget-button">↓</button>
          </div>
        </div>
      </div>
      
      <div id="dg-buero-jalousie-popup-overlay" class="jalousie-popup-overlay"></div>
      <div id="dg-buero-jalousie-popup" class="jalousie-popup">
        <div class="jalousie-popup-header">
          DG Büro
          <button id="dg-buero-close-popup" style="background: none; border: none; font-size: 20px; cursor: pointer; color: #333;">×</button>
        </div>
        
        <div class="jalousie-popup-status">
          <div class="jalousie-popup-status-item">
            <span class="jalousie-popup-status-label">Jalousie:</span>
            <span class="jalousie-popup-status-value" id="dg-buero-popup-status-jalousie">0%</span>
          </div>
          <div class="jalousie-popup-status-item">
            <span class="jalousie-popup-status-label">Lamellen:</span>
            <span class="jalousie-popup-status-value" id="dg-buero-popup-status-lamellen">0%</span>
          </div>
        </div>
        
        <div class="jalousie-popup-content">
          <div class="jalousie-sliders-container">
            <div class="jalousie-slider-column">
              <div class="jalousie-slider-wrapper">
                <svg class="jalousie-slider-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                  <rect x="6" y="4" width="12" height="16" rx="1" />
                  <line x1="6" y1="8" x2="18" y2="8" />
                  <line x1="6" y1="12" x2="18" y2="12" />
                  <line x1="6" y1="16" x2="18" y2="16" />
                </svg>
                <div class="jalousie-value-display"><span id="dg-buero-popup-jalousie-value">0</span>%</div>
                <input type="range" min="0" max="100" value="0" id="dg-buero-slider-jalousie" class="jalousie-slider-vertical" orient="vertical" />
                <div class="jalousie-slider-label">Position Jalousie</div>
                <div class="jalousie-slider-buttons">
                  <button id="dg-buero-btn-jalousie-up" class="jalousie-slider-button">↑</button>
                  <button id="dg-buero-btn-jalousie-down" class="jalousie-slider-button">↓</button>
                </div>
              </div>
            </div>
            
            <div class="jalousie-slider-column">
              <div class="jalousie-slider-wrapper">
                <svg class="jalousie-slider-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                  <path d="M12 3 L4 10 L20 10 Z" />
                  <path d="M12 10 L4 17 L20 17 Z" />
                </svg>
                <div class="jalousie-value-display"><span id="dg-buero-popup-lamellen-value">0</span>%</div>
                <input type="range" min="0" max="100" value="0" id="dg-buero-slider-lamellen" class="jalousie-slider-vertical" orient="vertical" />
                <div class="jalousie-slider-label">Position Lamellen</div>
                <div class="jalousie-slider-buttons">
                  <button id="dg-buero-btn-lamellen-up" class="jalousie-slider-button">↑</button>
                  <button id="dg-buero-btn-lamellen-down" class="jalousie-slider-button">↓</button>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        <div class="jalousie-popup-footer">
          <button id="dg-buero-btn-stop" class="jalousie-popup-button">STOP</button>
          <div>
            <button id="dg-buero-btn-preset-1" class="jalousie-popup-button">50%</button>
            <button id="dg-buero-btn-preset-2" class="jalousie-popup-button">100%</button>
          </div>
        </div>
      </div>
      
      <script>
        // Datenpunkte definieren - Diese müssen an dein ioBroker-System angepasst sein
        const statusDP = 'openknx.0.Status.Jalousinen_Lamellen.Position_Jalousine_DG_Büro_status';  // For main widget display
        const statusJalousieDP = 'openknx.0.Status.Jalousinen_Lamellen.Position_Jalousine_DG_Büro_status';  // Jalousie status in popup
        const statusLamellenDP = 'openknx.0.Status.Jalousinen_Lamellen.Position_Lamellen_DG_Büro_status';  // Lamella status in popup
        const lamellenDP = 'openknx.0.Schalten.Jalousinen.DG_Büro_Balkon_Lamellen';
        const jalousienDP = 'openknx.0.Schalten.Jalousinen.DG_Büro_Balkon_Jalousien';
        const absoluteJalousieDP = 'openknx.0.Schalten.Jalousinen.DG_Büro_Absolute_Position_Jalousine';
        const absoluteLamellenDP = 'openknx.0.Schalten.Jalousinen.DG_Büro_Absolute_Position_Lamellen';
      
        let holdTimeout;
        let statusValue = 0;
        let jalousieValue = 0;  // Status value for jalousie
        let lamellenValue = 0;  // Status value for lamella
      
        // DOM-Elemente
        const btnUp = document.getElementById('dg-buero-btn-up');
        const btnDown = document.getElementById('dg-buero-btn-down');
        const jalousieIcon = document.getElementById('dg-buero-jalousie-icon');
        const closePopup = document.getElementById('dg-buero-close-popup');
        const jalousiePopup = document.getElementById('dg-buero-jalousie-popup');
        const popupOverlay = document.getElementById('dg-buero-jalousie-popup-overlay');
        const statusElement = document.getElementById('dg-buero-jalousie-status');
        const sliderJalousie = document.getElementById('dg-buero-slider-jalousie');
        const sliderLamellen = document.getElementById('dg-buero-slider-lamellen');
        
        // DOM-Elemente für die Popup-Werte
        const popupJalousieValue = document.getElementById('dg-buero-popup-jalousie-value');
        const popupLamellenValue = document.getElementById('dg-buero-popup-lamellen-value');
        const popupStatusJalousie = document.getElementById('dg-buero-popup-status-jalousie');
        const popupStatusLamellen = document.getElementById('dg-buero-popup-status-lamellen');
        const btnStop = document.getElementById('dg-buero-btn-stop');
        const btnPreset1 = document.getElementById('dg-buero-btn-preset-1');
        const btnPreset2 = document.getElementById('dg-buero-btn-preset-2');
        
        // Additional popup buttons
        const btnJalousieUp = document.getElementById('dg-buero-btn-jalousie-up');
        const btnJalousieDown = document.getElementById('dg-buero-btn-jalousie-down');
        const btnLamellenUp = document.getElementById('dg-buero-btn-lamellen-up');
        const btnLamellenDown = document.getElementById('dg-buero-btn-lamellen-down');
      
        // Funktion für das Senden von Werten an Datenpunkte
        function sendToDP(dp, value) {
          if (typeof vis !== 'undefined') {
            vis.setValue(dp, value);
          } else {
            console.log('Sending to ' + dp + ': ' + value);
          }
        }
      
        // Funktion für das Halten von Tasten
        function setupHoldButton(button, shortDP, longDP, value) {
          button.addEventListener('mousedown', function() {
            holdTimeout = setTimeout(function() {
              sendToDP(longDP, value);
              holdTimeout = null;
            }, 400);
          });
      
          button.addEventListener('mouseup', function() {
            if (holdTimeout) {
              clearTimeout(holdTimeout);
              sendToDP(shortDP, value);
            }
          });
      
          button.addEventListener('mouseleave', function() {
            if (holdTimeout) {
              clearTimeout(holdTimeout);
            }
          });
          
          // Touch-Unterstützung für mobile Geräte
          button.addEventListener('touchstart', function(e) {
            e.preventDefault();
            holdTimeout = setTimeout(function() {
              sendToDP(longDP, value);
              holdTimeout = null;
            }, 400);
          });
      
          button.addEventListener('touchend', function(e) {
            e.preventDefault();
            if (holdTimeout) {
              clearTimeout(holdTimeout);
              sendToDP(shortDP, value);
            }
          });
        }
      
        // Popup öffnen/schließen
        function openPopup() {
          jalousiePopup.classList.add('active');
          popupOverlay.style.display = 'block';
          
          // Slider immer auf 0 setzen
          sliderJalousie.value = 0;
          sliderLamellen.value = 0;
          
          // Value-Displays auf 0 setzen
          popupJalousieValue.textContent = 0;
          popupLamellenValue.textContent = 0;
          
          // Status-Anzeige aus Datenpunkten lesen
          if (typeof vis !== 'undefined') {
            let jalousieStatus = vis.states.attr(statusJalousieDP + '.val');
            let lamellenStatus = vis.states.attr(statusLamellenDP + '.val');
            
            if (jalousieStatus !== undefined && jalousieStatus !== null) {
              popupStatusJalousie.textContent = parseInt(jalousieStatus) + '%';
            }
            
            if (lamellenStatus !== undefined && lamellenStatus !== null) {
              popupStatusLamellen.textContent = parseInt(lamellenStatus) + '%';
            }
          }
        }
        
        function closePopupFunc() {
          jalousiePopup.classList.remove('active');
          popupOverlay.style.display = 'none';
        }
      
        // Add touch event handlers to prevent background scrolling on mobile
        document.getElementById('dg-buero-jalousie-popup-overlay').addEventListener('touchmove', function(e) {
          e.preventDefault();
        }, { passive: false });
        
        document.getElementById('dg-buero-jalousie-popup').addEventListener('touchmove', function(e) {
          // Only prevent if the touch is not on a slider
          if (!e.target.classList.contains('jalousie-slider-vertical')) {
            e.preventDefault();
          }
        }, { passive: false });
        
        // Ensure sliders can be used on mobile
        ['dg-buero-slider-jalousie', 'dg-buero-slider-lamellen'].forEach(id => {
          const slider = document.getElementById(id);
          slider.addEventListener('touchmove', function(e) {
            e.stopPropagation(); // Allow slider to function normally
          }, { passive: true });
        });
        
        // Event-Listener für Popup
        jalousieIcon.addEventListener('click', openPopup);
        closePopup.addEventListener('click', closePopupFunc);
        popupOverlay.addEventListener('click', closePopupFunc);
      
        // Slider-Events mit Echtzeit-Aktualisierung
        sliderJalousie.addEventListener('input', function() {
          const value = parseInt(this.value);
          popupJalousieValue.textContent = value;
        });
      
        sliderJalousie.addEventListener('change', function() {
          const value = parseInt(this.value);
          sendToDP(absoluteJalousieDP, value);
          // Don't update statusValue directly since it comes from the datapoint
        });
      
        sliderLamellen.addEventListener('input', function() {
          const value = parseInt(this.value);
          popupLamellenValue.textContent = value;
          // Also update the status bar immediately for better user feedback
          popupStatusLamellen.textContent = value + '%';
        });
      
        sliderLamellen.addEventListener('change', function() {
          const value = parseInt(this.value);
          sendToDP(absoluteLamellenDP, value);
          // The status will be updated via datapoint binding
        });
      
        // STOP-Button und Preset-Buttons
        btnStop.addEventListener('click', function() {
          sendToDP(lamellenDP, true);
        });
      
        btnPreset1.addEventListener('click', function() {
          sendToDP(absoluteJalousieDP, 50);
        });
      
        btnPreset2.addEventListener('click', function() {
          sendToDP(absoluteJalousieDP, 100);
        });
        
        // Setup popup arrow buttons with same logic as main widget
        setupHoldButton(btnJalousieUp, lamellenDP, jalousienDP, false);
        setupHoldButton(btnJalousieDown, lamellenDP, jalousienDP, true);
        setupHoldButton(btnLamellenUp, lamellenDP, lamellenDP, false);
        setupHoldButton(btnLamellenDown, lamellenDP, lamellenDP, true);
      
        // Button-Konfiguration
        setupHoldButton(btnUp, lamellenDP, jalousienDP, false);
        setupHoldButton(btnDown, lamellenDP, jalousienDP, true);
      
        // Initialisierung für ioBroker
        function init() {
          // Status-Wert überwachen
          if (typeof vis !== 'undefined') {
      	
           // Jalousie-Status überwachen
      vis.states.bind(statusJalousieDP + '.val', function(e, newVal, oldVal) {
          if (newVal !== undefined) {  // Prüfung hinzugefügt
              jalousieValue = parseInt(newVal);
              statusElement.textContent = jalousieValue;
              sliderJalousie.value = jalousieValue;
              if (popupJalousieValue) {
                  popupJalousieValue.textContent = jalousieValue;
              }
              if (popupStatusJalousie) {
                  popupStatusJalousie.textContent = jalousieValue + '%';
              }
          }
      });
      
      // Lamellen-Status überwachen
      vis.states.bind(statusLamellenDP + '.val', function(e, newVal, oldVal) {
          if (newVal !== undefined) {
              lamellenValue = parseInt(newVal);
              sliderLamellen.value = lamellenValue;
              if (popupLamellenValue) {
                  popupLamellenValue.textContent = lamellenValue;
              }
              if (popupStatusLamellen) {
                  popupStatusLamellen.textContent = lamellenValue + '%';
              }
          }
      });
      
      
            
            // Anfangswerte laden
            if (vis.states[statusJalousieDP + '.val'] !== undefined) {
              jalousieValue = parseInt(vis.states[statusJalousieDP + '.val']);
              statusElement.textContent = jalousieValue;
              sliderJalousie.value = jalousieValue;
              popupJalousieValue.textContent = jalousieValue;
              popupStatusJalousie.textContent = jalousieValue + '%';
            }
            
            if (vis.states[statusLamellenDP + '.val'] !== undefined) {
              lamellenValue = parseInt(vis.states[statusLamellenDP + '.val']);
              sliderLamellen.value = lamellenValue;
              popupLamellenValue.textContent = lamellenValue;
              popupStatusLamellen.textContent = lamellenValue + '%';
            }
          } else {
            // Fallback für Testumgebungen
            jalousieValue = 50;
            lamellenValue = 50;
            statusElement.textContent = jalousieValue;
            sliderJalousie.value = jalousieValue;
            sliderLamellen.value = lamellenValue;
            popupJalousieValue.textContent = jalousieValue;
            popupLamellenValue.textContent = lamellenValue;
            popupStatusJalousie.textContent = jalousieValue + '%';
            popupStatusLamellen.textContent = lamellenValue + '%';
          }
        }
      
        // Wenn vis bereits geladen ist
        if (typeof vis !== 'undefined') {
          init();
        } else {
          // Falls vis noch nicht geladen ist (sollte in ioBroker nicht passieren)
          document.addEventListener('iobrokerReady', init);
        }
      </script>
      
      OliverIO 1 Reply Last reply Reply Quote 0
      • OliverIO
        OliverIO @smartysmart last edited by OliverIO

        @smartysmart

        Das Hauptproblem ist, das die ganzen datenpunkte nicht abonniert wurde.
        Vis sammelt beim Start (also bspw neuladen mit f5) zunächst erst einmal alle vorhandenen datenpunkte ein und abonniert diese beim Server.
        Erst dann sind die in der vis.states Auflistung vorhanden.
        Das passiert bei dir nicht. Daher auch keine Daten

        Du kannst mal hier nach meiner Funktion bindStates schauen.
        Die macht das mit der Angabe des datenpunkt namens.
        Du musst aber ein html Element mitgeben. Dort werden dann die trigger für die Änderung gespeichert, das die auch wieder entfernt werden. Ansonsten holst du dir früher oder später ein Speicherwerk, da sich mit der Zeit immer mehr trigger anhäufen und bei einer Änderung deine Funktionen dann zigmal aufgerufen werden.

        https://github.com/oweitman/ioBroker.tvprogram/blob/404b70e1e1886b545d9ae9f0b2dd7f2f27452179/widgets/tvprogram/js/tvprogram.js#L122

        Die variablen mit $ sind jquery Objekte.

        1 Reply Last reply Reply Quote 0
        • First post
          Last post

        Support us

        ioBroker
        Community Adapters
        Donate

        758
        Online

        31.7k
        Users

        79.7k
        Topics

        1.3m
        Posts

        2
        2
        79
        Loading More Posts
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes
        Reply
        • Reply as topic
        Log in to reply
        Community
        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
        The ioBroker Community 2014-2023
        logo