datapuunkt.JPG
------------------- KONFIGURATION ------------------- */ // Ziel-State, in welchem das interpretierte HTML abgelegt wird. Der State muss vorher manuell angelegt worden sein const STATE_BROWSE_RESULT_HTML = '0_userdata.0.heos.browse_result_html'; // play-Befehle werden immer via broadcast an alle Player gesendet, ist dieses nicht gewünscht, so können in dem hier // anzugegebenen State die PIDs der Player angegeben werden, welche die play-Befehle erhalten sollen. Lässt sich // z.B. gut mit dem Widget jqui-container-HTML-View "Setze Objekt-ID" nutzen. // Im State sind die Player-PIDs durch , getrennt angebbar, der State muss vorher manuell angelegt worden sein const STATE_BROWSE_RESULT_PLAYERS = '0_userdata.0.heos.browse_result_player'; // Font und Rahmen-Basisfarbe, bei dunklem Hintergrund durch '255,255,255' ersetzen const HEOS_FONT_COLOR = '0,0,0'; // wenn es sich bei der HEOS Instanz nicht um die 0. handelt, bitte anpassen const HEOS_INSTANCE = '0'; // sollen die Navigationsergebnisse beim Starten des Scripts bereits untersucht werden? const BUILD_HTML_AT_SCRIPTSTART = true; ------------------- Script ------------------- */ const STATE_BROWSE_RESULT = `heos.${HEOS_INSTANCE}.sources.browse_result`; const STATE_COMMAND = `heos.${HEOS_INSTANCE}.command`; const STATE_PLAYERS = `heos.${HEOS_INSTANCE}.players`; function buildHTML( data ) { // sind players angegeben, so wird das globale command-State durch die Player-command-States ersetzt und // "player/" wird aus dem command selbst entfernt function buildOnClick(cmd,cmdState,players,doPatch) { let cmds = [cmdState]; let onClick = ''; // wenn nur ein player angesprochen werden soll, dann command-state auf den des players setzen // und command anpassen 'player\' entfernen if (doPatch && players!='') { cmds = players.split(','); for (let j=0; j<cmds.length; j++ ) cmds[j] = `${STATE_PLAYERS}.${cmds[j]}.command`; cmd = cmd.substr(cmd.indexOf('/',cmd)+1,9999); } for (let j=0; j<cmds.length; j++ ) onClick += `servConn.setState('${cmds[j]}','${cmd}');`; return onClick; } let html = "Sorry, no data!" if(data){ let command = getState(STATE_COMMAND).val; let playerIDs = ''; if (existsState(STATE_BROWSE_RESULT_PLAYERS)) playerIDs = getState(STATE_BROWSE_RESULT_PLAYERS).val; // Playernamen ermitteln let playerNames = 'Alle'; if (playerIDs!='') { let players = playerIDs.split(','); playerNames = ''; for (let i=0; i<players.length; i++) { if (existsState(`${STATE_PLAYERS}.${players[i]}.name`)) playerNames += (playerNames==''?'':', ') + getState(`${STATE_PLAYERS}.${players[i]}.name`).val; } } // subtitle soll Anzahl enthalten let subtitle = ''; if (data.parameter.count) subtitle += `${data.parameter.count} Einträge`; else if (data.payload) subtitle += `${data.payload.length} Einträge`; if (data.parameter.range) subtitle += ` (${data.parameter.range.replace(',','-')})`; if (subtitle!='') subtitle = `<div class="heos-head-subtext">${subtitle}</div>`; // globale Funktionen wie Übersicht/Back/... in der Kopfzeile darstellen let controls={'load_next':{'sym':'›', 'onClick':'' }, 'load_prev':{'sym':'‹', 'onClick':'' }, 'play_all': {'sym':'▸', 'onClick':'' }, 'back': {'sym':'▴', 'onClick':'' }, 'sources': {'sym':'=', 'onClick':'' }, 'getHTML': function(key) { return `<div class="heos-head-btn ${controls[key].onClick!=''?'heos-clickable':''}" ${controls[key].onClick}> ${controls[key].sym} </div>`; } }; for (let i = 0; i < data.payload.length; i++) { let payload = data.payload[i]; if (payload.type=="control" && controls.hasOwnProperty(payload.name)) { let onClick = ''; for (let key in payload.commands) onClick = buildOnClick(payload.commands[key],STATE_COMMAND,playerIDs,key=='play'); controls[payload.name].onClick = `onClick="${onClick}"`; } } // Zeilen des Listview aufbauen let rowsHTML=''; for (let i = 0; i < data.payload.length; i++) { let payload = data.payload[i]; if (payload.type!="control") { for (let key in payload.commands) { let sym = ''; let onClick = buildOnClick(payload.commands[key],STATE_COMMAND,playerIDs,key=='play'); switch (key) { case 'play': sym = '▸'; break; case 'browse': break; } rowsHTML += `<div class="heos-row" onClick="${onClick}"> <div class="heos-img">${payload.image_url!=''?`<img class="heos-img-fit" src="${payload.image_url}" width="auto" height="100%" alt="">`:'<div class="heos-img-empty"></div>'}</div> <div class="heos-text">${payload.name}</div> <div class="heos-btn">${sym}</div> </div>`; } } } html = ` <style type="text/css"> :root {--heos-font-color:rgba(${HEOS_FONT_COLOR},.9); --heos-border-color:rgba(${HEOS_FONT_COLOR},.05); } .heos-root { position:absolute; height:100%; width:100%; color:var(--heos-font-color); } .heos-head { height:96px; border-bottom:4px solid var(--heos-border-color); } .heos-head-players { font-size:0.7em; opacity:0.66; text-align:right; } .heos-head-img { width:72px; flex:none; height:72px; overflow:hidden; } .heos-head-title { width:100%; overflow:hidden; display:flex; align-items:flex-start; } .heos-head-text {text-align:left;padding-top:0.25em;padding-left:4px;font-size:1.1em;} .heos-head-subtext { font-size:0.66em; opacity:0.66; } .heos-head-btns {width:108px; flex:none; display:flex; flex-wrap:wrap; margin-left:auto;} .heos-head-btns-row {width:100%; display:flex;} .heos-head-btn {width:36px; height:36px; opacity:.2;text-align:center;font-size:2em; } .heos-body { overflow-y:auto; height:calc(100% - 72px); } .heos-img { width:64px; height:100%; overflow:hidden; } .heos-img-fit { width:100%; height:100%; object-fit:contain; } .heos-img-empty:after { content:'\\266A'; font-size:2.5em; opacity:0.2; display:flex; justify-content:center;} .heos-row { width:100%;height:56px;border-bottom:1px solid var(--heos-border-color);padding-top:4px;padding-bottom:4px; display:flex; align-items: center;} .heos-text {width:calc(100% - 112px);text-align:left;padding-left:4px;white-space: nowrap;overflow:hidden;} .heos-btn {width:48px;border-radius: 2px;text-align:center;font-size:2em; border-left:1px solid var(--heos-border-color); } .heos-clickable {opacity:1; } .heos-row:hover, .heos-clickable:hover {background-blend-mode:multiply;background-image: linear-gradient(var(--heos-border-color),var(--heos-border-color)) !important; } [class*="_heos-"] {outline:1px solid rgba(255,0,0,.2); outline-offset:-1px;} </style> <div class="heos-root"> <div class="heos-head"> <div class="heos-head-title"> <div class="heos-head-img">${data.image_url!=''?`<img class="heos-img-fit" src="${data.image_url}" alt="">`:'<div class="heos-img-empty"></div>'}</div> <div class="heos-head-text"> <div style="height:56px; overflow:hidden;"> ${data.name == "sources"?"HEOS Quellen-Übersicht":data.name} </div> ${subtitle} </div> <div class="heos-head-btns"> <div class="heos-head-btns-row"><div class="heos-head-btn"></div>${controls.getHTML('sources')+controls.getHTML('back')}</div> <div class="heos-head-btns-row">${controls.getHTML('load_prev')+controls.getHTML('play_all')+controls.getHTML('load_next')}</div> </div> </div> <div class="heos-head-players">Player: ${playerNames}</div> </div> <div class="heos-body"> ${rowsHTML} </div> </div>`; } setState(STATE_BROWSE_RESULT_HTML, html); }; // browse_result Überwachung on({id: STATE_BROWSE_RESULT, change: 'any'}, function (obj) { let data = JSON.parse(obj.state.val); if(data) buildHTML(data); }); on({id: STATE_BROWSE_RESULT_PLAYERS, change: 'any'}, function (obj) { let data = JSON.parse(getState(STATE_BROWSE_RESULT).val); if(data) buildHTML(data); }); // Sriptstart if (BUILD_HTML_AT_SCRIPTSTART) buildHTML( JSON.parse(getState(STATE_BROWSE_RESULT).val) );fehlermeldung.JPG