iobroker.skiinfo
Version:
1,151 lines (1,147 loc) • 47 kB
JavaScript
"use strict";
(() => {
var __getOwnPropNames = Object.getOwnPropertyNames;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// skiinfo/i18n/translations.json
var require_translations = __commonJS({
"skiinfo/i18n/translations.json"(exports, module) {
module.exports = {
Land: {
en: "Country",
de: "Land",
ru: "\u0421\u0442\u0440\u0430\u043D\u0430",
pt: "Pa\xEDs",
nl: "Land",
fr: "Pays",
it: "Paese",
es: "Pa\xEDs",
pl: "Kraj",
uk: "\u041A\u0440\u0430\u0457\u043D\u0430",
"zh-cn": "Country"
},
Region: {
en: "Region",
de: "Region",
ru: "\u0420\u0435\u0433\u0438\u043E\u043D",
pt: "Regi\xE3o",
nl: "Regio",
fr: "R\xE9gion",
it: "Regione",
es: "Regi\xF3n",
pl: "Region",
uk: "\u0420\u0435\u0433\u0456\u043E\u043D",
"zh-cn": "Region"
},
Area: {
en: "Area",
de: "Bereich",
ru: "\u041E\u0431\u043B\u0430\u0441\u0442\u044C",
pt: "\xC1rea",
nl: "Gebied",
fr: "Zone",
it: "Area",
es: "Zona",
pl: "Obszar",
uk: "\u041F\u043B\u043E\u0449\u0430",
"zh-cn": "Area"
},
Tal: {
en: "Valley",
de: "Tal",
ru: "\u0414\u043E\u043B\u0438\u043D\u0430",
pt: "Vale",
nl: "Vallei",
fr: "Vall\xE9e",
it: "Valle",
es: "Valle",
pl: "Dolina",
uk: "\u0414\u043E\u043B\u0438\u043D\u0430",
"zh-cn": "Valley"
},
Berg: {
en: "Mountain",
de: "Berg",
ru: "\u0413\u043E\u0440\u0430",
pt: "Montanha",
nl: "Berg",
fr: "Montagne",
it: "Montagna",
es: "Monta\xF1a",
pl: "G\xF3ra",
uk: "\u0413\u043E\u0440\u0430",
"zh-cn": "Mountain"
},
Neu: {
en: "Fresh",
de: "Frisch",
ru: "\u0421\u0432\u0435\u0436\u0438\u0435",
pt: "Fresco",
nl: "Vers",
fr: "Frais",
it: "Fresco",
es: "Fresco",
pl: "\u015Awie\u017Cy",
uk: "\u0421\u0432\u0456\u0436\u0438\u0439",
"zh-cn": "Fresh"
},
Lift: {
en: "Lift",
de: "Aufzug",
ru: "\u041F\u043E\u0434\u044A\u0435\u043C\u043D\u0438\u043A",
pt: "Elevador",
nl: "Lift",
fr: "Ascenseur",
it: "Sollevare",
es: "Ascensor",
pl: "Podnoszenie",
uk: "\u041F\u0456\u0434\u0439\u043E\u043C!",
"zh-cn": "Lift"
},
von: {
en: "date of",
de: "Datum von",
ru: "\u0434\u0430\u0442\u0430",
pt: "data de",
nl: "datum van",
fr: "date de",
it: "data di",
es: "fecha de",
pl: "data",
uk: "\u0434\u0430\u0442\u0430",
"zh-cn": "date of"
}
};
}
});
// ../package.json
var version = "0.4.0";
// skiinfo/js/skiinfo.js
var translations = require_translations();
$.extend(true, systemDictionary, translations);
vis.binds["skiinfo"] = {
version,
debug: true,
showVersion: function() {
if (vis.binds["skiinfo"].version) {
console.log(`Version skiinfo: ${vis.binds["skiinfo"].version}`);
vis.binds["skiinfo"].version = null;
}
},
data: null,
sortarrows: {
0: " ",
1: "↓",
2: "↑"
},
browser: {
/**
* Asynchronously creates a widget for the specified widget ID, view, data, and style.
* If the widget element is not found, the function retries after a delay.
* Loads instance and skiinfo_oid information, initializes necessary data structures,
* retrieves ski data if not already available, and sets the selected country.
* Finally, it renders the widget.
*
* @param widgetID - The ID of the widget to create.
* @param view - The view in which the widget is being created.
* @param data - Data object containing skiinfo_oid and other relevant information.
* @param style - The style to apply to the widget.
*/
createWidget: function(widgetID, view, data, style) {
return __async(this, null, function* () {
var $div = $(`#${widgetID}`);
if (!$div.length) {
return setTimeout(function() {
vis.binds["skiinfo"].browser.createWidget(widgetID, view, data, style);
}, 100);
}
this.visSkiinfo = vis.binds["skiinfo"];
if (!data.skiinfo_oid || data.skiinfo_oid == "") {
return;
}
let [instance, skiinfo_oid] = this.visSkiinfo.getInstanceInfo(data.skiinfo_oid);
if (!skiinfo_oid && !instance) {
return;
}
this.visSkiinfo.debug && console.log("Load Data");
if (!this.visSkiinfo[instance]) {
this.visSkiinfo[instance] = {
data: null
};
}
if (!this.visSkiinfo[widgetID]) {
this.visSkiinfo[widgetID] = {
// 0=default,1=asc,2=desc
sortState: {
thname: 0,
thvalley: 0,
thmountain: 0,
thnew: 0,
thlift: 0,
thupdate: 0
}
};
}
this.visSkiinfo[widgetID].wdata = data;
this.visSkiinfo[widgetID].instance = instance;
if (!this.visSkiinfo[instance].data) {
this.visSkiinfo[instance].data = yield this.visSkiinfo.getServerSkiData(instance);
if (!this.visSkiinfo[instance].data.favorites) {
this.visSkiinfo[instance].data.favorites = [];
}
}
if (!this.visSkiinfo[widgetID].selectedCountry) {
yield this.setSelectedCountry(widgetID);
}
this.render(widgetID);
});
},
/**
* Renders the skiinfo widget for the specified widget ID.
* Constructs the HTML structure and style, including tables for countries, regions, and areas.
* Adds click event handlers to elements for interactivity.
*
* @param widgetID - The ID of the widget to render.
*/
render(widgetID) {
return __async(this, null, function* () {
this.visSkiinfo.debug && console.log(`render browser`);
let instance = this.visSkiinfo[widgetID].instance;
let favoritecolor = this.visSkiinfo[widgetID].wdata.favoritecolor || "red";
let text = "";
text += `<style>`;
text += `.skiinfo.${widgetID}.container {
`;
text += " display: flex; \n";
text += " height: 100%; \n";
text += "} \n";
text += `.skiinfo.${widgetID}.flexcontainer {
`;
text += " overflow: auto; \n";
text += " scrollbar-width: thin; \n";
text += " margin: 0px 0px 0px 2px; \n";
text += "} \n";
text += `.skiinfo.${widgetID}.countries {
`;
text += "} \n";
text += `.skiinfo.${widgetID}.countries.scroll {
`;
text += "} \n";
text += `.skiinfo.${widgetID} ul {
`;
text += " list-style-type: none; \n";
text += " padding: 0px; \n";
text += " margin: 0px; \n";
text += "} \n";
text += `.skiinfo.${widgetID} li {
`;
text += " border: solid 1px;\n";
text += " border-color: currentcolor;\n";
text += " padding: 2px 8px;\n";
text += " margin: 2px 0px;\n";
text += " cursor: pointer;\n";
text += "} \n";
text += `.skiinfo.${widgetID}.regions {
`;
text += "} \n";
text += `.skiinfo.${widgetID}.regions.scroll {
`;
text += "} \n";
text += `.skiinfo.${widgetID}.regions li.selected {
`;
text += " font-weight: bold; \n";
text += "} \n";
text += `.skiinfo.${widgetID}.areas .favorite {
`;
text += " cursor: pointer;\n";
text += " padding-right: 5px; \n";
text += "} \n";
text += `.skiinfo.${widgetID}.areas .tharea {
`;
text += " cursor: pointer;\n";
text += "} \n";
text += `.skiinfo.${widgetID}.areas .favorite.selected {
`;
text += ` color: ${favoritecolor};
`;
text += "} \n";
text += `.skiinfo.${widgetID} table {
`;
text += " white-space: nowrap; \n";
text += " border-collapse: separate; \n";
text += " border-spacing: 0px 2px; \n";
text += "} \n";
text += `.skiinfo.${widgetID} table tr {
`;
text += "} \n";
text += `.skiinfo.${widgetID} table td, .skiinfo.${widgetID} table th {
`;
text += " padding: 2px 8px; \n";
text += " border: solid 1px currentcolor; \n";
text += " border-left-width: 0px; \n";
text += " border-right-width: 0px; \n";
text += "} \n";
text += `.skiinfo.${widgetID} th {
`;
text += " text-align: left; \n";
text += "} \n";
text += `.skiinfo.${widgetID} td span.selected {
`;
text += " font-weight: bold; \n";
text += "} \n";
text += `.skiinfo.${widgetID} table td.txtr {
`;
text += " text-align: right;\n";
text += "} \n";
text += `.skiinfo.${widgetID} table td.txtl {
`;
text += " text-align: left;\n";
text += "} \n";
text += `.skiinfo.${widgetID}.countries table td, .skiinfo.${widgetID}.regions table td {
`;
text += " cursor: pointer;\n";
text += "} \n";
text += `.skiinfo.${widgetID} table td:first-child, .skiinfo.${widgetID} table th:first-child {
`;
text += " border-left-width: 1px; \n";
text += "} \n";
text += `.skiinfo.${widgetID} table td:last-child, .skiinfo.${widgetID} table th:last-child {
`;
text += " border-right-width: 1px; \n";
text += " padding-right: 7px; \n";
text += "} \n";
text += `</style>`;
text += `<div class="skiinfo ${widgetID} container">`;
text += ` <div class="skiinfo ${widgetID} flexcontainer countries">`;
text += ` <table>`;
text += ` <tr>`;
text += ` <th>${_("Land")}</th>`;
text += ` </tr>`;
this.visSkiinfo[instance].data.skiinfodata.map((country) => {
text += ` <tr>`;
text += ` <td><span
data-code="${country.code}"
data-widgetid="${widgetID}"
${country.code == this.visSkiinfo[widgetID].selectedCountry.code ? 'class="selected"' : ""}
>${country.name}</span></td>`;
text += ` </tr>`;
});
text += ` </table>`;
text += ` </div>`;
text += ` <div class="skiinfo ${widgetID} flexcontainer regions">`;
text += ` <table>`;
text += ` <tr>`;
text += ` <th>${_("Region")}</th>`;
text += ` </tr>`;
this.visSkiinfo[widgetID].selectedCountry.regions.map((region) => {
text += ` <tr>`;
text += ` <td><span
data-code="${region.code}"
data-widgetid="${widgetID}"
data-country="${this.visSkiinfo[widgetID].selectedCountry.code}"
${region.code == this.visSkiinfo[widgetID].selectedRegion.code ? 'class="selected"' : ""}
>${region.name}</span></td>`;
text += ` </tr>`;
});
text += ` </table>`;
text += ` </div>`;
text += ` <div class="skiinfo ${widgetID} flexcontainer areas">`;
text += ` <table>`;
text += ` <tr>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thname">${_("Area")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thname"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thvalley">${_("Tal")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thvalley"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thmountain">${_("Berg")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thmountain"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thnew">${_("Neu")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thnew"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thlift">${_("Lift")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thlift"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thupdate">${_("von")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thupdate"]]}</th>`;
text += ` </tr>`;
let sortkey = "";
let sortdir = 0;
for (const item in this.visSkiinfo[widgetID].sortState) {
if (this.visSkiinfo[widgetID].sortState[item] > 0) {
sortkey = item;
sortdir = this.visSkiinfo[widgetID].sortState[item];
}
}
const compareFn = (a, b) => {
let valA, valB, compareType;
switch (sortkey) {
case "thname":
compareType = "string";
valA = a.name;
valB = b.name;
break;
case "thvalley":
compareType = "number";
valA = a.snowValley;
valB = b.snowValley;
break;
case "thmountain":
compareType = "number";
valA = a.snowMountain;
valB = b.snowMountain;
break;
case "thnew":
compareType = "number";
valA = a.freshSnow;
valB = b.freshSnow;
break;
case "thlift":
compareType = "number";
if (a.liftsAll == 0) {
valA = Infinity;
} else {
valA = a.liftsAll / a.liftsOpen;
}
if (b.liftsAll == 0) {
valB = Infinity;
} else {
valB = b.liftsAll / b.liftsOpen;
}
[valA, valB] = [valB, valA];
break;
case "thupdate":
compareType = "date";
valA = a.lastUpdate;
valB = b.lastUpdate;
break;
default:
compareType = "nosort";
break;
}
switch (sortdir) {
case 1:
[valA, valB] = [valB, valA];
break;
case 2:
break;
default:
break;
}
switch (compareType) {
case "string":
return valA.localeCompare(valB);
case "number":
return valA - valB;
case "date":
return new Date(valA).getTime() - new Date(valB).getTime();
default:
return 0;
}
};
this.visSkiinfo[widgetID].selectedCountry.areas.filter((area) => area.region == this.visSkiinfo[widgetID].selectedRegion.code).sort(compareFn).map((area) => {
let selected = this.visSkiinfo[instance].data.favorites.findIndex(
(item) => item.country == this.visSkiinfo[widgetID].selectedCountry.code && item.area == area.code
) == -1 ? false : true;
text += ` <tr>`;
text += ` <td class="txtl"><span class="favorite ${selected ? "selected" : ""}" data-widgetid="${widgetID}" data-country="${this.visSkiinfo[widgetID].selectedCountry.code}" data-area="${area.code}">🟊</span>${area.name}</td>`;
text += ` <td class="txtr">${area.snowValley}</td>`;
text += ` <td class="txtr">${area.snowMountain}</td>`;
text += ` <td class="txtr">${area.freshSnow}</td>`;
text += ` <td class="txtr">${area.liftsOpen}/${area.liftsAll}</td>`;
text += ` <td class="txtl">${area.lastUpdate}</td>`;
text += ` </tr>`;
});
text += ` </table>`;
text += ` </div>`;
text += `</div>`;
$(`#${widgetID}`).html(text);
$(`.skiinfo.${widgetID}.countries td span`).click(function() {
return __async(this, null, function* () {
yield vis.binds["skiinfo"].browser.onClickCountry(this);
});
});
$(`.skiinfo.${widgetID}.regions td span`).click(function() {
return __async(this, null, function* () {
yield vis.binds["skiinfo"].browser.onClickRegion(this);
});
});
$(`.skiinfo.${widgetID} .tharea`).click(function() {
return __async(this, null, function* () {
yield vis.binds["skiinfo"].browser.onClickHeadArea(this);
});
});
$(`.skiinfo.${widgetID}.areas .favorite`).click(function() {
return __async(this, null, function* () {
yield vis.binds["skiinfo"].browser.onClickFavorite(this);
});
});
});
},
/**
* Event handler for clicking on a country.
*
* @param el The HTML element that was clicked.
* @returns Promise
*
* This function sets the selected country to the one that was clicked
* and then calls the render function to update the widget.
*/
onClickCountry: function(el) {
return __async(this, null, function* () {
let code = $(el).attr("data-code");
let widgetID = $(el).attr("data-widgetid");
this.visSkiinfo.debug && console.log(`onClickCountry ${widgetID} ${code}`);
yield this.setSelectedCountry(widgetID, code);
this.render(widgetID);
});
},
/**
* Event handler for clicking on a region.
*
* @param el The HTML element that was clicked.
* @returns Promise
*
* This function sets the selected region to the one that was clicked
* and then calls the render function to update the widget.
*/
onClickRegion: function(el) {
return __async(this, null, function* () {
let code = $(el).attr("data-code");
let countrycode = $(el).attr("data-country");
let widgetID = $(el).attr("data-widgetid");
this.visSkiinfo.debug && console.log(`onClickRegion ${widgetID} ${countrycode} ${code}`);
yield this.setSelectedRegion(widgetID, countrycode, code);
this.render(widgetID);
});
},
/**
* Event handler for clicking on a table header in the area list.
*
* @param el The HTML element that was clicked.
* @returns Promise
*
* This function toggles the sort order of the area list by the sort key
* that was clicked and then calls the render function to update the
* widget.
*/
onClickHeadArea: function(el) {
return __async(this, null, function* () {
let sortkey = $(el).attr("data-sort");
let widgetID = $(el).attr("data-widgetid");
this.visSkiinfo.debug && console.log(`onClickHeadArea ${widgetID} ${sortkey}`);
vis.binds["skiinfo"].toggleSort(widgetID, sortkey);
this.render(widgetID);
});
},
/**
* Event handler for clicking on a favorite icon.
*
* @param el The HTML element that was clicked.
* @returns Promise
*
* This function toggles the favorite status of the clicked area and then
* calls the render function to update the widget.
*/
onClickFavorite: function(el) {
return __async(this, null, function* () {
let widgetID = $(el).attr("data-widgetid");
let instance = this.visSkiinfo[widgetID].instance;
let country = $(el).attr("data-country");
let area = $(el).attr("data-area");
if (!this.visSkiinfo[instance].data.favorites) {
this.visSkiinfo[instance].data.favorites = [];
}
let index = this.visSkiinfo[instance].data.favorites.findIndex(
(item) => item.country == country && item.area == area
);
if (index !== -1) {
this.visSkiinfo.debug && console.log(`onClickFavorite ${widgetID} ${country} ${area} fav deleted`);
this.visSkiinfo[instance].data = yield this.visSkiinfo.delServerFavorite(
this.visSkiinfo[widgetID].instance,
country,
area
);
} else {
this.visSkiinfo.debug && console.log(`onClickFavorite ${widgetID} ${country} ${area} fav added`);
this.visSkiinfo[instance].data = yield this.visSkiinfo.addServerFavorite(
this.visSkiinfo[widgetID].instance,
country,
area
);
}
this.render(widgetID);
});
},
/**
* Sets the selected country of the widget to the given country code.
*
* If the country code is not given, the first country in the list is selected.
*
* This function also sets the selected region to the first region of the selected country.
*
* @param widgetID The ID of the widget for which the selected country is changed.
* @param countrycode The code of the country to select.
* @returns Promise
*/
setSelectedCountry: function(widgetID, countrycode) {
return __async(this, null, function* () {
let instance = this.visSkiinfo[widgetID].instance;
this.visSkiinfo.debug && console.log(`setSelectedCountry ${widgetID} ${countrycode}`);
if (countrycode) {
this.visSkiinfo[widgetID].selectedCountry = this.visSkiinfo[instance].data.skiinfodata.find(
(country) => country.code == countrycode
);
if (this.visSkiinfo[widgetID].selectedCountry.loaded == false) {
this.visSkiinfo[instance].data = yield this.visSkiinfo.getServerCountryData(
this.visSkiinfo[widgetID].instance,
this.visSkiinfo[widgetID].selectedCountry.code
);
this.visSkiinfo[widgetID].selectedCountry = this.visSkiinfo[instance].data.skiinfodata.find(
(country) => country.code == countrycode
);
}
this.visSkiinfo[widgetID].selectedRegion = this.visSkiinfo[widgetID].selectedCountry.regions[0];
} else {
this.visSkiinfo[widgetID].selectedCountry = this.visSkiinfo[instance].data.skiinfodata[0];
this.visSkiinfo[widgetID].selectedRegion = this.visSkiinfo[widgetID].selectedCountry.regions[0];
}
});
},
/**
* Sets the selected region of the widget to the given region code.
*
* If the country code is not given, the currently selected country is used.
*
* If the region code is not given, the first region of the selected country is selected.
*
* This function also sets the selected country if the given country code is not the same as the currently selected country.
*
* @param widgetID The ID of the widget for which the selected region is changed.
* @param countrycode The code of the country which the region belongs to.
* @param regioncode The code of the region to select.
* @returns Promise
*/
setSelectedRegion: function(widgetID, countrycode, regioncode) {
return __async(this, null, function* () {
let instance = this.visSkiinfo[widgetID].instance;
this.visSkiinfo.debug && console.log(`setSelectedRegion ${widgetID} ${countrycode} ${regioncode}`);
if (countrycode) {
this.visSkiinfo[widgetID].selectedCountry = this.visSkiinfo[instance].data.skiinfodata.find(
(country) => country.code == countrycode
);
if (this.visSkiinfo[widgetID].selectedCountry.loaded == false) {
this.visSkiinfo[instance].data = yield this.visSkiinfo.getServerCountryData(
this.visSkiinfo[widgetID].instance,
this.visSkiinfo[widgetID].selectedCountry.code
);
this.visSkiinfo[widgetID].selectedCountry = this.visSkiinfo[instance].data.skiinfodata.find(
(country) => country.code == countrycode
);
}
} else {
this.visSkiinfo[widgetID].selectedCountry = this.visSkiinfo[instance].data.skiinfodata[0];
}
if (regioncode) {
this.visSkiinfo[widgetID].selectedRegion = this.visSkiinfo[widgetID].selectedCountry.regions.find(
(region) => region.code == regioncode
);
if (this.visSkiinfo[widgetID].selectedRegion.loaded == false) {
this.visSkiinfo[instance].data = yield this.visSkiinfo.getServerRegionData(
this.visSkiinfo[widgetID].instance,
this.visSkiinfo[widgetID].selectedCountry.code,
this.visSkiinfo[widgetID].selectedRegion.code
);
this.visSkiinfo[widgetID].selectedRegion = this.visSkiinfo[widgetID].selectedCountry.regions.find(
(region) => region.code == regioncode
);
}
} else {
this.visSkiinfo[widgetID].selectedRegion = this.visSkiinfo[widgetID].selectedCountry.regions[0];
}
});
}
},
favorites: {
/**
* Creates a widget for the specified widget ID, view, data, and style.
* If the widget element is not found, the function retries after a delay.
* Loads instance and skiinfo_oid information, initializes necessary data structures,
* retrieves ski data if not already available, and sets the selected country.
* Finally, it renders the widget.
*
* @param widgetID - The ID of the widget to create.
* @param view - The view in which the widget is being created.
* @param data - Data object containing skiinfo_oid and other relevant information.
* @param style - The style to apply to the widget.
*/
createWidget: function(widgetID, view, data, style) {
return __async(this, null, function* () {
var $div = $(`#${widgetID}`);
if (!$div.length) {
return setTimeout(function() {
vis.binds["skiinfo"].favorites.createWidget(widgetID, view, data, style);
}, 100);
}
this.visSkiinfo = vis.binds["skiinfo"];
if (!data.skiinfo_oid || data.skiinfo_oid == "") {
return;
}
let [instance, skiinfo_oid] = this.visSkiinfo.getInstanceInfo(data.skiinfo_oid);
if (!skiinfo_oid && !instance) {
return;
}
if (!this.visSkiinfo[widgetID]) {
this.visSkiinfo[widgetID] = {
// 0=default,1=asc,2=desc
sortState: {
thname: 0,
thvalley: 0,
thmountain: 0,
thnew: 0,
thlift: 0,
thupdate: 0
}
};
}
this.visSkiinfo[widgetID].wdata = data;
this.visSkiinfo[widgetID].instance = instance;
if (!this.visSkiinfo[instance].data) {
this.visSkiinfo[instance].data = yield this.visSkiinfo.getServerSkiData(instance);
if (!this.visSkiinfo[instance].data.favorites) {
this.visSkiinfo[instance].data.favorites = [];
}
}
let config = data["skiinfo_oid"] ? JSON.parse(vis.states.attr(`${data["skiinfo_oid"]}.val`)) : [];
this.visSkiinfo[instance].data.favorites = config.favorites || [];
function onChange(e, newVal) {
vis.binds["skiinfo"][instance].data.favorites = JSON.parse(newVal).favorites;
vis.binds["skiinfo"].favorites.render(widgetID);
}
if (data.skiinfo_oid) {
vis.states.bind(`${data.skiinfo_oid}.val`, onChange);
$div.data("bound", [`${data.skiinfo_oid}.val`]);
$div.data("bindHandler", onChange);
}
this.render(widgetID);
});
},
/**
* renders the skiinfo widget for the specified widget ID
* constructs the HTML structure and style, including tables for countries, regions, and areas
* adds click event handlers to elements for interactivity
*
* @param widgetID - The ID of the widget to render.
*/
render(widgetID) {
return __async(this, null, function* () {
this.visSkiinfo.debug && console.log(`favorites render ${widgetID}`);
let instance = this.visSkiinfo[widgetID].instance;
let favoritecolor = this.visSkiinfo[widgetID].wdata.favoritecolor || "red";
let text = "";
text += `<style>`;
text += `.skiinfo.${widgetID}.container {
`;
text += " display: flex; \n";
text += " height: 100%; \n";
text += "} \n";
text += `.skiinfo.${widgetID}.flexcontainer {
`;
text += " overflow: auto; \n";
text += " scrollbar-width: thin; \n";
text += " margin: 0px 0px 0px 2px; \n";
text += "} \n";
text += `.skiinfo.${widgetID}.areas .favorite {
`;
text += " cursor: pointer;\n";
text += " padding-right: 5px; \n";
text += "} \n";
text += `.skiinfo.${widgetID}.areas .tharea {
`;
text += " cursor: pointer;\n";
text += "} \n";
text += `.skiinfo.${widgetID}.areas .favorite.selected {
`;
text += ` color: ${favoritecolor};
`;
text += "} \n";
text += `.skiinfo.${widgetID} table {
`;
text += " white-space: nowrap; \n";
text += " border-collapse: separate; \n";
text += " border-spacing: 0px 2px; \n";
text += "} \n";
text += `.skiinfo.${widgetID} table tr {
`;
text += "} \n";
text += `.skiinfo.${widgetID} table td, .skiinfo.${widgetID} table th {
`;
text += " padding: 2px 8px; \n";
text += " border: solid 1px currentcolor; \n";
text += " border-left-width: 0px; \n";
text += " border-right-width: 0px; \n";
text += "} \n";
text += `.skiinfo.${widgetID} th {
`;
text += " text-align: left; \n";
text += "} \n";
text += `.skiinfo.${widgetID} td.selected {
`;
text += " font-weight: bold; \n";
text += "} \n";
text += `.skiinfo.${widgetID} table td.txtr {
`;
text += " text-align: right;\n";
text += "} \n";
text += `.skiinfo.${widgetID} table td.txtl {
`;
text += " text-align: left;\n";
text += "} \n";
text += `.skiinfo.${widgetID} table td:first-child, .skiinfo.${widgetID} table th:first-child {
`;
text += " border-left-width: 1px; \n";
text += "} \n";
text += `.skiinfo.${widgetID} table td:last-child, .skiinfo.${widgetID} table th:last-child {
`;
text += " border-right-width: 1px; \n";
text += " padding-right: 7px; \n";
text += "} \n";
text += `</style>`;
text += `<div class="skiinfo ${widgetID} container">`;
text += ` <div class="skiinfo ${widgetID} flexcontainer areas">`;
text += ` <table>`;
text += ` <tr>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thname">${_("Area")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thname"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thvalley">${_("Tal")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thvalley"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thmountain">${_("Berg")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thmountain"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thnew">${_("Neu")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thnew"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thlift">${_("Lift")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thlift"]]}</th>`;
text += ` <th class="thsort tharea" data-widgetid="${widgetID}" data-sort="thupdate">${_("von")} ${this.visSkiinfo.sortarrows[this.visSkiinfo[widgetID].sortState["thupdate"]]}</th>`;
text += ` </tr>`;
let sortkey = "";
let sortdir = 0;
for (const item in this.visSkiinfo[widgetID].sortState) {
if (this.visSkiinfo[widgetID].sortState[item] > 0) {
sortkey = item;
sortdir = this.visSkiinfo[widgetID].sortState[item];
}
}
const compareFn = (a, b) => {
let valA, valB, compareType;
switch (sortkey) {
case "thname":
compareType = "string";
valA = a.name;
valB = b.name;
break;
case "thvalley":
compareType = "number";
valA = a.snowValley;
valB = b.snowValley;
break;
case "thmountain":
compareType = "number";
valA = a.snowMountain;
valB = b.snowMountain;
break;
case "thnew":
compareType = "number";
valA = a.freshSnow;
valB = b.freshSnow;
break;
case "thlift":
compareType = "number";
if (a.liftsAll == 0) {
valA = Infinity;
} else {
valA = a.liftsAll / a.liftsOpen;
}
if (b.liftsAll == 0) {
valB = Infinity;
} else {
valB = b.liftsAll / b.liftsOpen;
}
[valA, valB] = [valB, valA];
break;
case "thupdate":
compareType = "date";
valA = a.lastUpdate;
valB = b.lastUpdate;
break;
default:
compareType = "nosort";
break;
}
switch (sortdir) {
case 1:
[valA, valB] = [valB, valA];
break;
case 2:
break;
default:
break;
}
switch (compareType) {
case "string":
return valA.localeCompare(valB);
case "number":
return valA - valB;
case "date":
return new Date(valA).getTime() - new Date(valB).getTime();
default:
return 0;
}
};
let areas = [];
this.visSkiinfo[instance].data.favorites.forEach((favorite) => {
const country = this.visSkiinfo[instance].data.skiinfodata.find(
(country2) => country2.code === favorite.country && country2.areas.find((area) => area.code === favorite.area)
);
if (country) {
areas.push(country.areas.find((area) => area.code === favorite.area));
}
});
areas.sort(compareFn).map((area) => {
text += ` <tr>`;
text += ` <td class="txtl"><span class="favorite selected" data-widgetid="${widgetID}" data-country="${area.country}" data-area="${area.code}">🟊</span>${area.name}</td>`;
text += ` <td class="txtr">${area.snowValley}</td>`;
text += ` <td class="txtr">${area.snowMountain}</td>`;
text += ` <td class="txtr">${area.freshSnow}</td>`;
text += ` <td class="txtr">${area.liftsOpen}/${area.liftsAll}</td>`;
text += ` <td class="txtl">${area.lastUpdate}</td>`;
text += ` </tr>`;
});
text += ` </table>`;
text += ` </div>`;
text += `</div>`;
$(`#${widgetID}`).html(text);
$(`.skiinfo.${widgetID} .tharea`).click(function() {
return __async(this, null, function* () {
yield vis.binds["skiinfo"].favorites.onClickHeadArea(this);
});
});
$(`.skiinfo.${widgetID}.areas .favorite`).click(function() {
return __async(this, null, function* () {
yield vis.binds["skiinfo"].favorites.onClickFavorite(this);
});
});
});
},
/**
* Event handler for clicking on a table header in the area list.
*
* @param el The HTML element that was clicked.
* @returns Promise
*
* This function toggles the sort order of the area list by the sort key
* that was clicked and then calls the render function to update the
* widget.
*/
onClickHeadArea: function(el) {
return __async(this, null, function* () {
let sortkey = $(el).attr("data-sort");
let widgetID = $(el).attr("data-widgetid");
this.visSkiinfo.debug && console.log(`onClickHeadArea ${widgetID} ${sortkey}`);
vis.binds["skiinfo"].toggleSort(widgetID, sortkey);
this.render(widgetID);
});
},
/**
* Event handler for clicking on a favorite icon.
*
* @param el The HTML element that was clicked.
* @returns Promise
*
* This function toggles the favorite status of the clicked area and then
* calls the render function to update the widget.
*/
onClickFavorite: function(el) {
return __async(this, null, function* () {
let widgetID = $(el).attr("data-widgetid");
let instance = this.visSkiinfo[widgetID].instance;
let country = $(el).attr("data-country");
let area = $(el).attr("data-area");
if (!this.visSkiinfo[instance].data.favorites) {
this.visSkiinfo[instance].data.favorites = [];
}
let index = this.visSkiinfo[instance].data.favorites.findIndex(
(item) => item.country == country && item.area == area
);
if (index !== -1) {
this.visSkiinfo.debug && console.log(`onClickFavorite ${widgetID} ${country} ${area} fav deleted`);
this.visSkiinfo[instance].data = yield this.visSkiinfo.delServerFavorite(
this.visSkiinfo[widgetID].instance,
country,
area
);
} else {
this.visSkiinfo.debug && console.log(`onClickFavorite ${widgetID} ${country} ${area} fav added`);
this.visSkiinfo[instance].data = yield this.visSkiinfo.addServerFavorite(
this.visSkiinfo[widgetID].instance,
country,
area
);
}
});
}
},
/**
* Toggles the sort state for a specified column in the skiinfo widget.
*
* The function iterates through the sort states of all columns, resetting
* those not matching the provided sort key to their default state (0).
* The sort state of the specified sort key is then incremented in a cyclic
* manner through the states: 0 (default), 1 (ascending), and 2 (descending).
*
* @param widgetID - The ID of the widget whose sort state is being toggled.
* @param sortkey - The key representing the column to toggle the sort state for.
*/
toggleSort: function(widgetID, sortkey) {
this.visSkiinfo.debug && console.log(`toggleSort ${widgetID} ${sortkey}`);
for (const item in vis.binds["skiinfo"][widgetID].sortState) {
if (item !== sortkey) {
vis.binds["skiinfo"][widgetID].sortState[item] = 0;
}
}
vis.binds["skiinfo"][widgetID].sortState[sortkey] = (vis.binds["skiinfo"][widgetID].sortState[sortkey] + 1) % 3;
},
/**
* Sends a request to the server to fetch the current ski data for all countries, regions, and areas.
*
* @param instance - The instance ID of the adapter.
* @returns - A promise that resolves to the ski data.
*/
getServerSkiData: function(instance) {
return __async(this, null, function* () {
this.visSkiinfo.debug && console.log(`getServerSkiData request`);
return yield this.sendToAsync(instance, "getServerSkiData", {});
});
},
/**
* Sends a request to the server to fetch the current ski data for a specific country.
*
* @param instance - The instance ID of the adapter.
* @param countrycode - The code of the country to fetch data for.
* @returns - A promise that resolves to the ski data.
*/
getServerCountryData: function(instance, countrycode) {
return __async(this, null, function* () {
this.visSkiinfo.debug && console.log(`getServerCountryData request`);
return yield this.sendToAsync(instance, "getServerCountryData", {
countrycode
});
});
},
/**
* Sends a request to the server to fetch the current ski data for a specific region.
*
* @param instance - The instance ID of the adapter.
* @param countrycode - The code of the country to fetch data for.
* @param regioncode - The code of the region to fetch data for.
* @returns - A promise that resolves to the ski data.
*/
getServerRegionData: function(instance, countrycode, regioncode) {
return __async(this, null, function* () {
this.visSkiinfo.debug && console.log(`getServerRegionData request`);
return yield this.sendToAsync(instance, "getServerRegionData", {
countrycode,
regioncode
});
});
},
/**
* Sends a request to the server to add a favorite ski area.
*
* @param instance - The instance ID of the adapter.
* @param countrycode - The code of the country to add the favorite for.
* @param areacode - The code of the area to add as a favorite.
* @returns - A promise that resolves to the ski data.
*/
addServerFavorite: function(instance, countrycode, areacode) {
return __async(this, null, function* () {
this.visSkiinfo.debug && console.log(`addServerFavorite request`);
return yield this.sendToAsync(instance, "addServerFavorite", {
countrycode,
areacode
});
});
},
/**
* Sends a request to the server to remove a favorite ski area.
*
* @param instance - The instance ID of the adapter.
* @param countrycode - The code of the country to remove the favorite for.
* @param areacode - The code of the area to remove as a favorite.
* @returns - A promise that resolves to the ski data.
*/
delServerFavorite: function(instance, countrycode, areacode) {
return __async(this, null, function* () {
this.visSkiinfo.debug && console.log(`delServerFavorite request`);
return yield this.sendToAsync(instance, "delServerFavorite", {
countrycode,
areacode
});
});
},
/**
* Sends a request to the server and returns a promise that resolves when the server responds.
*
* @param instance - The instance ID of the adapter.
* @param command - The command to send to the server.
* @param sendData - The data to send to the server.
* @returns - A promise that resolves to the response data.
*/
sendToAsync: function(instance, command, sendData) {
this.visSkiinfo.debug && console.log(`sendToAsync ${command} ${JSON.stringify(sendData)}`);
return new Promise((resolve, reject) => {
try {
vis.conn.sendTo(instance, command, sendData, function(receiveData) {
resolve(receiveData);
});
} catch (error) {
reject(error);
}
});
},
/**
* Extracts and returns the instance and skiinfo ID from a given object ID.
*
* This function splits the provided object ID (oid) into parts and forms
* two identifiers: the instance and the skiinfo ID. If the oid contains
* fewer than two parts, it returns [null, null].
*
* @param oid - The object ID to process, expected to be a string with dot-separated segments.
* @returns An array with two elements:
* - The first element is the instance identifier formed by joining the first two parts.
* - The second element is the skiinfo ID formed by joining the first three parts.
* If the oid has fewer than two parts, returns [null, null].
*/
getInstanceInfo: function(oid) {
this.visSkiinfo = vis.binds["skiinfo"];
this.visSkiinfo.debug && console.log("getInstanceInfo");
let idParts = oid.trim().split(".");
if (idParts.length < 2) {
return [null, null];
}
return [
idParts.slice(0, 2).join("."),
// instance
idParts.slice(0, 3).join(".")
// skiinfo id
];
}
};
vis.binds["skiinfo"].showVersion();
})();
//# sourceMappingURL=skiinfo-dist.js.map