From 802506294d0d63454e34926cb631ec84c32c5610 Mon Sep 17 00:00:00 2001 From: Claus Hagen Date: Mon, 29 Jan 2024 13:30:59 +0100 Subject: [PATCH 1/6] Additional views and error fixes --- .../colors/source/src/assets/css/style.css | 2 +- .../source/src/assets/js/processMessages.ts | 59 +++- .../source/src/assets/js/themeConfig.ts | 55 ++++ .../components/batteryList/BatteryList.vue | 75 +++-- .../chargePointList/CPChargePoint.vue | 5 +- .../chargePointList/ChargePointList.vue | 16 +- .../cpConfig/CPChargeConfigPanel.vue | 3 +- .../cpSimpleList/CPSimpleList.vue | 15 +- .../src/components/chargePointList/model.ts | 9 + .../src/components/counterList/ClCounter.vue | 70 +++++ .../components/counterList/CounterList.vue | 124 ++------ .../src/components/counterList/model.ts | 58 ++-- .../components/energyMeter/EnergyMeter.vue | 33 +- .../components/powerGraph/PGUsageGraph.vue | 1 - .../powerGraph/processDayGraphData.ts | 5 +- .../src/components/priceChart/PriceChart.vue | 1 - .../source/src/components/priceChart/model.ts | 6 + .../components/priceChart/processMessages.ts | 8 +- .../source/src/components/shared/InfoItem.vue | 38 ++- .../source/src/components/shared/WBWidget.vue | 2 +- .../components/vehicleList/VehicleList.vue | 43 +++ .../src/components/vehicleList/VlVehicle.vue | 53 ++++ .../src/components/vehicleList/model.ts | 44 +++ .../colors/source/src/views/ColorsTheme.vue | 83 ++++-- .../colors/source/src/views/ThemeSettings.vue | 282 +++++++++++------- .../web_themes/colors/source/yarn.lock | 25 +- .../colors/web/assets/index-9692d2c9.js | 2 - .../colors/web/assets/index-bfa678dd.js | 6 + ...{index-ddfbfd60.css => index-ecfa9611.css} | 4 +- ...{vendor-6b0aaf61.js => vendor-6c3d972a.js} | 6 +- .../modules/web_themes/colors/web/index.html | 6 +- 31 files changed, 779 insertions(+), 360 deletions(-) create mode 100755 packages/modules/web_themes/colors/source/src/components/counterList/ClCounter.vue create mode 100755 packages/modules/web_themes/colors/source/src/components/vehicleList/VehicleList.vue create mode 100755 packages/modules/web_themes/colors/source/src/components/vehicleList/VlVehicle.vue create mode 100755 packages/modules/web_themes/colors/source/src/components/vehicleList/model.ts delete mode 100644 packages/modules/web_themes/colors/web/assets/index-9692d2c9.js create mode 100644 packages/modules/web_themes/colors/web/assets/index-bfa678dd.js rename packages/modules/web_themes/colors/web/assets/{index-ddfbfd60.css => index-ecfa9611.css} (72%) rename packages/modules/web_themes/colors/web/assets/{vendor-6b0aaf61.js => vendor-6c3d972a.js} (75%) diff --git a/packages/modules/web_themes/colors/source/src/assets/css/style.css b/packages/modules/web_themes/colors/source/src/assets/css/style.css index f834e1c4da..d7c4b38437 100644 --- a/packages/modules/web_themes/colors/source/src/assets/css/style.css +++ b/packages/modules/web_themes/colors/source/src/assets/css/style.css @@ -192,7 +192,7 @@ body>.container-fluid { --color-subframe: lightgrey; --color-fg: black; --color-scale: lightgrey; - --color-title: black; + --color-title: rgba(0, 0, 0, 0.644); --padding-widget: 5px; --fontCol: rgba(255, 255, 255, 0.82); --gridCol: rgba(255, 255, 255, 0.82); diff --git a/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts b/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts index b93652b01c..8c6ac52c8c 100755 --- a/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts @@ -24,6 +24,8 @@ import { processVehicleTemplateMessages, } from '@/components/chargePointList/processMessages' import { processSmarthomeMessages } from '@/components/smartHome/processMessages' +import { addCounter, counters } from '@/components/counterList/model' +import { mqttClientId } from './mqttClient' const topicsToSubscribe = [ 'openWB/counter/#', @@ -35,6 +37,7 @@ const topicsToSubscribe = [ 'openWB/optional/et/#', 'openWB/system/#', 'openWB/LegacySmartHome/#', + 'openWB/command/#', ] export function msgInit() { mqttRegister(processMqttMessage) @@ -74,34 +77,51 @@ function processMqttMessage(topic: string, payload: Buffer) { } else if (topic.match(/^openwb\/optional\/et\//i)) { processEtProviderMessages(topic, message) } // else if ( mqttTopic.match( /^openwb\/global\//i) ) { processGlobalMessages(mqttTopic, message); } - //else if (topic.match(/^openwb\/system\//i)) { - // processSystemMessages(topic, message) - //} else if ( mqttTopic.match( /^openwb\/verbraucher\//i) ) { processVerbraucherMessages(mqttTopic, message); } + else if (topic.match(/^openwb\/system\//i)) { + processSystemMessages(topic, message) + } // else if ( mqttTopic.match( /^openwb\/verbraucher\//i) ) { processVerbraucherMessages(mqttTopic, message); } // else if ( mqttTopic.match( /^openwb\/hook\//i) ) { processHookMessages(mqttTopic, message); } // else if ( mqttTopic.match( /^openwb\/SmartHome\/Devices\//i) ) { processSmartHomeDevicesMessages(mqttTopic, message); } else if (topic.match(/^openwb\/LegacySmartHome\//i)) { processSmarthomeMessages(topic, message) + } else if (topic.match(/^openwb\/command\//i)) { + processCommandMessages(topic, message) } + // else if ( mqttTopic.match( /^openwb\/config\/get\/sofort\/lp\//i) ) { processSofortConfigMessages(mqttTopic, message); } } function processCounterMessages(topic: string, message: string) { const elements = topic.split('/') - if (+elements[2] == globalData.evuId) { + const id = +elements[2] + if (id == globalData.evuId) { processEvuMessages(topic, message) } else if (elements[3] == 'config') { // console.warn('Ignored counter config message') - } else { + } + if (elements[3] == 'get') { switch (elements[4]) { case 'power': + counters[id].power = +message + break case 'config': + break case 'fault_str': + break case 'fault_state': + break case 'power_factors': + break case 'imported': + break case 'exported': + break case 'frequency': - case 'daily_yield_import': - case 'daily_yield_export': + break + case 'daily_imported': + counters[id].energy_imported = +message + break + case 'daily_exported': + counters[id].energy_exported = +message break default: // console.warn('Ignored COUNTER message: ' + topic) @@ -138,6 +158,7 @@ function processHierarchy(hierarchy: Hierarchy) { switch (hierarchy.type) { case 'counter': // console.info('counter in hierachy: ' + hierarchy.id) + addCounter(hierarchy.id, hierarchy.type) break case 'cp': addChargePoint(hierarchy.id) @@ -152,6 +173,7 @@ function processHierarchy(hierarchy: Hierarchy) { default: // console.warn('Ignored Hierarchy type: ' + hierarchy.type) } + // recursively process the hierarchy hierarchy.children.forEach((element) => processHierarchy(element)) } @@ -203,3 +225,26 @@ function processEvuMessages(topic: string, message: string) { default: } } + +function processSystemMessages(topic: string, message: string) { + if ( + topic.match(/^openWB\/system\/device\/[0-9]+\/component\/[0-9]+\/config$/i) + ) { + const config = JSON.parse(message) + if (config.type == 'counter') { + counters[config.id].name = config.name + } + } +} + +function processCommandMessages(topic: string, message: string) { + const tokens = topic.split('/') + if (topic.match(/^openWB\/command\/[a-z]+\/error$/i)) { + if (tokens[2] == mqttClientId()) { + const err = JSON.parse(message) + console.error( + `Error message from openWB: \nCommand: ${err.command}\nData: JSON.stringify(err.data)\nError:\n ${err.error}`, + ) + } + } +} diff --git a/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts b/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts index b4d83a6bb4..519bb0adeb 100644 --- a/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts @@ -21,12 +21,15 @@ export class Config { private _decimalPlaces = 1 private _showQuickAccess = true private _simpleCpList = false + private _shortCpList = 'no' private _showAnimations = true private _preferWideBoxes = false private _maxPower = 4000 private _fluidDisplay = false private _showClock = 'no' private _showButtonBar = true + private _showCounters = false + private _showVehicles = false private _debug: boolean = false isEtEnabled: boolean = false etPrice: number = 20.5 @@ -129,6 +132,16 @@ export class Config { setSimpleCpList(show: boolean) { this._simpleCpList = show } + get shortCpList() { + return this._shortCpList + } + set shortCpList(show: string) { + this._shortCpList = show + savePrefs() + } + setShortCpList(show: string) { + this._shortCpList = show + } get showAnimations() { return this._showAnimations } @@ -184,6 +197,7 @@ export class Config { } set debug(on: boolean) { this._debug = on + savePrefs() } setDebug(on: boolean) { this._debug = on @@ -198,6 +212,26 @@ export class Config { setShowButtonBar(show: boolean) { this._showButtonBar = show } + get showCounters() { + return this._showCounters + } + set showCounters(show: boolean) { + this._showCounters = show + savePrefs() + } + setShowCounters(show: boolean) { + this._showCounters = show + } + get showVehicles() { + return this._showVehicles + } + set showVehicles(show: boolean) { + this._showVehicles = show + savePrefs() + } + setShowVehicles(show: boolean) { + this._showVehicles = show + } } export const globalConfig = reactive(new Config()) export function initConfig() { @@ -329,11 +363,15 @@ interface Preferences { maxPow?: number showQA?: boolean simpleCP?: boolean + shortCP?: string animation?: boolean wideB?: boolean fluidD?: boolean clock?: string showButtonBar?: boolean + showCounters?: boolean + showVehicles?: boolean + debug?: boolean } function writeCookie() { @@ -351,11 +389,16 @@ function writeCookie() { prefs.maxPow = globalConfig.maxPower prefs.showQA = globalConfig.showQuickAccess prefs.simpleCP = globalConfig.simpleCpList + prefs.shortCP = globalConfig.shortCpList prefs.animation = globalConfig.showAnimations prefs.wideB = globalConfig.preferWideBoxes prefs.fluidD = globalConfig.fluidDisplay prefs.clock = globalConfig.showClock prefs.showButtonBar = globalConfig.showButtonBar + prefs.showCounters = globalConfig.showCounters + prefs.showVehicles = globalConfig.showVehicles + prefs.debug = globalConfig.debug + document.cookie = 'openWBColorTheme=' + JSON.stringify(prefs) + '; max-age=16000000' } @@ -405,6 +448,9 @@ function readCookie() { if (prefs.simpleCP !== undefined) { globalConfig.setSimpleCpList(prefs.simpleCP) } + if (prefs.shortCP !== undefined) { + globalConfig.setShortCpList(prefs.shortCP) + } if (prefs.animation != undefined) { globalConfig.setShowAnimations(prefs.animation) } @@ -420,5 +466,14 @@ function readCookie() { if (prefs.showButtonBar !== undefined) { globalConfig.setShowButtonBar(prefs.showButtonBar) } + if (prefs.showCounters !== undefined) { + globalConfig.setShowCounters(prefs.showCounters) + } + if (prefs.showVehicles !== undefined) { + globalConfig.setShowVehicles(prefs.showVehicles) + } + if (prefs.debug !== undefined) { + globalConfig.setDebug(prefs.debug) + } } } diff --git a/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue b/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue index f2937ffd87..4a496cb6a0 100755 --- a/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue +++ b/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue @@ -2,46 +2,54 @@ Hagen */ @@ -72,12 +80,15 @@ const powerstring = computed(() => { .battery-color { color: var(--color-battery); } + .fg-color { color: var(--color-fg); } + .menu-color { color: var(--color-menu); } + .todaystring { color: var(--color-menu); } diff --git a/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue b/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue index b1da8a1de1..9a460bca93 100755 --- a/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue +++ b/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue @@ -176,7 +176,10 @@ /> -
+
{{ diff --git a/packages/modules/web_themes/colors/source/src/components/chargePointList/ChargePointList.vue b/packages/modules/web_themes/colors/source/src/components/chargePointList/ChargePointList.vue index d2cfe2b5be..89810d02dd 100755 --- a/packages/modules/web_themes/colors/source/src/components/chargePointList/ChargePointList.vue +++ b/packages/modules/web_themes/colors/source/src/components/chargePointList/ChargePointList.vue @@ -1,7 +1,7 @@ diff --git a/packages/modules/web_themes/colors/source/src/components/chargePointList/cpConfig/CPChargeConfigPanel.vue b/packages/modules/web_themes/colors/source/src/components/chargePointList/cpConfig/CPChargeConfigPanel.vue index 9e30a38ed2..fd0a39ae47 100755 --- a/packages/modules/web_themes/colors/source/src/components/chargePointList/cpConfig/CPChargeConfigPanel.vue +++ b/packages/modules/web_themes/colors/source/src/components/chargePointList/cpConfig/CPChargeConfigPanel.vue @@ -56,7 +56,7 @@ () diff --git a/packages/modules/web_themes/colors/source/src/components/chargePointList/cpSimpleList/CPSimpleList.vue b/packages/modules/web_themes/colors/source/src/components/chargePointList/cpSimpleList/CPSimpleList.vue index bde3423d2f..3abd6c69a6 100755 --- a/packages/modules/web_themes/colors/source/src/components/chargePointList/cpSimpleList/CPSimpleList.vue +++ b/packages/modules/web_themes/colors/source/src/components/chargePointList/cpSimpleList/CPSimpleList.vue @@ -1,6 +1,14 @@ + + diff --git a/packages/modules/web_themes/colors/source/src/components/chargePointList/cpSimpleList/CpsListItem2.vue b/packages/modules/web_themes/colors/source/src/components/chargePointList/cpSimpleList/CpsListItem2.vue new file mode 100755 index 0000000000..64328a3671 --- /dev/null +++ b/packages/modules/web_themes/colors/source/src/components/chargePointList/cpSimpleList/CpsListItem2.vue @@ -0,0 +1,387 @@ + + + + + diff --git a/packages/modules/web_themes/colors/source/src/components/shared/InfoItem.vue b/packages/modules/web_themes/colors/source/src/components/shared/InfoItem.vue index 74d7cb0d60..3b69b0548a 100755 --- a/packages/modules/web_themes/colors/source/src/components/shared/InfoItem.vue +++ b/packages/modules/web_themes/colors/source/src/components/shared/InfoItem.vue @@ -1,9 +1,9 @@ diff --git a/packages/modules/web_themes/colors/source/src/components/shared/WbWidgetFlex.vue b/packages/modules/web_themes/colors/source/src/components/shared/WbWidgetFlex.vue index 2b65237a46..2af3cbfd63 100755 --- a/packages/modules/web_themes/colors/source/src/components/shared/WbWidgetFlex.vue +++ b/packages/modules/web_themes/colors/source/src/components/shared/WbWidgetFlex.vue @@ -1,6 +1,6 @@ -
+
diff --git a/packages/modules/web_themes/colors/source/src/components/powerGraph/model.ts b/packages/modules/web_themes/colors/source/src/components/powerGraph/model.ts index 672c73d328..db8bae576f 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerGraph/model.ts +++ b/packages/modules/web_themes/colors/source/src/components/powerGraph/model.ts @@ -145,12 +145,12 @@ export const dayGraph = reactive({ this.date.getFullYear().toString() + (this.date.getMonth() + 1).toString().padStart(2, '0') + this.date.getDate().toString().padStart(2, '0') - graphData.data = [] mqttSubscribe(this.topic) sendCommand({ command: 'getDailyLog', data: { day: dateString }, }) + graphData.data = [] } }, deactivate() { diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue index 9c436fe4b7..7c31c8a6e6 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue @@ -233,7 +233,7 @@ function labelCoordinates(item: number) { // methods function soc(i: number) { - return chargepoints.value[i].soc + return Math.round(chargepoints.value[i].soc) } function trimName(name: string) { const maxlen = 12 diff --git a/packages/modules/web_themes/colors/source/src/components/priceChart/GlobalPriceChart.vue b/packages/modules/web_themes/colors/source/src/components/priceChart/GlobalPriceChart.vue index f9ce3722b9..5c08b7ac70 100755 --- a/packages/modules/web_themes/colors/source/src/components/priceChart/GlobalPriceChart.vue +++ b/packages/modules/web_themes/colors/source/src/components/priceChart/GlobalPriceChart.vue @@ -43,6 +43,7 @@ import { timeFormat, axisLeft, select, + line, } from 'd3' const props = defineProps<{ @@ -78,15 +79,28 @@ const xScale = computed(() => { .range([margin.left, width - margin.left - margin.right]) .domain(xdomain) }) -const yScale = computed(() => { - let ydomain = extent(plotdata.value, (d) => d[1]) as [number, number] - if (ydomain[0] > 0) { - ydomain[0] = 0 +const yDomain = computed(() => { + let yd = extent(plotdata.value, (d) => d[1]) as [number, number] + if (yd[0] > 1) { + yd[0] = 0 + } else { + yd[0] = Math.floor(yd[0]) - 1 } - ydomain[1] = Math.floor(ydomain[1] + 1) + yd[1] = Math.floor(yd[1]) + 1 + return yd +}) +const yScale = computed(() => { return scaleLinear() .range([height - margin.bottom, 0]) - .domain(ydomain) + .domain(yDomain.value) +}) +const zeroPath = computed(() => { + const generator = line() + const points = [ + [margin.left, yScale.value(0)], + [width - margin.right, yScale.value(0)], + ] + return generator(points as [number, number][]) }) const xAxisGenerator = computed(() => { return axisBottom(xScale.value).ticks(4).tickFormat(timeFormat('%H:%M')) @@ -113,15 +127,9 @@ const draw = computed(() => { .append('rect') .attr('class', 'bar') .attr('x', (d) => xScale.value(d[0])) - .attr('y', (d) => { - return d[1] >= 0 ? yScale.value(d[1]) : yScale.value(0) - }) + .attr('y', (d) => yScale.value(d[1])) .attr('width', barwidth.value) - .attr('height', (d) => - d[1] >= 0 - ? yScale.value(0) - yScale.value(d[1]) - : yScale.value(d[1]) - yScale.value(0), - ) + .attr('height', (d) => yScale.value(yDomain.value[0]) - yScale.value(d[1])) .attr('fill', 'var(--color-charging)') // X Axis const xAxis = svg.append('g').attr('class', 'axis').call(xAxisGenerator.value) @@ -152,8 +160,14 @@ const draw = computed(() => { .attr('stroke-width', '0.5') yAxis.select('.domain').attr('stroke', 'var(--color-bg)') - // Line for max price + // zero line + if (yDomain.value[0] < 0) { + svg + .append('path') + .attr('d', zeroPath.value) + .attr('stroke', 'var(--color-fg)') + } return 'PriceChart.vue' }) const chartId = computed(() => { @@ -183,6 +197,7 @@ onMounted(() => { color: var(--color-axis); font-size: 16px; } + .providerbadge { background-color: var(--color-menu); font-weight: normal; diff --git a/packages/modules/web_themes/colors/source/src/components/priceChart/PriceChart.vue b/packages/modules/web_themes/colors/source/src/components/priceChart/PriceChart.vue index ebfbc3a413..e61ba0f2e4 100755 --- a/packages/modules/web_themes/colors/source/src/components/priceChart/PriceChart.vue +++ b/packages/modules/web_themes/colors/source/src/components/priceChart/PriceChart.vue @@ -118,15 +118,20 @@ const xScale = computed(() => { .range([margin.left, width - margin.left - margin.right]) .domain(xdomain) }) -const yScale = computed(() => { - let ydomain = extent(plotdata.value, (d) => d[1]) as [number, number] - if (ydomain[0] > 0) { - ydomain[0] = 0 +const yDomain = computed(() => { + let yd = extent(plotdata.value, (d) => d[1]) as [number, number] + if (yd[0] > 1) { + yd[0] = 0 + } else { + yd[0] = Math.floor(yd[0] - 1) } - ydomain[1] = Math.floor(ydomain[1] + 1) + yd[1] = Math.floor(yd[1] + 1) + return yd +}) +const yScale = computed(() => { return scaleLinear() .range([height - margin.bottom, 0]) - .domain(ydomain) + .domain(yDomain.value) }) const linePath = computed(() => { const generator = line() @@ -136,6 +141,15 @@ const linePath = computed(() => { ] return generator(points as [number, number][]) }) +const zeroPath = computed(() => { + const generator = line() + const points = [ + [margin.left, yScale.value(0)], + [width - margin.right, yScale.value(0)], + ] + return generator(points as [number, number][]) +}) + const xAxisGenerator = computed(() => { return axisBottom(xScale.value).ticks(4).tickFormat(timeFormat('%H:%M')) }) @@ -161,15 +175,9 @@ const draw = computed(() => { .append('rect') .attr('class', 'bar') .attr('x', (d) => xScale.value(d[0])) - .attr('y', (d) => { - return d[1] >= 0 ? yScale.value(d[1]) : yScale.value(0) - }) + .attr('y', (d) => yScale.value(d[1])) .attr('width', barwidth.value) - .attr('height', (d) => - d[1] >= 0 - ? yScale.value(0) - yScale.value(d[1]) - : yScale.value(d[1]) - yScale.value(0), - ) + .attr('height', (d) => yScale.value(yDomain.value[0]) - yScale.value(d[1])) .attr('fill', (d) => d[1] <= maxPrice.value ? 'var(--color-charging)' : 'var(--color-axis)', ) @@ -200,8 +208,14 @@ const draw = computed(() => { .selectAll('.tick line') .attr('stroke', 'var(--color-bg)') .attr('stroke-width', '0.5') - yAxis.select('.domain').attr('stroke', 'var(--color-bg)') + // zero line + if (yDomain.value[0] < 0) { + svg + .append('path') + .attr('d', zeroPath.value) + .attr('stroke', 'var(--color-fg)') + } // Line for max price svg.append('path').attr('d', linePath.value).attr('stroke', 'yellow') diff --git a/packages/modules/web_themes/colors/source/src/components/shared/BatterySymbol.vue b/packages/modules/web_themes/colors/source/src/components/shared/BatterySymbol.vue index 38d19ef5e2..5b2b9838fc 100755 --- a/packages/modules/web_themes/colors/source/src/components/shared/BatterySymbol.vue +++ b/packages/modules/web_themes/colors/source/src/components/shared/BatterySymbol.vue @@ -1,7 +1,7 @@ @@ -48,6 +65,6 @@ const statusString = computed(() => { } .vehiclename { - font-size: var(--font-medium); + font-size: var(--font-large); } diff --git a/packages/modules/web_themes/colors/source/src/views/ColorsTheme.vue b/packages/modules/web_themes/colors/source/src/views/ColorsTheme.vue index 0e6c85fec0..0a310a2774 100644 --- a/packages/modules/web_themes/colors/source/src/views/ColorsTheme.vue +++ b/packages/modules/web_themes/colors/source/src/views/ColorsTheme.vue @@ -15,8 +15,9 @@ Hagen */ - + +
@@ -143,6 +145,20 @@ Hagen */
+
+
+ +
+
+
-
-
- -
-
{ init() window.addEventListener('resize', updateDimensions) - window.document.addEventListener('visibilitychange', visibilityChange) + window.addEventListener('focus', haveFocus) + //window.addEventListener('blur',lostFocus) msgInit() }) -function visibilityChange() { - if (!document.hidden) { - msgInit() +function haveFocus() { + if (document.hasFocus()) { + // console.log('I have focus') + + initGraph() } + //msgInit() } +/* function lostFocus() { + if (!document.hasFocus()) { + console.log('I lost focus') + } +// msgStop() +} */