diff --git a/compact-custom-header.js b/compact-custom-header.js
index 493c680..b9972d8 100644
--- a/compact-custom-header.js
+++ b/compact-custom-header.js
@@ -1,423 +1,467 @@
console.info(
- `%c COMPACT-CUSTOM-HEADER \n%c Version 1.4.1 `,
+ `%c COMPACT-CUSTOM-HEADER \n%c Version 1.4.2 `,
"color: orange; font-weight: bold; background: black",
"color: white; font-weight: bold; background: dimgray"
);
-const LitElement = Object.getPrototypeOf(
- customElements.get("ha-panel-lovelace")
-);
-const html = LitElement.prototype.html;
-const hass = document.querySelector("home-assistant").hass;
-
-const fireEvent = (node, type, detail, options = {}) => {
- detail = detail === null || detail === undefined ? {} : detail;
- const event = new Event(type, {
- bubbles: options.bubbles === undefined ? true : options.bubbles,
- cancelable: Boolean(options.cancelable),
- composed: options.composed === undefined ? true : options.composed
- });
- event.detail = detail;
- node.dispatchEvent(event);
- return event;
-};
-
-const defaultConfig = {
- header: true,
- disable: false,
- menu: "show",
- voice: "show",
- notifications: "show",
- options: "show",
- clock_format: 12,
- clock_am_pm: true,
- clock_date: false,
- date_locale: hass.language,
- chevrons: false,
- redirect: true,
- background: "",
- hide_tabs: [],
- show_tabs: [],
- edit_mode_show_tabs: false,
- default_tab: "",
- default_tab_template: "",
- kiosk_mode: false,
- sidebar_swipe: true,
- sidebar_closed: false,
- disable_sidebar: false,
- hide_help: false,
- hide_config: false,
- hide_unused: false,
- tab_color: {},
- button_color: {},
- statusbar_color: "",
- swipe: false,
- swipe_amount: "15",
- swipe_animate: "none",
- swipe_skip: "",
- swipe_wrap: true,
- swipe_prevent_default: false,
- swipe_skip_hidden: true,
- warning: true,
- compact_header: true,
- view_css: "",
- time_css: "",
- date_css: "",
- header_css: "",
- tab_css: {},
- button_css: {}
-};
-
-let root = document.querySelector("home-assistant");
-root = root && root.shadowRoot;
-root = root && root.querySelector("home-assistant-main");
-const main = root;
-root = root && root.shadowRoot;
-root = root && root.querySelector("app-drawer-layout partial-panel-resolver");
-const panelResolver = root;
-root = (root && root.shadowRoot) || root;
-root = root && root.querySelector("ha-panel-lovelace");
-root = root && root.shadowRoot;
-root = root && root.querySelector("hui-root");
-const lovelace = root.lovelace;
-root = root.shadowRoot;
-
-const frontendVersion = Number(window.frontendVersion);
-const newSidebar = frontendVersion >= 20190710;
-const header = root.querySelector("app-header");
-let cchConfig = buildConfig(lovelace.config.cch || {});
-if (typeof cchConfig.background == "boolean") cchConfig.background = "";
-const view = root.querySelector("ha-app-layout").querySelector("#view");
-const disabled =
- window.location.href.includes("disable_cch") || cchConfig.disable;
-
-let sidebarClosed = false;
-let editMode = header.className == "edit-mode";
-let firstRun = true;
-let buttons = {};
-let prevColor = {};
-
-run();
-breakingChangeNotification();
-
-function run() {
- const tabContainer = root.querySelector("paper-tabs");
- const tabs = tabContainer
- ? Array.from(tabContainer.querySelectorAll("paper-tab"))
- : [];
- if (firstRun || buttons == undefined) {
- buttons = getButtonElements(tabContainer);
- }
- if (!buttons.menu || !buttons.options || header.className == "edit-mode") {
- return;
- }
- if (!disabled) {
- insertEditMenu(tabs);
- hideMenuItems();
- styleHeader(tabContainer, tabs, header);
- styleButtons(tabs, tabContainer);
- if (firstRun) {
- sidebarMod();
- conditionalStyling(tabs, header);
- }
- hideTabs(tabContainer, tabs);
- for (let button in buttons) {
- if (cchConfig[button] == "clock") insertClock(button);
- }
- if (!editMode) tabContainerMargin(tabContainer);
- if (cchConfig.swipe) swipeNavigation(tabs, tabContainer);
- }
- if (firstRun) {
- observers(tabContainer, tabs, header);
- defaultTab(tabs, tabContainer);
- }
- firstRun = false;
- fireEvent(header, "iron-resize");
-}
+class CompactCustomHeader {
+ constructor() {
+ this.LitElement = Object.getPrototypeOf(
+ customElements.get("ha-panel-lovelace")
+ );
+ this.hass = document.querySelector("home-assistant").hass;
+ this.fireEvent = (node, type, detail, options = {}) => {
+ detail = detail === null || detail === undefined ? {} : detail;
+ const event = new Event(type, {
+ bubbles: options.bubbles === undefined ? true : options.bubbles,
+ cancelable: Boolean(options.cancelable),
+ composed: options.composed === undefined ? true : options.composed
+ });
+ event.detail = detail;
+ node.dispatchEvent(event);
+ return event;
+ };
-function buildConfig(config) {
- let exceptionConfig = {};
- let highestMatch = 0;
- // Count number of matching conditions and choose config with most matches.
- if (config.exceptions) {
- config.exceptions.forEach(exception => {
- const matches = countMatches(exception.conditions);
- if (matches > highestMatch) {
- highestMatch = matches;
- exceptionConfig = exception.config;
- }
- });
+ let ll = document.querySelector("home-assistant");
+ ll = ll && ll.shadowRoot;
+ ll = ll && ll.querySelector("home-assistant-main");
+ this.main = ll;
+ ll = ll && ll.shadowRoot;
+ ll = ll && ll.querySelector("app-drawer-layout partial-panel-resolver");
+ this.panelResolver = ll;
+ ll = (ll && ll.shadowRoot) || ll;
+ ll = ll && ll.querySelector("ha-panel-lovelace");
+ ll = ll && ll.shadowRoot;
+ ll = ll && ll.querySelector("hui-root");
+ this.lovelace = ll.lovelace;
+ this.root = ll.shadowRoot;
+
+ this.frontendVersion = Number(window.frontendVersion);
+ this.newSidebar = this.frontendVersion >= 20190710;
+ this.header = this.root.querySelector("app-header");
+ this.editMode = this.header.className == "edit-mode";
+ this.view = this.root.querySelector("ha-app-layout #view");
+
+ this.sidebarClosed = false;
+ this.firstRun = true;
+ this.buttons = {};
+ this.prevColor = {};
+
+ this.defaultConfig = {
+ header: true,
+ disable: false,
+ menu: "show",
+ voice: "show",
+ notifications: "show",
+ options: "show",
+ clock_format: 12,
+ clock_am_pm: true,
+ clock_date: false,
+ date_locale: this.hass.language,
+ chevrons: false,
+ redirect: true,
+ background: "",
+ hide_tabs: "",
+ show_tabs: "",
+ edit_mode_show_tabs: false,
+ default_tab: "",
+ default_tab_template: "",
+ kiosk_mode: false,
+ sidebar_swipe: true,
+ sidebar_closed: false,
+ disable_sidebar: false,
+ hide_help: false,
+ hide_config: false,
+ hide_unused: false,
+ tab_color: {},
+ button_color: {},
+ statusbar_color: "",
+ swipe: false,
+ swipe_amount: "15",
+ swipe_animate: "none",
+ swipe_skip: "",
+ swipe_wrap: true,
+ swipe_prevent_default: false,
+ swipe_skip_hidden: true,
+ warning: true,
+ compact_header: true,
+ view_css: "",
+ time_css: "",
+ date_css: "",
+ header_css: "",
+ tab_css: {},
+ button_css: {}
+ };
+
+ this.cchConfig = this.buildConfig(
+ this.lovelace.config.cch || {},
+ this.hass.user.name
+ );
}
- // If exception config uses hide_tabs and main config uses show_tabs,
- // delete show_tabs and vice versa.
- if (
- exceptionConfig.hide_tabs &&
- config.show_tabs &&
- exceptionConfig.hide_tabs.length &&
- config.show_tabs.length
- ) {
- delete config.show_tabs;
- } else if (
- exceptionConfig.show_tabs &&
- config.hide_tabs &&
- exceptionConfig.show_tabs.length &&
- config.hide_tabs.length
- ) {
- delete config.hide_tabs;
- }
-
- return { ...defaultConfig, ...config, ...exceptionConfig };
-
- function countMatches(conditions) {
- const userVars = { user: hass.user.name, user_agent: navigator.userAgent };
- let count = 0;
- for (const cond in conditions) {
- if (cond == "user" && conditions[cond].includes(",")) {
- conditions[cond].split(/[ ,]+/).forEach(user => {
- if (userVars[cond] == user) count++;
- });
- } else {
- if (
- userVars[cond] == conditions[cond] ||
- (cond == "query_string" &&
- window.location.search.includes(conditions[cond])) ||
- (cond == "user_agent" && userVars[cond].includes(conditions[cond])) ||
- (cond == "media_query" && window.matchMedia(conditions[cond]).matches)
- ) {
- count++;
+
+ run() {
+ const tabContainer = this.root.querySelector("paper-tabs");
+ const tabs = tabContainer
+ ? Array.from(tabContainer.querySelectorAll("paper-tab"))
+ : [];
+ let disabled =
+ window.location.href.includes("disable_cch") || this.cchConfig.disable;
+
+ if (this.firstRun || this.buttons == undefined) {
+ this.buttons = this.getButtonElements(tabContainer);
+ }
+ if (!this.buttons.menu || !this.buttons.options || this.editMode) return;
+ if (!disabled) {
+ this.insertEditMenu(tabs);
+ this.hideMenuItems();
+ this.styleHeader(tabContainer, tabs);
+ this.styleButtons(tabs, tabContainer);
+ if (this.firstRun) {
+ this.sidebarMod();
+ this.conditionalStyling(tabs, this.header);
+ }
+ this.hideTabs(tabContainer, tabs);
+ for (let button in this.buttons) {
+ if (this.cchConfig[button] == "clock") this.insertClock(button);
+ }
+ if (!this.editMode) this.tabContainerMargin(tabContainer);
+ if (this.cchConfig.swipe) this.swipeNavigation(tabs, tabContainer);
+ if (this.firstRun) this.defaultTab(tabs, tabContainer);
+ }
+ if (this.firstRun) {
+ this.observers(tabContainer, tabs, disabled);
+ this.breakingChangeNotification();
+ }
+ this.firstRun = false;
+ this.fireEvent(this.header, "iron-resize");
+ }
+
+ buildConfig(config, user_name) {
+ let exceptionConfig = {};
+ let highestMatch = 0;
+ // Count number of matching conditions and choose config with most matches.
+ if (config.exceptions) {
+ config.exceptions.forEach(exception => {
+ const matches = countMatches(exception.conditions, user_name);
+ if (matches > highestMatch) {
+ highestMatch = matches;
+ exceptionConfig = exception.config;
+ }
+ });
+ }
+ // If exception config uses hide_tabs and main config uses show_tabs,
+ // delete show_tabs and vice versa.
+ if (
+ exceptionConfig.hide_tabs &&
+ config.show_tabs &&
+ exceptionConfig.hide_tabs.length &&
+ config.show_tabs.length
+ ) {
+ delete config.show_tabs;
+ } else if (
+ exceptionConfig.show_tabs &&
+ config.hide_tabs &&
+ exceptionConfig.show_tabs.length &&
+ config.hide_tabs.length
+ ) {
+ delete config.hide_tabs;
+ }
+
+ return { ...this.defaultConfig, ...config, ...exceptionConfig };
+
+ function countMatches(conditions, user_name) {
+ const userVars = {
+ user: user_name,
+ user_agent: navigator.userAgent
+ };
+ let count = 0;
+ for (const cond in conditions) {
+ if (cond == "user" && conditions[cond].includes(",")) {
+ conditions[cond].split(/[ ,]+/).forEach(user => {
+ if (userVars[cond] == user) count++;
+ });
} else {
- return 0;
+ if (
+ userVars[cond] == conditions[cond] ||
+ (cond == "query_string" &&
+ window.location.search.includes(conditions[cond])) ||
+ (cond == "user_agent" &&
+ userVars[cond].includes(conditions[cond])) ||
+ (cond == "media_query" &&
+ window.matchMedia(conditions[cond]).matches)
+ ) {
+ count++;
+ } else {
+ return 0;
+ }
}
}
+ return count;
}
- return count;
}
-}
-function observers(tabContainer, tabs, header) {
- const callback = mutations => {
- // Theme Changed.
- if (mutations[0].target.nodeName == "HTML") {
- mutations = [mutations[0]];
- styleHeader(tabContainer, tabs, header);
- conditionalStyling(tabs, header);
- return;
- }
- mutations.forEach(({ addedNodes, target }) => {
- if (addedNodes.length && target.nodeName == "PARTIAL-PANEL-RESOLVER") {
- // Navigated back to lovelace from elsewhere in HA.
- buttons = getButtonElements();
- run();
- } else if (target.className == "edit-mode" && addedNodes.length) {
- // Entered edit mode.
- editMode = true;
- if (!disabled) removeStyles(tabContainer, tabs, header);
- buttons.options = root.querySelector("paper-menu-button");
- insertEditMenu(tabs);
- fireEvent(header, "iron-resize");
- } else if (target.nodeName == "APP-HEADER" && addedNodes.length) {
- // Exited edit mode.
- for (let node of addedNodes) {
- if (node.nodeName == "APP-TOOLBAR") {
- editMode = false;
- buttons = getButtonElements();
- root.querySelectorAll("[id^='cch']").forEach(style => {
- style.remove();
- });
- setTimeout(() => {
- run();
- if (!disabled) conditionalStyling(tabs, header);
- }, 100);
- }
- }
- } else if (
- // Viewing unused entities
- frontendVersion < 20190911 &&
- addedNodes.length &&
- !addedNodes[0].nodeName == "HUI-UNUSED-ENTITIES"
- ) {
- let editor = root
- .querySelector("ha-app-layout")
- .querySelector("editor");
- if (editor) root.querySelector("ha-app-layout").removeChild(editor);
- if (cchConfig.conditional_styles) {
- buttons = getButtonElements(tabContainer);
- conditionalStyling(tabs, header);
- }
- } else if (target.id == "view" && addedNodes.length) {
- scrollTabIconIntoView();
+ observers(tabContainer, tabs, disabled) {
+ // Watch for changes in Lovelace.
+ const callback = mutations => {
+ // Theme changed.
+ if (mutations[0].target.nodeName == "HTML") {
+ mutations = [mutations[0]];
+ this.styleHeader(tabContainer, tabs);
+ this.conditionalStyling(tabs);
+ return;
}
- });
- };
- let observer = new MutationObserver(callback);
- observer.observe(panelResolver, { childList: true });
- observer.observe(document.querySelector("html"), { attributes: true });
- observer.observe(view, { childList: true });
- observer.observe(root.querySelector("app-header"), { childList: true });
-
- if (!disabled) {
- window.hassConnection.then(({ conn }) => {
- conn.socket.onmessage = () => {
- if (cchConfig.conditional_styles && !editMode) {
- conditionalStyling(tabs, header);
+ mutations.forEach(({ addedNodes, target }) => {
+ if (addedNodes.length && target.nodeName == "PARTIAL-PANEL-RESOLVER") {
+ // Navigated back to lovelace from elsewhere in HA.
+ this.buttons = this.getButtonElements();
+ this.run();
+ } else if (target.className == "edit-mode" && addedNodes.length) {
+ // Entered edit mode.
+ this.editMode = true;
+ if (!disabled) this.removeStyles(tabContainer, tabs, this.header);
+ this.buttons.options = this.root.querySelector("paper-menu-button");
+ this.insertEditMenu(tabs);
+ this.fireEvent(this.header, "iron-resize");
+ } else if (target.nodeName == "APP-HEADER" && addedNodes.length) {
+ // Exited edit mode.
+ let editor = this.root
+ .querySelector("ha-app-layout")
+ .querySelector("editor");
+ if (editor) {
+ this.root.querySelector("ha-app-layout").removeChild(editor);
+ }
+ for (let node of addedNodes) {
+ if (node.nodeName == "APP-TOOLBAR") {
+ this.editMode = false;
+ this.buttons = this.getButtonElements();
+ this.root.querySelectorAll("[id^='cch']").forEach(style => {
+ style.remove();
+ });
+ setTimeout(() => {
+ this.run();
+ if (!disabled) this.conditionalStyling(tabs, this.header);
+ }, 100);
+ }
+ }
+ } else if (
+ // Viewing unused entities
+ this.frontendVersion < 20190911 &&
+ addedNodes.length &&
+ !addedNodes[0].nodeName == "HUI-UNUSED-ENTITIES"
+ ) {
+ let editor = this.root
+ .querySelector("ha-app-layout")
+ .querySelector("editor");
+ if (editor) {
+ this.root.querySelector("ha-app-layout").removeChild(editor);
+ }
+ if (this.cchConfig.conditional_styles) {
+ this.buttons = this.getButtonElements(tabContainer);
+ this.conditionalStyling(tabs, this.header);
+ }
+ } else if (target.id == "view" && addedNodes.length) {
+ // Navigating to new tab/view.
+ this.run();
+ this.scrollTabIconIntoView();
}
- };
+ });
+ };
+ let observer = new MutationObserver(callback);
+ observer.observe(this.panelResolver, { childList: true });
+ observer.observe(document.querySelector("html"), { attributes: true });
+ observer.observe(this.view, { childList: true });
+ observer.observe(this.root.querySelector("app-header"), {
+ childList: true
});
- }
-}
-function getButtonElements() {
- let buttons = {};
- buttons.options = root.querySelector("paper-menu-button");
- if (!editMode) {
- buttons.menu = root.querySelector("ha-menu-button");
- buttons.voice = root.querySelector("ha-start-voice-button");
- if (!newSidebar) {
- buttons.notifications = root.querySelector("hui-notifications-button");
+ if (!disabled) {
+ // Watch for changes in entities.
+ window.hassConnection.then(({ conn }) => {
+ conn.socket.onmessage = () => {
+ if (this.cchConfig.conditional_styles && !this.editMode) {
+ conditionalStyling(tabs, this.header);
+ }
+ };
+ });
}
}
- if (buttons.menu && buttons.menu.style.visibility == "hidden" && !disabled) {
- buttons.menu.style.display = "none";
- } else if (buttons.menu) {
- buttons.menu.style.display = "";
- }
- return buttons;
-}
-function tabContainerMargin(tabContainer) {
- let marginRight = 0;
- let marginLeft = 15;
- for (const button in buttons) {
- let paperIconButton =
- buttons[button].querySelector("paper-icon-button") ||
- buttons[button].shadowRoot.querySelector("paper-icon-button");
- let visible = paperIconButton
- ? buttons[button].style.display !== "none" &&
- !paperIconButton.hasAttribute("hidden")
- : buttons[button].style.display !== "none";
- if (cchConfig[button] == "show" && visible) {
- if (button == "menu") marginLeft += 45;
- else marginRight += 45;
- } else if (cchConfig[button] == "clock" && visible) {
- const clockWidth =
- (cchConfig.clock_format == 12 && cchConfig.clock_am_pm) ||
- cchConfig.clock_date
- ? 110
- : 80;
- if (button == "menu") marginLeft += clockWidth + 15;
- else marginRight += clockWidth;
- }
- }
- if (tabContainer) {
- tabContainer.style.marginRight = `${marginRight}px`;
- tabContainer.style.marginLeft = `${marginLeft}px`;
+ getButtonElements(disabled) {
+ let buttons = {};
+ buttons.options = this.root.querySelector("paper-menu-button");
+ if (!this.editMode) {
+ buttons.menu = this.root.querySelector("ha-menu-button");
+ buttons.voice = this.root.querySelector("ha-start-voice-button");
+ if (!this.newSidebar) {
+ buttons.notifications = this.root.querySelector(
+ "hui-notifications-button"
+ );
+ }
+ }
+ // Remove space taken up by "hidden" menu button anytime we get buttons.
+ if (
+ buttons.menu &&
+ buttons.menu.style.visibility == "hidden" &&
+ !disabled
+ ) {
+ buttons.menu.style.display = "none";
+ } else if (buttons.menu) {
+ buttons.menu.style.display = "";
+ }
+ return buttons;
+ }
+
+ tabContainerMargin(tabContainer) {
+ let marginRight = 0;
+ let marginLeft = 15;
+ for (const button in this.buttons) {
+ let paperIconButton =
+ this.buttons[button].querySelector("paper-icon-button") ||
+ this.buttons[button].shadowRoot.querySelector("paper-icon-button");
+ let visible = paperIconButton
+ ? this.buttons[button].style.display !== "none" &&
+ !paperIconButton.hasAttribute("hidden")
+ : this.buttons[button].style.display !== "none";
+ if (this.cchConfig[button] == "show" && visible) {
+ if (button == "menu") marginLeft += 45;
+ else marginRight += 45;
+ } else if (this.cchConfig[button] == "clock" && visible) {
+ const clockWidth =
+ (this.cchConfig.clock_format == 12 && this.cchConfig.clock_am_pm) ||
+ this.cchConfig.clock_date
+ ? 110
+ : 80;
+ if (button == "menu") marginLeft += clockWidth + 15;
+ else marginRight += clockWidth;
+ }
+ }
+ if (tabContainer) {
+ tabContainer.style.marginRight = `${marginRight}px`;
+ tabContainer.style.marginLeft = `${marginLeft}px`;
+ }
}
-}
-function scrollTabIconIntoView() {
- let paperTabs = root.querySelector("paper-tabs");
- let currentTab = paperTabs.querySelector(".iron-selected");
- if (!paperTabs || !currentTab) return;
- let tab = currentTab.getBoundingClientRect();
- let container = paperTabs.shadowRoot
- .querySelector("#tabsContainer")
- .getBoundingClientRect();
- if (container.right < tab.right || container.left > tab.left) {
- if ("scrollMarginInline" in document.documentElement.style) {
- currentTab.scrollIntoView({ inline: "center" });
- } else if (Element.prototype.scrollIntoViewIfNeeded) {
- currentTab.scrollIntoViewIfNeeded(true);
- } else {
- currentTab.scrollIntoView();
+ scrollTabIconIntoView() {
+ let paperTabs = this.root.querySelector("paper-tabs");
+ let currentTab = paperTabs.querySelector(".iron-selected");
+ if (!paperTabs || !currentTab) return;
+ let tab = currentTab.getBoundingClientRect();
+ let container = paperTabs.shadowRoot
+ .querySelector("#tabsContainer")
+ .getBoundingClientRect();
+ // If tab's icon isn't in view scroll it in.
+ if (container.right < tab.right || container.left > tab.left) {
+ if ("scrollMarginInline" in document.documentElement.style) {
+ currentTab.scrollIntoView({ inline: "center" });
+ } else if (Element.prototype.scrollIntoViewIfNeeded) {
+ currentTab.scrollIntoViewIfNeeded(true);
+ } else {
+ currentTab.scrollIntoView();
+ }
}
}
-}
-function hideMenuItems() {
- if (cchConfig.hide_help || cchConfig.hide_config || cchConfig.hide_unused) {
- const itemCheck = (item, string) => {
- let localized = hass.localize(`ui.panel.lovelace.menu.${string}`);
- return (
- item.innerHTML.includes(localized) ||
- item.getAttribute("aria-label") == localized
- );
- };
- buttons.options
- .querySelector("paper-listbox")
- .querySelectorAll("paper-item")
- .forEach(item => {
- if (
- (cchConfig.hide_help && itemCheck(item, "help")) ||
- (cchConfig.hide_unused && itemCheck(item, "unused_entities")) ||
- (cchConfig.hide_config && itemCheck(item, "configure_ui"))
- ) {
- item.parentNode.removeChild(item);
- }
- });
+ hideMenuItems() {
+ // Hide items in options menu.
+ if (
+ this.cchConfig.hide_help ||
+ this.cchConfig.hide_config ||
+ this.cchConfig.hide_unused
+ ) {
+ const localized = (item, string) => {
+ let localString = this.hass.localize(
+ `ui.panel.lovelace.menu.${string}`
+ );
+ return (
+ item.innerHTML.includes(localString) ||
+ item.getAttribute("aria-label") == localString
+ );
+ };
+ this.buttons.options
+ .querySelector("paper-listbox")
+ .querySelectorAll("paper-item")
+ .forEach(item => {
+ if (
+ (this.cchConfig.hide_help && localized(item, "help")) ||
+ (this.cchConfig.hide_unused &&
+ localized(item, "unused_entities")) ||
+ (this.cchConfig.hide_config && localized(item, "configure_ui"))
+ ) {
+ item.parentNode.removeChild(item);
+ }
+ });
+ }
}
-}
-function insertEditMenu(tabs) {
- if (buttons.options && editMode) {
- // If any tabs are hidden, add "show all tabs" option.
- if (cchConfig.hide_tabs && !cchConfig.edit_mode_show_tabs) {
- let show_tabs = document.createElement("paper-item");
- show_tabs.setAttribute("id", "show_tabs");
- show_tabs.addEventListener("click", () => {
- for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.removeProperty("display");
- }
- });
- show_tabs.innerHTML = "Show all tabs";
- insertMenuItem(buttons.options.querySelector("paper-listbox"), show_tabs);
- }
+ insertEditMenu(tabs, disabled) {
+ if (this.buttons.options && this.editMode) {
+ // If any tabs are hidden, add "show all tabs" option.
+ if (this.cchConfig.hide_tabs && !this.cchConfig.edit_mode_show_tabs) {
+ let show_tabs = document.createElement("paper-item");
+ show_tabs.setAttribute("id", "show_tabs");
+ show_tabs.addEventListener("click", () => {
+ for (let i = 0; i < tabs.length; i++) {
+ tabs[i].style.removeProperty("display");
+ }
+ });
+ show_tabs.innerHTML = "Show all tabs";
+ this.insertMenuItem(
+ this.buttons.options.querySelector("paper-listbox"),
+ show_tabs
+ );
+ }
- // Add menu item to open CCH settings.
- let cchSettings = document.createElement("paper-item");
- cchSettings.setAttribute("id", "cch_settings");
- cchSettings.addEventListener("click", () => {
- showEditor();
- });
- cchSettings.innerHTML = "CCH Settings";
- insertMenuItem(buttons.options.querySelector("paper-listbox"), cchSettings);
- if (!disabled) hideMenuItems();
+ // Add menu item to open CCH settings.
+ let cchSettings = document.createElement("paper-item");
+ cchSettings.setAttribute("id", "cch_settings");
+ cchSettings.addEventListener("click", () => this.showEditor());
+ cchSettings.innerHTML = "CCH Settings";
+ this.insertMenuItem(
+ this.buttons.options.querySelector("paper-listbox"),
+ cchSettings
+ );
+ if (!disabled) this.hideMenuItems();
+ }
}
-}
-function removeStyles(tabContainer, tabs, { style }) {
- root.querySelector("app-header").style.backgroundColor = "#455a64";
- root.querySelectorAll("[id^='cch']").forEach(style => {
- style.remove();
- });
- if (cchConfig.tab_css) {
- for (let [key, value] of Object.entries(cchConfig.tab_css)) {
- key = getViewIndex(key);
- value = value.replace(/: /g, ":").replace(/; /g, ";");
- let css = tabs[key].style.cssText.replace(/: /g, ":").replace(/; /g, ";");
- tabs[key].style.cssText = css.replace(value, "");
- }
- }
- if (cchConfig.header_css) {
- let value = cchConfig.header_css.replace(/: /g, ":").replace(/; /g, ";");
- let css = style.cssText.replace(/: /g, ":").replace(/; /g, ";");
- style.cssText = css.replace(value, "");
- }
- if (tabContainer) {
- tabContainer.style.marginLeft = "";
- tabContainer.style.marginRight = "";
- }
- view.style = "";
- for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.color = "";
- }
- if (cchConfig.edit_mode_show_tabs) {
+ removeStyles(tabContainer, tabs, { style }) {
+ this.root.querySelector("app-header").style.backgroundColor = "#455a64";
+ this.root.querySelectorAll("[id^='cch']").forEach(style => {
+ style.remove();
+ });
+ if (this.cchConfig.tab_css) {
+ for (let [key, value] of Object.entries(this.cchConfig.tab_css)) {
+ key = getViewIndex(key);
+ value = value.replace(/: /g, ":").replace(/; /g, ";");
+ let css = tabs[key].style.cssText
+ .replace(/: /g, ":")
+ .replace(/; /g, ";");
+ tabs[key].style.cssText = css.replace(value, "");
+ }
+ }
+ if (this.cchConfig.header_css) {
+ let value = this.cchConfig.header_css
+ .replace(/: /g, ":")
+ .replace(/; /g, ";");
+ let css = style.cssText.replace(/: /g, ":").replace(/; /g, ";");
+ style.cssText = css.replace(value, "");
+ }
+ if (tabContainer) {
+ tabContainer.style.marginLeft = "";
+ tabContainer.style.marginRight = "";
+ }
+ this.view.style = "";
for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.removeProperty("display");
+ tabs[i].style.color = "";
}
- }
- let viewStyle = document.createElement("style");
- viewStyle.setAttribute("id", "cch_view_styling");
- viewStyle.innerHTML = `
+ if (this.cchConfig.edit_mode_show_tabs) {
+ for (let i = 0; i < tabs.length; i++) {
+ tabs[i].style.removeProperty("display");
+ }
+ }
+ let viewStyle = document.createElement("style");
+ viewStyle.setAttribute("id", "cch_view_styling");
+ viewStyle.innerHTML = `
hui-view {
min-height: 100vh;
}
@@ -425,139 +469,133 @@ function removeStyles(tabContainer, tabs, { style }) {
min-height: calc(100vh - 52px);
}
`;
- root.appendChild(viewStyle);
-}
+ this.root.appendChild(viewStyle);
+ }
-function styleHeader(tabContainer, tabs, header) {
- document.body.style.backgroundColor = getComputedStyle(
- document.body
- ).getPropertyValue("--background-color");
- prevColor.background =
- cchConfig.background ||
- getComputedStyle(document.body).getPropertyValue("--cch-background") ||
- getComputedStyle(document.body).getPropertyValue("--primary-color");
- let statusBarColor = cchConfig.statusbar_color || prevColor.background;
- // Match mobile status bar color to header color.
- let themeColor = document.querySelector('[name="theme-color"]');
- let themeColorApple =
- document.querySelector('[name="apple-mobile-web-app-status-bar-style"]') ||
- document.createElement("meta");
- function colorStatusBar() {
- statusBarColor =
- cchConfig.statusbar_color ||
- cchConfig.background ||
+ styleHeader(tabContainer, tabs) {
+ // Fix for old background config option.
+ if (typeof this.cchConfig.background == "boolean") {
+ this.cchConfig.background = "";
+ }
+ this.prevColor.background =
+ this.cchConfig.background ||
getComputedStyle(document.body).getPropertyValue("--cch-background") ||
getComputedStyle(document.body).getPropertyValue("--primary-color");
- themeColor = document.querySelector("meta[name=theme-color]");
- themeColor.setAttribute("content", statusBarColor);
- themeColor.setAttribute("default-content", statusBarColor);
- if (
- !document.querySelector('[name="apple-mobile-web-app-status-bar-style"]')
- ) {
- themeColorApple.name = "apple-mobile-web-app-status-bar-style";
- themeColorApple.content = statusBarColor;
- document.getElementsByTagName("head")[0].appendChild(themeColorApple);
- } else {
- themeColorApple.setAttribute("content", statusBarColor);
+ let statusBarColor =
+ this.cchConfig.statusbar_color || this.prevColor.background;
+ // Match mobile status bar color to header color.
+ let themeColor = document.querySelector('[name="theme-color"]');
+ let themeColorApple =
+ document.querySelector(
+ '[name="apple-mobile-web-app-status-bar-style"]'
+ ) || document.createElement("meta");
+ colorStatusBar(statusBarColor);
+ // If browser is idle or in background sometimes theme-color needs reset.
+ let observeStatus = new MutationObserver(() => {
+ if (themeColor.content != statusBarColor) colorStatusBar(statusBarColor);
+ });
+ if (this.firstRun) {
+ observeStatus.observe(themeColor, {
+ attributes: true,
+ attributeFilter: ["content"]
+ });
}
- }
- colorStatusBar();
- // If app/browser is idle or in background sometimes theme-color needs reset.
- let observeStatus = new MutationObserver(() => {
- if (themeColor.content != statusBarColor) colorStatusBar();
- });
- if (firstRun) {
- observeStatus.observe(themeColor, { attributeFilter: ["content"] });
- }
- // Adjust view size & padding for new header size.
- if (!cchConfig.header || cchConfig.kiosk_mode) {
- header.style.display = "none";
- view.style.minHeight = "100vh";
- if (
- frontendVersion >= 20190911 &&
- !root.querySelector("#cch_view_styling")
- ) {
- let viewStyle = document.createElement("style");
- viewStyle.setAttribute("id", "cch_view_styling");
- viewStyle.innerHTML = `
+ // Adjust view size & padding for new header size.
+ if (!this.cchConfig.header || this.cchConfig.kiosk_mode) {
+ this.header.style.display = "none";
+ this.view.style.minHeight = "100vh";
+ if (
+ this.frontendVersion >= 20190911 &&
+ !this.root.querySelector("#cch_view_styling")
+ ) {
+ let viewStyle = document.createElement("style");
+ viewStyle.setAttribute("id", "cch_view_styling");
+ viewStyle.innerHTML = `
hui-view {
- ${cchConfig.view_css ? cchConfig.view_css : ""}
+ ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
}
hui-panel-view {
- ${cchConfig.view_css ? cchConfig.view_css : ""}
+ ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
}
`;
- root.appendChild(viewStyle);
- }
- } else {
- view.style.minHeight = "100vh";
- view.style.marginTop = "-48.5px";
- view.style.paddingTop = "48.5px";
- view.style.boxSizing = "border-box";
- header.style.background = prevColor.background;
- header.querySelector("app-toolbar").style.background = "transparent";
- if (
- frontendVersion >= 20190911 &&
- !root.querySelector("#cch_view_styling")
- ) {
- let viewStyle = document.createElement("style");
- viewStyle.setAttribute("id", "cch_view_styling");
- viewStyle.innerHTML = `
+ this.root.appendChild(viewStyle);
+ }
+ } else {
+ this.view.style.minHeight = "100vh";
+ this.view.style.marginTop = "-48.5px";
+ this.view.style.paddingTop = "48.5px";
+ this.view.style.boxSizing = "border-box";
+ this.header.style.background = this.prevColor.background;
+ this.header.querySelector("app-toolbar").style.background = "transparent";
+ if (
+ this.frontendVersion >= 20190911 &&
+ !this.root.querySelector("#cch_view_styling")
+ ) {
+ let viewStyle = document.createElement("style");
+ viewStyle.setAttribute("id", "cch_view_styling");
+ viewStyle.innerHTML = `
hui-view {
margin-top: -48.5px;
padding-top: 52px;
min-height: 100vh;
- ${cchConfig.view_css ? cchConfig.view_css : ""}
+ ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
}
hui-panel-view {
margin-top: -48.5px;
padding-top: 52px;
min-height: calc(100vh - 52px);
- ${cchConfig.view_css ? cchConfig.view_css : ""}
+ ${this.cchConfig.view_css ? this.cchConfig.view_css : ""}
}
`;
- root.appendChild(viewStyle);
- }
- }
-
- // Match sidebar elements to header's size.
- if (newSidebar && cchConfig.compact_header) {
- let sidebar = main.shadowRoot.querySelector("ha-sidebar").shadowRoot;
- sidebar.querySelector(".menu").style = "height:49px;";
- sidebar.querySelector("paper-listbox").style = "height:calc(100% - 180px);";
- }
-
- // Current tab icon color.
- let conditionalTabs = cchConfig.conditional_styles
- ? JSON.stringify(cchConfig.conditional_styles).includes("tab")
- : false;
- if (
- !root.querySelector("#cch_iron_selected") &&
- !editMode &&
- !conditionalTabs &&
- tabContainer
- ) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_iron_selected");
- style.innerHTML = `
+ this.root.appendChild(viewStyle);
+ }
+ }
+
+ // Match sidebar elements to header's size.
+ if (this.newSidebar && this.cchConfig.compact_header) {
+ let sidebar = this.main.shadowRoot.querySelector("ha-sidebar").shadowRoot;
+ sidebar.querySelector(".menu").style = "height:49px;";
+ sidebar.querySelector("paper-listbox").style =
+ "height:calc(100% - 180px);";
+ }
+
+ // Current tab icon color.
+ let conditionalTabs = this.cchConfig.conditional_styles
+ ? JSON.stringify(this.cchConfig.conditional_styles).includes("tab")
+ : false;
+ if (
+ !this.root.querySelector("#cch_iron_selected") &&
+ !this.editMode &&
+ !conditionalTabs &&
+ tabContainer
+ ) {
+ let style = document.createElement("style");
+ style.setAttribute("id", "cch_iron_selected");
+ style.innerHTML = `
.iron-selected {
${
- cchConfig.active_tab_color
- ? `color: ${`${cchConfig.active_tab_color} !important`}`
+ this.cchConfig.active_tab_color
+ ? `color: ${`${
+ this.cchConfig.active_tab_color
+ } !important`}`
: "var(--cch-active-tab-color)"
}
}
`;
- tabContainer.appendChild(style);
- }
+ tabContainer.appendChild(style);
+ }
- // Style current tab indicator.
- let indicator = cchConfig.tab_indicator_color;
- if (indicator && !root.querySelector("#cch_header_colors") && !editMode) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_header_colors");
- style.innerHTML = `
+ // Style current tab indicator.
+ let indicator = this.cchConfig.tab_indicator_color;
+ if (
+ indicator &&
+ !this.root.querySelector("#cch_header_colors") &&
+ !this.editMode
+ ) {
+ let style = document.createElement("style");
+ style.setAttribute("id", "cch_header_colors");
+ style.innerHTML = `
paper-tabs {
${
indicator
@@ -566,81 +604,96 @@ function styleHeader(tabContainer, tabs, header) {
}
}
`;
- root.appendChild(style);
- }
-
- // Tab's icon color.
- let all_tabs_color = cchConfig.all_tabs_color || "var(--cch-all-tabs-color)";
- if (
- (cchConfig.tab_color && Object.keys(cchConfig.tab_color).length) ||
- all_tabs_color
- ) {
- for (let i = 0; i < tabs.length; i++) {
- tabs[i].style.color = cchConfig.tab_color[i] || all_tabs_color;
+ this.root.appendChild(style);
}
- }
- // Add header custom css.
- if (cchConfig.header_css) header.style.cssText += cchConfig.header_css;
-
- // Add view custom css.
- if (cchConfig.view_css && frontendVersion < 20190911) {
- view.style.cssText += cchConfig.view_css;
- }
+ // Tab's icon color.
+ let all_tabs_color =
+ this.cchConfig.all_tabs_color || "var(--cch-all-tabs-color)";
+ if (
+ (this.cchConfig.tab_color &&
+ Object.keys(this.cchConfig.tab_color).length) ||
+ all_tabs_color
+ ) {
+ for (let i = 0; i < tabs.length; i++) {
+ tabs[i].style.color = this.cchConfig.tab_color[i] || all_tabs_color;
+ }
+ }
- // Add tab custom css.
- let tabCss = cchConfig.tab_css;
- if (tabCss) {
- for (let [key, value] of Object.entries(tabCss)) {
- key = getViewIndex(key);
- if (tabs[key]) tabs[key].style.cssText += value;
+ // Add custom css.
+ if (this.cchConfig.tab_css) {
+ for (let [key, value] of Object.entries(this.cchConfig.tab_css)) {
+ key = getViewIndex(key);
+ if (tabs[key]) tabs[key].style.cssText += value;
+ }
+ }
+ if (this.cchConfig.header_css)
+ this.header.style.cssText += this.cchConfig.header_css;
+ if (this.cchConfig.view_css && this.frontendVersion < 20190911) {
+ this.view.style.cssText += this.cchConfig.view_css;
}
- }
- if (tabContainer) {
- // Shift the header up to hide unused portion.
- root.querySelector("app-toolbar").style.marginTop = cchConfig.compact_header
- ? "-64px"
- : "";
+ if (tabContainer) {
+ // Shift the header up to hide unused portion.
+ this.root.querySelector("app-toolbar").style.marginTop = this.cchConfig
+ .compact_header
+ ? "-64px"
+ : "";
- tabs.forEach(({ style }) => {
- style.marginTop = "-1px";
- });
+ tabs.forEach(({ style }) => {
+ style.marginTop = "-1px";
+ });
- // Show/hide tab navigation chevrons.
- if (!cchConfig.chevrons) {
- let chevron = tabContainer.shadowRoot.querySelectorAll(
- '[icon^="paper-tabs:chevron"]'
- );
- chevron[0].style.display = "none";
- chevron[1].style.display = "none";
- } else {
- // Remove space taken up by "not-visible" chevron.
- let style = document.createElement("style");
- style.setAttribute("id", "cch_chevron");
- style.innerHTML = `
+ // Show/hide tab navigation chevrons.
+ if (!this.cchConfig.chevrons) {
+ let chevron = tabContainer.shadowRoot.querySelectorAll(
+ '[icon^="paper-tabs:chevron"]'
+ );
+ chevron[0].style.display = "none";
+ chevron[1].style.display = "none";
+ } else {
+ // Remove space taken up by "not-visible" chevron.
+ let style = document.createElement("style");
+ style.setAttribute("id", "cch_chevron");
+ style.innerHTML = `
.not-visible {
display:none;
}
`;
- tabContainer.shadowRoot.appendChild(style);
+ tabContainer.shadowRoot.appendChild(style);
+ }
+ }
+ function colorStatusBar(statusBarColor) {
+ themeColor = document.querySelector("meta[name=theme-color]");
+ themeColor.setAttribute("content", statusBarColor);
+ themeColor.setAttribute("default-content", statusBarColor);
+ if (
+ !document.querySelector(
+ '[name="apple-mobile-web-app-status-bar-style"]'
+ )
+ ) {
+ themeColorApple.name = "apple-mobile-web-app-status-bar-style";
+ themeColorApple.content = statusBarColor;
+ document.getElementsByTagName("head")[0].appendChild(themeColorApple);
+ } else {
+ themeColorApple.setAttribute("content", statusBarColor);
+ }
}
}
-}
-function styleButtons({ length }, tabContainer) {
- let topMargin =
- length > 0 && cchConfig.compact_header ? "margin-top:111px;" : "";
- let topMarginMenu =
- length > 0 && cchConfig.compact_header ? "margin-top:115px;" : "";
- // Reverse buttons object so menu is first in overflow menu.
- buttons = reverseObject(buttons);
- for (const button in buttons) {
- if (!buttons[button]) continue;
- if (button == "options" && cchConfig[button] == "overflow") {
- cchConfig[button] = "show";
- }
- let buttonStyle = `
+ styleButtons({ length }, tabContainer) {
+ let topMargin =
+ length > 0 && this.cchConfig.compact_header ? "margin-top:111px;" : "";
+ let topMarginMenu =
+ length > 0 && this.cchConfig.compact_header ? "margin-top:115px;" : "";
+ // Reverse buttons object so "menu" is first in the overflow menu.
+ this.buttons = this.reverseObject(this.buttons);
+ for (const button in this.buttons) {
+ if (!this.buttons[button]) continue;
+ if (button == "options" && this.cchConfig[button] == "overflow") {
+ this.cchConfig[button] = "show";
+ }
+ let buttonStyle = `
z-index:1;
${
button == "menu"
@@ -650,46 +703,57 @@ function styleButtons({ length }, tabContainer) {
${button == "menu" ? "" : topMargin}
${button == "options" ? "margin-right:-5px;" : ""}
`;
- if (cchConfig[button] == "show" || cchConfig[button] == "clock") {
- if (button == "menu") {
- let paperIconButton = buttons[button].querySelector("paper-icon-button")
- ? buttons[button].querySelector("paper-icon-button")
- : buttons[button].shadowRoot.querySelector("paper-icon-button");
- if (!paperIconButton) continue;
- paperIconButton.style.cssText = buttonStyle;
- } else {
- buttons[button].style.cssText = buttonStyle;
- }
- } else if (cchConfig[button] == "overflow") {
- const menu_items = buttons.options.querySelector("paper-listbox");
- let paperIconButton = buttons[button].querySelector("paper-icon-button")
- ? buttons[button].querySelector("paper-icon-button")
- : buttons[button].shadowRoot.querySelector("paper-icon-button");
- if (paperIconButton && paperIconButton.hasAttribute("hidden")) {
- continue;
- }
- const id = `menu_item_${button}`;
- if (!menu_items.querySelector(`#${id}`)) {
- const wrapper = document.createElement("paper-item");
- wrapper.setAttribute("id", id);
- wrapper.innerText = getTranslation(button);
- wrapper.appendChild(buttons[button]);
- wrapper.addEventListener("click", () => {
- paperIconButton.click();
- });
- paperIconButton.style.pointerEvents = "none";
- insertMenuItem(menu_items, wrapper);
- if (button == "notifications" && !newSidebar) {
- let style = document.createElement("style");
- style.innerHTML = `
+ if (
+ this.cchConfig[button] == "show" ||
+ this.cchConfig[button] == "clock"
+ ) {
+ if (button == "menu") {
+ let paperIconButton = this.buttons[button].querySelector(
+ "paper-icon-button"
+ )
+ ? this.buttons[button].querySelector("paper-icon-button")
+ : this.buttons[button].shadowRoot.querySelector(
+ "paper-icon-button"
+ );
+ if (!paperIconButton) continue;
+ paperIconButton.style.cssText = buttonStyle;
+ } else {
+ this.buttons[button].style.cssText = buttonStyle;
+ }
+ } else if (this.cchConfig[button] == "overflow") {
+ const menu_items = this.buttons.options.querySelector("paper-listbox");
+ let paperIconButton = this.buttons[button].querySelector(
+ "paper-icon-button"
+ )
+ ? this.buttons[button].querySelector("paper-icon-button")
+ : this.buttons[button].shadowRoot.querySelector("paper-icon-button");
+ if (paperIconButton && paperIconButton.hasAttribute("hidden")) {
+ continue;
+ }
+ const id = `menu_item_${button}`;
+ if (!menu_items.querySelector(`#${id}`)) {
+ const wrapper = document.createElement("paper-item");
+ wrapper.setAttribute("id", id);
+ wrapper.innerText = getTranslation(button);
+ wrapper.appendChild(this.buttons[button]);
+ wrapper.addEventListener("click", () => {
+ paperIconButton.click();
+ });
+ paperIconButton.style.pointerEvents = "none";
+ insertMenuItem(menu_items, wrapper);
+ if (button == "notifications" && !this.newSidebar) {
+ let style = document.createElement("style");
+ style.innerHTML = `
.indicator {
top: 5px;
right: 0px;
width: 10px;
height: 10px;
${
- cchConfig.notify_indicator_color
- ? `background-color:${cchConfig.notify_indicator_color}`
+ this.cchConfig.notify_indicator_color
+ ? `background-color:${
+ this.cchConfig.notify_indicator_color
+ }`
: ""
}
}
@@ -697,69 +761,78 @@ function styleButtons({ length }, tabContainer) {
display:none;
}
`;
- paperIconButton.parentNode.appendChild(style);
+ paperIconButton.parentNode.appendChild(style);
+ }
}
+ } else if (this.cchConfig[button] == "hide") {
+ this.buttons[button].style.display = "none";
+ }
+ // Hide menu button if hiding the sidebar.
+ if (
+ this.newSidebar &&
+ (this.cchConfig.kiosk_mode || this.cchConfig.disable_sidebar)
+ ) {
+ this.buttons.menu.style.display = "none";
}
- } else if (cchConfig[button] == "hide") {
- buttons[button].style.display = "none";
}
- // Hide menu button if hiding the sidebar.
- if (newSidebar && (cchConfig.kiosk_mode || cchConfig.disable_sidebar)) {
- buttons.menu.style.display = "none";
+
+ // Remove empty space taken up by hidden menu button.
+ if (this.buttons.menu && this.newSidebar && this.firstRun) {
+ new MutationObserver(() => {
+ if (this.buttons.menu.style.visibility == "hidden") {
+ this.buttons.menu.style.display = "none";
+ } else {
+ this.buttons.menu.style.display = "";
+ }
+ this.tabContainerMargin(tabContainer);
+ }).observe(this.buttons.menu, {
+ attributes: true,
+ attributeFilter: ["style"]
+ });
}
- }
- // Remove empty space taken up by hidden menu button.
- if (buttons.menu && newSidebar && !disabled) {
- new MutationObserver(() => {
- if (buttons.menu.style.visibility == "hidden") {
- buttons.menu.style.display = "none";
- } else {
- buttons.menu.style.display = "";
+ // Use color vars set in HA theme.
+ this.buttons.menu.style.color = "var(--cch-button-color-menu)";
+ if (!this.newSidebar) {
+ this.buttons.notifications.style.color =
+ "var(--cch-button-color-notifications)";
+ }
+ this.buttons.voice.style.color = "var(--cch-button-color-voice)";
+ this.buttons.options.style.color = "var(--cch-button-color-options)";
+ if (this.cchConfig.all_buttons_color) {
+ this.root.querySelector("app-toolbar").style.color =
+ this.cchConfig.all_buttons_color || "var(--cch-all-buttons-color)";
+ }
+
+ // Use colors set in CCH config.
+ for (const button in this.buttons) {
+ if (this.cchConfig.button_color[button]) {
+ this.buttons[button].style.color = this.cchConfig.button_color[button];
}
- tabContainerMargin(tabContainer);
- }).observe(buttons.menu, { attributeFilter: ["style"] });
- }
-
- // Use color vars set in HA theme.
- buttons.menu.style.color = "var(--cch-button-color-menu)";
- if (!newSidebar) {
- buttons.notifications.style.color = "var(--cch-button-color-notifications)";
- }
- buttons.voice.style.color = "var(--cch-button-color-voice)";
- buttons.options.style.color = "var(--cch-button-color-options)";
- if (cchConfig.all_buttons_color) {
- root.querySelector("app-toolbar").style.color =
- cchConfig.all_buttons_color || "var(--cch-all-buttons-color)";
- }
-
- // Use colors set in CCH config.
- for (const button in buttons) {
- if (cchConfig.button_color[button]) {
- buttons[button].style.color = cchConfig.button_color[button];
- }
- }
-
- // Notification indicator's color for HA 0.96 and above.
- if (
- newSidebar &&
- cchConfig.menu != "hide" &&
- !buttons.menu.shadowRoot.querySelector("#cch_dot")
- ) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_dot");
- let indicator =
- cchConfig.notify_indicator_color ||
- getComputedStyle(header).getPropertyValue("--cch-tab-indicator-color") ||
- "";
- let border = getComputedStyle(header)
- .getPropertyValue("background")
- .includes("url")
- ? "border-color: transparent !important"
- : `border-color: ${getComputedStyle(header).getPropertyValue(
- "background-color"
- )} !important;`;
- style.innerHTML = `
+ }
+
+ // Notification indicator's color for HA 0.96 and above.
+ if (
+ this.newSidebar &&
+ this.cchConfig.menu != "hide" &&
+ !this.buttons.menu.shadowRoot.querySelector("#cch_dot")
+ ) {
+ let style = document.createElement("style");
+ style.setAttribute("id", "cch_dot");
+ let indicator =
+ this.cchConfig.notify_indicator_color ||
+ getComputedStyle(this.header).getPropertyValue(
+ "--cch-tab-indicator-color"
+ ) ||
+ "";
+ let border = getComputedStyle(this.header)
+ .getPropertyValue("background")
+ .includes("url")
+ ? "border-color: transparent !important"
+ : `border-color: ${getComputedStyle(this.header).getPropertyValue(
+ "background-color"
+ )} !important;`;
+ style.innerHTML = `
.dot {
${topMargin}
z-index: 2;
@@ -767,186 +840,194 @@ function styleButtons({ length }, tabContainer) {
${border}
}
`;
- buttons.menu.shadowRoot.appendChild(style);
- } else if (
- // Notification indicator's color for HA 0.95 and below.
- cchConfig.notify_indicator_color &&
- cchConfig.notifications == "show" &&
- !newSidebar
- ) {
- let style = document.createElement("style");
- style.innerHTML = `
+ this.buttons.menu.shadowRoot.appendChild(style);
+ } else if (
+ // Notification indicator's color for HA 0.95 and below.
+ this.cchConfig.notify_indicator_color &&
+ this.cchConfig.notifications == "show" &&
+ !this.newSidebar
+ ) {
+ let style = document.createElement("style");
+ style.innerHTML = `
.indicator {
- background-color:${cchConfig.notify_indicator_color ||
+ background-color:${this.cchConfig.notify_indicator_color ||
"var(--cch-notify-indicator-color)"} !important;
- color: ${cchConfig.notify_text_color ||
+ color: ${this.cchConfig.notify_text_color ||
"var(--cch-notify-text-color), var(--primary-text-color)"};
}
`;
- buttons.notifications.shadowRoot.appendChild(style);
- }
+ this.buttons.notifications.shadowRoot.appendChild(style);
+ }
- // Add buttons's custom css.
- let buttonCss = cchConfig.button_css;
- if (buttonCss) {
- for (const [key, value] of Object.entries(buttonCss)) {
- if (!buttons[key]) {
- continue;
- } else {
- buttons[key].style.cssText += value;
+ // Add buttons's custom css.
+ let buttonCss = this.cchConfig.button_css;
+ if (buttonCss) {
+ for (const [key, value] of Object.entries(buttonCss)) {
+ if (!this.buttons[key]) {
+ continue;
+ } else {
+ this.buttons[key].style.cssText += value;
+ }
}
}
}
-}
-function getTranslation(button) {
- switch (button) {
- case "notifications":
- return hass.localize("ui.notification_drawer.title");
- default:
- return button.charAt(0).toUpperCase() + button.slice(1);
+ getTranslation(button) {
+ switch (button) {
+ case "notifications":
+ return this.hass.localize("ui.notification_drawer.title");
+ default:
+ return button.charAt(0).toUpperCase() + button.slice(1);
+ }
}
-}
-function defaultTab(tabs, tabContainer) {
- let firstTab = tabs.indexOf(tabs.filter(tab => tab.style.display == "")[0]);
- let default_tab = cchConfig.default_tab;
- if (!default_tab || default_tab == []) return;
- let template = cchConfig.default_tab_template;
- if ((default_tab || template) && tabContainer) {
- if (template) default_tab = templateEval(template, hass.states);
- default_tab = getViewIndex(default_tab);
- let activeTab = tabs.indexOf(tabContainer.querySelector(".iron-selected"));
- if (
- activeTab != default_tab &&
- activeTab == firstTab &&
- (!cchConfig.redirect ||
- (cchConfig.redirect && tabs[default_tab].style.display != "none"))
- ) {
- tabs[default_tab].click();
+ defaultTab(tabs, tabContainer) {
+ let firstTab = tabs.indexOf(tabs.filter(tab => tab.style.display == "")[0]);
+ let default_tab = this.cchConfig.default_tab;
+ if (typeof default_tab == "object" && !default_tab.length) return;
+ let template = this.cchConfig.default_tab_template;
+ if ((default_tab || template) && tabContainer) {
+ if (template) default_tab = this.templateEval(template, this.hass.states);
+ default_tab = this.getViewIndex(default_tab);
+ let activeTab = tabs.indexOf(
+ tabContainer.querySelector(".iron-selected")
+ );
+ if (
+ activeTab != default_tab &&
+ activeTab == firstTab &&
+ (!this.cchConfig.redirect ||
+ (this.cchConfig.redirect &&
+ tabs[default_tab].style.display != "none"))
+ ) {
+ tabs[default_tab].click();
+ }
}
}
-}
-function sidebarMod() {
- let menu = buttons.menu.querySelector("paper-icon-button");
- let sidebar = main.shadowRoot.querySelector("app-drawer");
-
- // HA 0.95 and below
- if (!newSidebar) {
- if (!cchConfig.sidebar_swipe || cchConfig.kiosk_mode) {
- sidebar.removeAttribute("swipe-open");
- }
- if ((cchConfig.sidebar_closed || cchConfig.kiosk_mode) && !sidebarClosed) {
- if (sidebar.hasAttribute("opened")) menu.click();
- sidebarClosed = true;
- }
- // HA 0.96 and above
- } else if (cchConfig.disable_sidebar || cchConfig.kiosk_mode) {
- sidebar.style.display = "none";
- sidebar.addEventListener(
- "mouseenter",
- event => {
- event.stopPropagation();
- },
- true
- );
- let style = document.createElement("style");
- style.type = "text/css";
- style.appendChild(
- document.createTextNode(
- ":host(:not([expanded])) {width: 0px !important;}"
- )
- );
- main.shadowRoot.querySelector("ha-sidebar").shadowRoot.appendChild(style);
+ sidebarMod() {
+ let menu = this.buttons.menu.querySelector("paper-icon-button");
+ let sidebar = this.main.shadowRoot.querySelector("app-drawer");
- style = document.createElement("style");
- style.type = "text/css";
- style.appendChild(
- document.createTextNode(":host {--app-drawer-width: 0px !important;}")
- );
- main.shadowRoot.appendChild(style);
+ // HA 0.95 and below
+ if (!this.newSidebar) {
+ if (!this.cchConfig.sidebar_swipe || this.cchConfig.kiosk_mode) {
+ sidebar.removeAttribute("swipe-open");
+ }
+ if (
+ (this.cchConfig.sidebar_closed || this.cchConfig.kiosk_mode) &&
+ !this.sidebarClosed
+ ) {
+ if (sidebar.hasAttribute("opened")) menu.click();
+ this.sidebarClosed = true;
+ }
+ // HA 0.96 and above
+ } else if (this.cchConfig.disable_sidebar || this.cchConfig.kiosk_mode) {
+ sidebar.style.display = "none";
+ sidebar.addEventListener(
+ "mouseenter",
+ event => {
+ event.stopPropagation();
+ },
+ true
+ );
+ let style = document.createElement("style");
+ style.type = "text/css";
+ style.appendChild(
+ document.createTextNode(
+ ":host(:not([expanded])) {width: 0px !important;}"
+ )
+ );
+ this.main.shadowRoot
+ .querySelector("ha-sidebar")
+ .shadowRoot.appendChild(style);
+
+ style = document.createElement("style");
+ style.type = "text/css";
+ style.appendChild(
+ document.createTextNode(":host {--app-drawer-width: 0px !important;}")
+ );
+ this.main.shadowRoot.appendChild(style);
+ }
}
-}
-function hideTabs(tabContainer, tabs) {
- let hidden_tabs = String(cchConfig.hide_tabs).length
- ? String(cchConfig.hide_tabs)
- .replace(/\s+/g, "")
- .split(",")
- : null;
- let shown_tabs = String(cchConfig.show_tabs).length
- ? String(cchConfig.show_tabs)
- .replace(/\s+/g, "")
- .split(",")
- : null;
-
- // Set the tab config source.
- if (!hidden_tabs && shown_tabs) {
- let all_tabs = [];
- shown_tabs = buildRanges(shown_tabs);
- for (let i = 0; i < tabs.length; i++) all_tabs.push(i);
- // Invert shown_tabs to hidden_tabs.
- hidden_tabs = all_tabs.filter(el => !shown_tabs.includes(el));
- } else {
- hidden_tabs = buildRanges(hidden_tabs);
- }
-
- // Hide tabs.
- for (const tab of hidden_tabs) {
- if (!tabs[tab]) continue;
- tabs[tab].style.display = "none";
- }
-
- if (cchConfig.redirect && tabContainer) {
- const activeTab = tabContainer.querySelector("paper-tab.iron-selected");
- const activeTabIndex = tabs.indexOf(activeTab);
- // Is the current tab hidden and is there at least one tab is visible.
- if (
- hidden_tabs.includes(activeTabIndex) &&
- hidden_tabs.length != tabs.length
- ) {
- let i = 0;
- // Find the first visible tab and navigate.
- while (hidden_tabs.includes(i)) {
- i++;
+ hideTabs(tabContainer, tabs) {
+ let hidden_tabs = String(this.cchConfig.hide_tabs).length
+ ? String(this.cchConfig.hide_tabs)
+ .replace(/\s+/g, "")
+ .split(",")
+ : null;
+ let shown_tabs = String(this.cchConfig.show_tabs).length
+ ? String(this.cchConfig.show_tabs)
+ .replace(/\s+/g, "")
+ .split(",")
+ : null;
+
+ // Set the tab config source.
+ if (!hidden_tabs && shown_tabs) {
+ let all_tabs = [];
+ shown_tabs = buildRanges(shown_tabs);
+ for (let i = 0; i < tabs.length; i++) all_tabs.push(i);
+ // Invert shown_tabs to hidden_tabs.
+ hidden_tabs = all_tabs.filter(el => !shown_tabs.includes(el));
+ } else {
+ hidden_tabs = this.buildRanges(hidden_tabs);
+ }
+
+ // Hide tabs.
+ for (const tab of hidden_tabs) {
+ if (!tabs[tab]) continue;
+ tabs[tab].style.display = "none";
+ }
+
+ if (this.cchConfig.redirect && tabContainer) {
+ const activeTab = tabContainer.querySelector("paper-tab.iron-selected");
+ const activeTabIndex = tabs.indexOf(activeTab);
+ // Is the current tab hidden and is there at least one tab is visible.
+ if (
+ hidden_tabs.includes(activeTabIndex) &&
+ hidden_tabs.length != tabs.length
+ ) {
+ let i = 0;
+ // Find the first visible tab and navigate.
+ while (hidden_tabs.includes(i)) {
+ i++;
+ }
+ tabs[i].click();
}
- tabs[i].click();
}
+ return hidden_tabs;
}
- return hidden_tabs;
-}
-function insertMenuItem(menu_items, element) {
- let first_item = menu_items.querySelector("paper-item");
- if (!menu_items.querySelector(`#${element.id}`)) {
- first_item.parentNode.insertBefore(element, first_item);
+ insertMenuItem(menu_items, element) {
+ let first_item = menu_items.querySelector("paper-item");
+ if (!menu_items.querySelector(`#${element.id}`)) {
+ first_item.parentNode.insertBefore(element, first_item);
+ }
}
-}
-function insertClock(button) {
- const clock_button = buttons[button].querySelector("paper-icon-button")
- ? buttons[button]
- : buttons[button].shadowRoot;
- const clockIcon = clock_button.querySelector("paper-icon-button");
- const clockIronIcon =
- clockIcon.querySelector("iron-icon") ||
- clockIcon.shadowRoot.querySelector("iron-icon");
- const clockWidth =
- (cchConfig.clock_format == 12 && cchConfig.clock_am_pm) ||
- cchConfig.clock_date
- ? 105
- : 80;
-
- if (
- !newSidebar &&
- cchConfig.notifications == "clock" &&
- cchConfig.clock_date &&
- !buttons.notifications.shadowRoot.querySelector("#cch_indicator")
- ) {
- let style = document.createElement("style");
- style.setAttribute("id", "cch_indicator");
- style.innerHTML = `
+ insertClock(button) {
+ const clock_button = this.buttons[button].querySelector("paper-icon-button")
+ ? this.buttons[button]
+ : this.buttons[button].shadowRoot;
+ const clockIcon = clock_button.querySelector("paper-icon-button");
+ const clockIronIcon =
+ clockIcon.querySelector("iron-icon") ||
+ clockIcon.shadowRoot.querySelector("iron-icon");
+ const clockWidth =
+ (this.cchConfig.clock_format == 12 && this.cchConfig.clock_am_pm) ||
+ this.cchConfig.clock_date
+ ? 105
+ : 80;
+
+ if (
+ !this.newSidebar &&
+ this.cchConfig.notifications == "clock" &&
+ this.cchConfig.clock_date &&
+ !this.buttons.notifications.shadowRoot.querySelector("#cch_indicator")
+ ) {
+ let style = document.createElement("style");
+ style.setAttribute("id", "cch_indicator");
+ style.innerHTML = `
.indicator {
top: unset;
bottom: -3px;
@@ -955,8 +1036,8 @@ function insertClock(button) {
height: 3px;
border-radius: 0;
${
- cchConfig.notify_indicator_color
- ? `background-color:${cchConfig.notify_indicator_color}`
+ this.cchConfig.notify_indicator_color
+ ? `background-color:${this.cchConfig.notify_indicator_color}`
: ""
}
}
@@ -964,708 +1045,801 @@ function insertClock(button) {
display:none;
}
`;
- buttons.notifications.shadowRoot.appendChild(style);
- }
+ this.buttons.notifications.shadowRoot.appendChild(style);
+ }
- let clockElement = clockIronIcon.parentNode.getElementById("cch_clock");
- if (cchConfig.menu == "clock") {
- buttons.menu.style.marginTop = cchConfig.compact_header ? "111px" : "";
- buttons.menu.style.zIndex = "1";
- }
- if (!clockElement) {
- clockIcon.style.cssText = `
+ let clockElement = clockIronIcon.parentNode.getElementById("cch_clock");
+ if (this.cchConfig.menu == "clock") {
+ this.buttons.menu.style.marginTop = this.cchConfig.compact_header
+ ? "111px"
+ : "";
+ this.buttons.menu.style.zIndex = "1";
+ }
+ if (!clockElement) {
+ clockIcon.style.cssText = `
margin-right:-5px;
width:${clockWidth}px;
text-align: center;
`;
- clockElement = document.createElement("p");
- clockElement.setAttribute("id", "cch_clock");
- let clockAlign = "center";
- let padding = "";
- let fontSize = "";
- if (cchConfig.clock_date && cchConfig.menu == "clock") {
- clockAlign = "left";
- padding = "margin-right:-20px";
- fontSize = "font-size:12pt";
- } else if (cchConfig.clock_date) {
- clockAlign = "right";
- padding = "margin-left:-20px";
- fontSize = "font-size:12pt";
- }
- clockElement.style.cssText = `
- margin-top: ${cchConfig.clock_date ? "-4px" : "2px"};
+ clockElement = document.createElement("p");
+ clockElement.setAttribute("id", "cch_clock");
+ let clockAlign = "center";
+ let padding = "";
+ let fontSize = "";
+ if (this.cchConfig.clock_date && this.cchConfig.menu == "clock") {
+ clockAlign = "left";
+ padding = "margin-right:-20px";
+ fontSize = "font-size:12pt";
+ } else if (this.cchConfig.clock_date) {
+ clockAlign = "right";
+ padding = "margin-left:-20px";
+ fontSize = "font-size:12pt";
+ }
+ clockElement.style.cssText = `
+ margin-top: ${this.cchConfig.clock_date ? "-4px" : "2px"};
text-align: ${clockAlign};
${padding};
${fontSize};
`;
- clockIronIcon.parentNode.insertBefore(clockElement, clockIronIcon);
- clockIronIcon.style.display = "none";
- let style = document.createElement("style");
- style.setAttribute("id", "cch_clock");
- style.innerHTML = `
+ clockIronIcon.parentNode.insertBefore(clockElement, clockIronIcon);
+ clockIronIcon.style.display = "none";
+ let style = document.createElement("style");
+ style.setAttribute("id", "cch_clock");
+ style.innerHTML = `
time {
- ${cchConfig.time_css}
+ ${this.cchConfig.time_css}
}
date {
- ${cchConfig.date_css}
+ ${this.cchConfig.date_css}
}
`;
- clockIronIcon.parentNode.insertBefore(style, clockIronIcon);
- }
-
- const clockFormat = {
- hour12: cchConfig.clock_format != 24,
- hour: "2-digit",
- minute: "2-digit"
- };
- updateClock(clockElement, clockFormat);
-}
-
-function updateClock(clock, clockFormat) {
- let date = new Date();
- let locale = cchConfig.date_locale || hass.language;
- let time = date.toLocaleTimeString([], clockFormat);
- let options = {
- weekday: "short",
- month: "2-digit",
- day: "2-digit"
- };
- date = cchConfig.clock_date
- ? `
${hass.user.name}
+${cch.hass.user.name}