From 7a53d62327ec236ed452f1f39d67631704b84d34 Mon Sep 17 00:00:00 2001 From: Laurent Garnier Date: Tue, 8 Aug 2023 23:27:52 +0200 Subject: [PATCH] [BasicUI] Add a new header line for image, chart and video elements. Header line for video element contains icon and label. Header line for image element contains icon, label and a button to switch between no upscale and upscale of the image. Header line for chart element contains icon, label and 4 buttons: - one button to show or hide the legend - one button to change the time range - one button to switch between no upscale and upscale of the chart - one button to refresh the chart Fix handling of iconcolor and labelcolor parameters for mapview and webview elements. For image, chart, video, mapview and webview elements, if the label is emppty, the header line is hidden. For chart and image elements, there is now no upscale applied by default (tablet/phone devices) but a button allows upscaling. Closes #1939 Fixes #1367 Also related to #1930 Signed-off-by: Laurent Garnier --- .../basic/internal/render/ChartRenderer.java | 45 +++++ .../basic/internal/render/ImageRenderer.java | 9 + .../internal/render/MapviewRenderer.java | 7 + .../basic/internal/render/VideoRenderer.java | 9 + .../internal/render/WebviewRenderer.java | 7 + .../src/main/resources/snippets/chart.html | 35 ++++ .../src/main/resources/snippets/image.html | 15 ++ .../src/main/resources/snippets/mapview.html | 15 +- .../src/main/resources/snippets/video.html | 9 + .../src/main/resources/snippets/webview.html | 15 +- .../org.openhab.ui.basic/web-src/_layout.scss | 44 +++- .../web-src/_theming.scss | 4 + .../org.openhab.ui.basic/web-src/smarthome.js | 188 +++++++++++++++++- 13 files changed, 375 insertions(+), 27 deletions(-) diff --git a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ChartRenderer.java b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ChartRenderer.java index 37a03cc8d4..8712488796 100644 --- a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ChartRenderer.java +++ b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ChartRenderer.java @@ -15,10 +15,12 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Date; +import java.util.List; import org.eclipse.emf.common.util.ECollections; import org.eclipse.emf.common.util.EList; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.i18n.LocaleProvider; import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.items.GroupItem; @@ -91,7 +93,9 @@ public EList renderWidget(Widget w, StringBuilder sb, String sitemap) th } // if legend parameter is given, add corresponding GET parameter + boolean legend = item instanceof GroupItem && !forceAsItem; if (chart.getLegend() != null) { + legend = chart.getLegend(); if (chart.getLegend()) { chartUrl += "&legend=true"; } else { @@ -123,8 +127,17 @@ public EList renderWidget(Widget w, StringBuilder sb, String sitemap) th } String snippet = getSnippet("chart"); + + boolean showHeaderRow = !getLabel(w).isEmpty(); + snippet = snippet.replace("%header_visibility_class%", + showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden"); + snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString()); + snippet = preprocessSnippet(snippet, w); + // Process the color tags + snippet = processColor(w, snippet); + if (chart.getRefresh() > 0) { snippet = snippet.replace("%update_interval%", Integer.toString(chart.getRefresh())); } else { @@ -136,6 +149,18 @@ public EList renderWidget(Widget w, StringBuilder sb, String sitemap) th snippet = snippet.replace("%valid_url%", "true"); snippet = snippet.replace("%ignore_refresh%", ignoreRefresh ? "true" : "false"); snippet = snippet.replace("%url%", url); + snippet = snippet.replace("%legend%", Boolean.valueOf(legend).toString()); + + List> periods = List.of(List.of("Last hour", "h"), List.of("Last 4 hours", "4h"), + List.of("Last 8 hours", "8h"), List.of("Last 12 hours", "12h"), List.of("Last day", "D"), + List.of("Last 2 days", "2D"), List.of("Last 3 days", "3D"), List.of("Last week", "W"), + List.of("Last 2 weeks", "2W"), List.of("Last month", "M"), List.of("Last 2 months", "2M"), + List.of("Last 4 months", "4M"), List.of("Last year", "Y")); + StringBuilder rowSB = new StringBuilder(); + for (List period : periods) { + buildRow(chart, period.get(0), period.get(1), chart.getPeriod(), rowSB); + } + snippet = snippet.replace("%period_rows%", rowSB.toString()); sb.append(snippet); } catch (ItemNotFoundException e) { @@ -143,4 +168,24 @@ public EList renderWidget(Widget w, StringBuilder sb, String sitemap) th } return ECollections.emptyEList(); } + + private void buildRow(Chart w, @Nullable String lab, String cmd, String current, StringBuilder rowSB) + throws RenderException { + String rowSnippet = getSnippet("selection_row"); + + String command = cmd; + String label = lab == null ? cmd : lab; + + rowSnippet = rowSnippet.replace("%item%", w.getItem() != null ? w.getItem() : ""); + rowSnippet = rowSnippet.replace("%cmd%", escapeHtml(command)); + rowSnippet = rowSnippet.replace("%label%", escapeHtml(label)); + + if (command.equals(current)) { + rowSnippet = rowSnippet.replace("%checked%", "checked=\"true\""); + } else { + rowSnippet = rowSnippet.replace("%checked%", ""); + } + + rowSB.append(rowSnippet); + } } diff --git a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ImageRenderer.java b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ImageRenderer.java index e6c691e45a..e20a6af164 100644 --- a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ImageRenderer.java +++ b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ImageRenderer.java @@ -69,8 +69,17 @@ public EList renderWidget(Widget w, StringBuilder sb, String sitemap) th String widgetId = itemUIRegistry.getWidgetId(w); snippet = snippet.replace("%id%", widgetId); + + boolean showHeaderRow = !getLabel(w).isEmpty(); + snippet = snippet.replace("%header_visibility_class%", + showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden"); + snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString()); + snippet = preprocessSnippet(snippet, w); + // Process the color tags + snippet = processColor(w, snippet); + boolean validUrl = isValidURL(image.getUrl()); String proxiedUrl = "../proxy?sitemap=" + sitemap + "&widgetId=" + widgetId; State state = itemUIRegistry.getState(w); diff --git a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/MapviewRenderer.java b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/MapviewRenderer.java index d900d8168e..13c96c14ee 100644 --- a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/MapviewRenderer.java +++ b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/MapviewRenderer.java @@ -57,7 +57,14 @@ public boolean canRender(Widget w) { public EList renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException { Mapview mapview = (Mapview) w; String snippet = getSnippet("mapview"); + + boolean showHeaderRow = !getLabel(w).isEmpty(); + snippet = snippet.replace("%header_visibility_class%", + showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden"); + snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString()); + snippet = preprocessSnippet(snippet, mapview, true); + // Process the color tags snippet = processColor(w, snippet); diff --git a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/VideoRenderer.java b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/VideoRenderer.java index ab95955437..b7bd4bcb71 100644 --- a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/VideoRenderer.java +++ b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/VideoRenderer.java @@ -66,8 +66,17 @@ public EList renderWidget(Widget w, StringBuilder sb, String sitemap) th && videoWidget.getEncoding().toLowerCase().contains("mjpeg")) ? "image" : "video"; snippet = getSnippet(snippetName); + + boolean showHeaderRow = !getLabel(w).isEmpty(); + snippet = snippet.replace("%header_visibility_class%", + showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden"); + snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString()); + snippet = preprocessSnippet(snippet, w); + // Process the color tags + snippet = processColor(w, snippet); + State state = itemUIRegistry.getState(w); String url; if ("image".equals(snippetName)) { diff --git a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/WebviewRenderer.java b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/WebviewRenderer.java index 649773b424..c24dfb3bad 100644 --- a/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/WebviewRenderer.java +++ b/bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/WebviewRenderer.java @@ -52,7 +52,14 @@ public boolean canRender(Widget w) { public EList renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException { Webview webview = (Webview) w; String snippet = getSnippet("webview"); + + boolean showHeaderRow = !getLabel(w).isEmpty(); + snippet = snippet.replace("%header_visibility_class%", + showHeaderRow ? "%visibility_class%" : "mdl-form__row--hidden"); + snippet = snippet.replace("%header_row%", Boolean.valueOf(showHeaderRow).toString()); + snippet = preprocessSnippet(snippet, webview, true); + // Process the color tags snippet = processColor(w, snippet); diff --git a/bundles/org.openhab.ui.basic/src/main/resources/snippets/chart.html b/bundles/org.openhab.ui.basic/src/main/resources/snippets/chart.html index a2b44a5ff7..80d37a2d6b 100644 --- a/bundles/org.openhab.ui.basic/src/main/resources/snippets/chart.html +++ b/bundles/org.openhab.ui.basic/src/main/resources/snippets/chart.html @@ -1,3 +1,36 @@ +
+ + %icon_snippet% + + + %label% + +
+ + + + + +
+
diff --git a/bundles/org.openhab.ui.basic/src/main/resources/snippets/image.html b/bundles/org.openhab.ui.basic/src/main/resources/snippets/image.html index c51025a2bd..3272de58dc 100644 --- a/bundles/org.openhab.ui.basic/src/main/resources/snippets/image.html +++ b/bundles/org.openhab.ui.basic/src/main/resources/snippets/image.html @@ -1,3 +1,17 @@ +
+ + %icon_snippet% + + + %label% + +
+ +
+
diff --git a/bundles/org.openhab.ui.basic/src/main/resources/snippets/mapview.html b/bundles/org.openhab.ui.basic/src/main/resources/snippets/mapview.html index c4b1ef01e5..a78eddc2d1 100644 --- a/bundles/org.openhab.ui.basic/src/main/resources/snippets/mapview.html +++ b/bundles/org.openhab.ui.basic/src/main/resources/snippets/mapview.html @@ -1,10 +1,10 @@ -
- - %icon_snippet% - - - %label% - +
+ + %icon_snippet% + + + %label% +
diff --git a/bundles/org.openhab.ui.basic/src/main/resources/snippets/video.html b/bundles/org.openhab.ui.basic/src/main/resources/snippets/video.html index 257d533fa8..370de2fe28 100644 --- a/bundles/org.openhab.ui.basic/src/main/resources/snippets/video.html +++ b/bundles/org.openhab.ui.basic/src/main/resources/snippets/video.html @@ -1,8 +1,17 @@ +
+ + %icon_snippet% + + + %label% + +
diff --git a/bundles/org.openhab.ui.basic/src/main/resources/snippets/webview.html b/bundles/org.openhab.ui.basic/src/main/resources/snippets/webview.html index fe2b28ea0c..7a033b4f9b 100644 --- a/bundles/org.openhab.ui.basic/src/main/resources/snippets/webview.html +++ b/bundles/org.openhab.ui.basic/src/main/resources/snippets/webview.html @@ -1,16 +1,17 @@ -
- - %icon_snippet% - - - %label% - +
+ + %icon_snippet% + + + %label% +
diff --git a/bundles/org.openhab.ui.basic/web-src/_layout.scss b/bundles/org.openhab.ui.basic/web-src/_layout.scss index 2431a97b01..a6b1446023 100644 --- a/bundles/org.openhab.ui.basic/web-src/_layout.scss +++ b/bundles/org.openhab.ui.basic/web-src/_layout.scss @@ -67,6 +67,9 @@ @include align-items-2011(center); white-space: nowrap; height: $form-row-desktop-height; + html.ui-layout-condensed & { + height: $form-row-desktop-height-condensed; + } box-sizing: content-box; padding: 4px 0; margin: 0 $mdl-grid-spacing; @@ -76,7 +79,7 @@ padding: 4px $mdl-grid-spacing; margin: 0; html.ui-layout-condensed & { - height: $form-row-desktop-height-condensed; + height: $form-row-mobile-height-condensed; } } @media screen and (min-width: $layout-tablet-size-threshold) { @@ -95,12 +98,19 @@ height: auto; } } + &--header { + border-bottom: none; + padding-bottom: 0; + padding-left: 48px; + padding-right: 48px; + @media screen and (max-width: $layout-tablet-size-threshold) { + padding-left: $mdl-grid-spacing + 16px; + padding-right: $mdl-grid-spacing + 16px; + } + } &--hidden { display: none; } - html.ui-layout-condensed & { - height: $form-row-desktop-height-condensed; - } } &__image { &.mdl-form__control { @@ -111,11 +121,7 @@ max-width: 100%; } } - @media screen and (max-width: $layout-tablet-size-threshold) { - &.mdl-form__control { - padding-left: 0; - padding-right: 0; - } + &-upscale { width: 100%; img { height: auto; @@ -250,6 +256,26 @@ padding-top: 6px; } } + &__header { + padding-left: 8px; + padding-right: $form-row-desktop-padding; + @media screen and (max-width: $layout-tablet-size-threshold) { + padding-right: $form-row-mobile-padding; + } + .mdl-button { + box-shadow: none; + -webkit-box-shadow: none; + min-width: 0; + padding-top: 6px; + } + .chart-legend-button, + .chart-period-button { + padding-top: 1px; + } + &-rows { + display: none; + } + } &__group { padding-top: 4px; } diff --git a/bundles/org.openhab.ui.basic/web-src/_theming.scss b/bundles/org.openhab.ui.basic/web-src/_theming.scss index b4d1d63d01..99f6e4609f 100644 --- a/bundles/org.openhab.ui.basic/web-src/_theming.scss +++ b/bundles/org.openhab.ui.basic/web-src/_theming.scss @@ -84,6 +84,10 @@ body { color: var(--container-text-color, #616161) !important; } +.mdl-form__row--header { + border-bottom: none; +} + .mdl-switch .mdl-switch__track { background: rgba(0,0,0,.26); background: var(--switch-off-track-bg, rgba(0,0,0,.26)); diff --git a/bundles/org.openhab.ui.basic/web-src/smarthome.js b/bundles/org.openhab.ui.basic/web-src/smarthome.js index 169db5427a..f2386fcd4f 100644 --- a/bundles/org.openhab.ui.basic/web-src/smarthome.js +++ b/bundles/org.openhab.ui.basic/web-src/smarthome.js @@ -356,10 +356,19 @@ _t.formRow = parentNode.parentNode; _t.item = _t.parentNode.getAttribute(o.itemAttribute); _t.id = _t.parentNode.getAttribute(o.idAttribute); - _t.iconContainer = _t.parentNode.parentNode.querySelector(o.formIcon); - _t.icon = _t.parentNode.parentNode.querySelector(o.formIconImg); _t.visible = !_t.formRow.classList.contains(o.formRowHidden); - _t.label = _t.parentNode.parentNode.querySelector(o.formLabel); + _t.headerRow = _t.parentNode.getAttribute("data-header-row"); + if (_t.headerRow !== undefined) { + _t.formHeaderRow = _t.formRow.previousElementSibling; + _t.iconContainer = _t.formHeaderRow.querySelector(o.formIcon); + _t.icon = _t.formHeaderRow.querySelector(o.formIconImg); + _t.label = _t.formHeaderRow.querySelector(o.formLabel); + } else { + _t.formHeaderRow = null; + _t.iconContainer = _t.formRow.querySelector(o.formIcon); + _t.icon = _t.formRow.querySelector(o.formIconImg); + _t.label = _t.formRow.querySelector(o.formLabel); + } function convertToInlineSVG() { this.removeEventListener("load", convertToInlineSVG); @@ -404,7 +413,11 @@ // Replace the current icon element with the built inline SVG _t.iconContainer.replaceChild(newIconElement, _t.icon); - _t.icon = _t.parentNode.parentNode.querySelector(o.formIconSvg); + if (_t.headerRow !== undefined) { + _t.icon = _t.formHeaderRow.querySelector(o.formIconSvg); + } else { + _t.icon = _t.formRow.querySelector(o.formIconSvg); + } }; _t.getSVGIconAndReplaceWithInline = function(srcUrl, checkCurrentColor, defaultSVG) { @@ -456,8 +469,14 @@ _t.setVisible = function(state) { if (state) { + if (_t.headerRow === "true") { + _t.formHeaderRow.classList.remove(o.formRowHidden); + } _t.formRow.classList.remove(o.formRowHidden); } else { + if (_t.headerRow === "true") { + _t.formHeaderRow.classList.add(o.formRowHidden); + } _t.formRow.classList.add(o.formRowHidden); } @@ -553,6 +572,12 @@ } else { this.parentNode = parentNode; this.id = this.parentNode.getAttribute(o.idAttribute); + this.headerRow = this.parentNode.getAttribute("data-header-row"); + if (this.headerRow !== undefined) { + this.formHeaderRow = this.parentNode.parentNode.previousElementSibling; + } else { + this.formHeaderRow = null; + } } var @@ -566,6 +591,27 @@ _t.url = parentNode.getAttribute("data-proxied-url"); _t.validUrl = parentNode.getAttribute("data-valid-url") === "true"; _t.ignoreRefresh = parentNode.getAttribute("data-ignore-refresh") === "true"; + _t.legendButton = null; + _t.periodButton = null; + _t.upscaleButton = null; + _t.refreshButton = null; + _t.displayLegend = _t.parentNode.getAttribute("data-legend") === "true"; + _t.period = null; + _t.upscale = false; + + if (_t.headerRow === "true") { + _t.legendButton = _t.formHeaderRow.querySelector(o.image.legendButton); + _t.periodButton = _t.formHeaderRow.querySelector(o.image.periodButton); + _t.upscaleButton = _t.formHeaderRow.querySelector(o.image.upscaleButton); + _t.refreshButton = _t.formHeaderRow.querySelector(o.image.refreshButton); + if (_t.legendButton !== null) { + if (_t.displayLegend) { + _t.legendButton.classList.add(o.buttonActiveClass); + } else { + _t.legendButton.classList.remove(o.buttonActiveClass); + } + } + } _t.setValuePrivate = function(value, itemState, visible) { if (!visible) { @@ -589,9 +635,15 @@ _t.setVisible = function(state) { if (state) { + if (_t.headerRow === "true") { + _t.formHeaderRow.classList.remove(o.formRowHidden); + } _t.formRow.classList.remove(o.formRowHidden); _t.activateRefresh(); } else { + if (_t.headerRow === "true") { + _t.formHeaderRow.classList.add(o.formRowHidden); + } _t.formRow.classList.add(o.formRowHidden); _t.deactivateRefresh(); } @@ -626,14 +678,134 @@ }, _t.updateInterval); }; + function onLegendClick() { + _t.displayLegend = !_t.displayLegend; + if (_t.displayLegend) { + _t.legendButton.classList.add(o.buttonActiveClass); + } else { + _t.legendButton.classList.remove(o.buttonActiveClass); + } + _t.url = _t.url.replace(/&legend=(true|false)/, ""); + if (_t.displayLegend) { + _t.url = _t.url + "&legend=true"; + } else { + _t.url = _t.url + "&legend=false"; + } + _t.image.setAttribute("src", _t.url + "&t=" + Date.now()); + } + + function onPeriodChange(event) { + event.stopPropagation(); + + if (event.target.tagName.toLowerCase() !== "input") { + return; + } + + _t.period = event.target.getAttribute("value"); + _t.url = _t.url.replace(/&period=(h|4h|8h|12h|D|2D|3D|W|2W|M|2M|4M|Y)/, "&period=" + _t.period); + _t.image.setAttribute("src", _t.url + "&t=" + Date.now()); + + setTimeout(function() { + _t.modalPeriods.hide(); + }, 300); + } + + _t.showModalPeriods = function() { + var + content = _t.formHeaderRow.querySelector(o.image.periodRows).innerHTML; + + _t.modalPeriods = new Modal(content); + _t.modalPeriods.show(); + _t.modalPeriods.onHide = function() { + var + items = [].slice.call(_t.modalPeriods.container.querySelectorAll(o.formRadio)); + + componentHandler.downgradeElements(items); + items.forEach(function(control) { + control.removeEventListener("click", onPeriodChange); + }); + + _t.modalPeriods = null; + }; + + var + controls = [].slice.call(_t.modalPeriods.container.querySelectorAll(o.formRadio)); + + if (_t.period !== null) { + var + items = [].slice.call(_t.modalPeriods.container.querySelectorAll("input[type=radio]")); + + items.forEach(function(radioItem) { + if (radioItem.value === _t.period) { + radioItem.checked = true; + } else { + radioItem.checked = false; + } + }); + } + + controls.forEach(function(control) { + componentHandler.upgradeElement(control, "MaterialRadio"); + control.addEventListener("click", onPeriodChange); + }); + }; + + function onUpscaleClick() { + _t.upscale = !_t.upscale; + if (_t.upscale) { + _t.upscaleButton.classList.add(o.buttonActiveClass); + } else { + _t.upscaleButton.classList.remove(o.buttonActiveClass); + } + if (_t.upscale) { + _t.parentNode.classList.add(o.image.upscaleClass); + } else { + _t.parentNode.classList.remove(o.image.upscaleClass); + } + } + + function onRefreshClick() { + _t.image.setAttribute("src", _t.url + "&t=" + Date.now()); + } + _t.destroy = function() { var imageParent = _t.image.parentNode; _t.image.setAttribute("src", urlNoneIcon); imageParent.removeChild(_t.image); + + if (_t.legendButton !== null) { + componentHandler.downgradeElements([ _t.legendButton ]); + _t.legendButton.removeEventListener("click", onLegendClick); + } + if (_t.periodButton !== null) { + componentHandler.downgradeElements([ _t.periodButton ]); + _t.periodButton.removeEventListener("click", _t.showModalPeriods); + } + if (_t.upscaleButton !== null) { + componentHandler.downgradeElements([ _t.upscaleButton ]); + _t.upscaleButton.removeEventListener("click", onUpscaleClick); + } + if (_t.refreshButton !== null) { + componentHandler.downgradeElements([ _t.refreshButton ]); + _t.refreshButton.removeEventListener("click", onRefreshClick); + } }; + if (_t.legendButton !== null) { + _t.legendButton.addEventListener("click", onLegendClick); + } + if (_t.periodButton !== null) { + _t.periodButton.addEventListener("click", _t.showModalPeriods); + } + if (_t.upscaleButton !== null) { + _t.upscaleButton.addEventListener("click", onUpscaleClick); + } + if (_t.refreshButton !== null) { + _t.refreshButton.addEventListener("click", onRefreshClick); + } + if (_t.visible) { _t.activateRefresh(); } @@ -2780,6 +2952,14 @@ colorpicker: ".colorpicker", button: ".colorpicker__buttons > button" }, + image: { + legendButton: ".chart-legend-button", + periodButton: ".chart-period-button", + periodRows: ".mdl-form__header-rows", + upscaleButton: ".image-upscale-button", + upscaleClass: "mdl-form__image-upscale", + refreshButton: ".chart-refresh-button" + }, notify: ".mdl-notify__container", notifyHidden: "mdl-notify--hidden", notifyTemplateOffline: "template-offline-notify",