Increase font size of numbers on manual alarm panel keypad

Just updated to the HA 0.88.1 and the new manual alarm panel is a big improvement visually. However, the numbers on the keypad is too small. I know a “style” parameter is supported however, there is little documentation on how to use it. Any ideas?

style is css. So when you need to find out how to do something, google search what you want to do and include css.

font-size: 12px

https://www.w3schools.com/css/css_font.asp

It can be hard coded instead of css. But you seem to have eaten barb wire today. This is the second post in a row where I consider your answers to be rude.

1 Like

Ok, wasn’t trying to be rude. Was just trying to let him know how to search for undocumented style properties. Sorry I offended you. The take away from the post was that the information is outside HA. Which people don’t know. How is that rude? Because I didn’t pepper it with frill?

A link to a general CSS site wont help. The source code for this card reveals a clue to the syntax for the style parameters.
ha-card {
–alarm-color-disarmed: var(–label-badge-green);
–alarm-color-pending: var(–label-badge-yellow);
–alarm-color-triggered: var(–label-badge-red);
–alarm-color-armed: var(–label-badge-red);
–alarm-color-autoarm: rgba(0, 153, 255, .1);
–alarm-state-color: var(–alarm-color-armed);
–base-unit: ${this._config.scale};
font-size: calc(var(–base-unit));

These are the alarm card’s style attributes. There’s one for font-size however, it references a “base-unit” value. I suspect that if you multiply that value by some factor it’ll increase the font size of ALL characters in the HA card.

There is a style code section for “alpha” - the keypad I presume.
.alpha {
position: absolute;
text-align: center;
bottom: calc(var(–base-unit) * 0.1);
color: var(–secondary-text-color);
font-size: calc(var(–base-unit) * 0.7);

The question is: Is changing the font even supported? If the example style is any indicator of it’s flexibility then, perhaps no. Maybe you can only change badge label colors.

This will only influence the badge not the fonts on the card
this card is hard coded for the fonts card modder won’t do the trick

It was a link to all the font css, not the general css site. Many of the cards are trial and error with css in the style section. So linking the css was useful because it gives you options to try.

It may not be supported by the card, I don’t know off the top of my head. You can use card modder to adjust it.

It’s a custom card that allows you to use pretty much any css within reason. Font should be one of the things you can change.

What about setting the theme on the card? Is the font hard coded in regards to the theme or just straight hard coded?

tried that it didn’t change the size of the font either i guess the thing to do is to pull a request about that.

If you are using the custom card not the default home assistant one you can add ‘‘scale: 30px’’ and it will increase the size of the fonts.

On the home assistant native alarm code it is as i suspected the font style is hard coded.
you can see below is the code for the card and the base-unit is hard coded.

ha-card {
      padding-bottom: 16px;
      position: relative;
      --alarm-color-disarmed: var(--label-badge-green);
      --alarm-color-pending: var(--label-badge-yellow);
      --alarm-color-triggered: var(--label-badge-red);
      --alarm-color-armed: var(--label-badge-red);
      --alarm-color-autoarm: rgba(0, 153, 255, 0.1);
      --alarm-state-color: var(--alarm-color-armed);
      --base-unit: 15px;
      font-size: calc(var(--base-unit));
    }

Thanks for all the help. I suppose I’ll make sure I have my glasses on when I disarm.

Seem like the original poster didn’t get his answer, I’m also having problem changing the keypad font size. I tried changing the css style for .pad .mwc-button , but all other attributes like width and height takes effect, except font-size. Anyone know why?

Using HA 0.95

.pad mwc-button {
        position: relative;
        padding: calc(var(--base-unit)*0.5);
        font-size: calc(var(--base-unit) * 2);
        min-width: calc(var(--base-unit) * 5);
      }

I ended up changing all the keypad buttons to standard button instead of mwc-button. Looks much better now

Alarm_panel

1 Like

I used card-mod to make them bigger and white to match my theme:

type: alarm-panel
name: House Alarm
entity: alarm_control_panel.home_alarm
states:
  - arm_away
  - arm_night
style:
  .: |
    ha-card {
      --mdc-theme-primary: white;
    }
  "#keypad mwc-button":
    $: |
      button {
        font-size: 32px !important;
      }
  "#keypad mwc-button:nth-of-type(12)":
    $: |
      button {
        font-size: 18px !important;
      }

Looks good, can you share your card-mod setup?

Can you please detail how you changed to standard button?

I modified the custom alarm card js file. Here’s the code if you are interested.

class AlarmControlPanelCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this._icons = {
      'armed_away': 'mdi:shield-lock',
      'armed_custom_bypass': 'mdi:security',
      'armed_home': 'mdi:shield-home',
      'armed_night': 'mdi:shield-home',
      'disarmed': 'mdi:shield-check',
      'pending': 'mdi:shield-outline',
      'triggered': 'hass:bell-ring',
    }
  }

  set hass(hass) {
    const entity = hass.states[this._config.entity];

    if (entity) {
      this.myhass = hass;
      if(!this.shadowRoot.lastChild) {
        this._createCard(entity);
      }
      if (entity.state != this._state) {
        this._state = entity.state;
        this._updateCardContent(entity);
      }
    }
  }

  _createCard(entity) {
    const config = this._config;

    const card = document.createElement('ha-card');
    card.innerHTML = `
      ${this._iconLabel()}
      ${config.title ? '<div id="state-text"></div>' : ''}
    `;
    const content = document.createElement('div');
    content.id = "content";
    content.style.display = config.auto_hide ? 'none' : '';
    //`<paper-input label='${this._label("ui.card.alarm_control_panel.code")}' type="password"></paper-input>` : ''}
    content.innerHTML = `
      ${this._actionButtons()}
      ${entity.attributes.code_format ?
          `<paper-input type="number"></paper-input>` : ''}
      ${this._keypad(entity)}
    `;
    card.appendChild(this._style(config.style, entity));
    card.appendChild(content);
    this.shadowRoot.appendChild(card);

    this._setupInput();
    this._setupKeypad();
    this._setupActions();
  }

  connectedCallback() {
  }

  setConfig(config) {
    if (!config.entity || config.entity.split(".")[0] !== "alarm_control_panel") {
      throw new Error('Please specify an entity from alarm_control_panel domain.');
    }
    if (config.auto_enter) {
      if (!config.auto_enter.code_length || !config.auto_enter.arm_action) {
        throw new
          Error('Specify both code_length and arm_action when using auto_enter.');
      }
      this._arm_action = config.auto_enter.arm_action;
    }
    if (!config.states) config.states = ['arm_away', 'arm_home'];
    if (!config.scale) config.scale = '15px';
    this._config = Object.assign({}, config);

    const root = this.shadowRoot;
    if (root.lastChild) root.removeChild(root.lastChild);
  }

  _updateCardContent(entity) {
    const root = this.shadowRoot;
    const card = root.lastChild;
    const config = this._config;

    const state_str = "state.alarm_control_panel." + this._state;
    if (config.title) {
      card.header = config.title;
      root.getElementById("state-text").innerHTML = this._label(state_str);
      root.getElementById("state-text").className = `state ${this._state}`;
    } else {
      card.header = this._label(state_str);
    }

    root.getElementById("state-icon").setAttribute("icon",
      this._icons[this._state] || 'mdi:shield-outline');
    root.getElementById("badge-icon").className = this._state;

    var iconText = this._stateIconLabel(this._state);
    if (iconText === "") {
      root.getElementById("icon-label").style.display = "none";
    } else {
      root.getElementById("icon-label").style.display = "";
      if (iconText.length > 5) {
        root.getElementById("icon-label").className = "label big";
      } else {
	root.getElementById("icon-label").className = "label";
      }
      root.getElementById("icon-text").innerHTML = iconText;
    }

    const armVisible = (this._state === 'disarmed');
    root.getElementById("arm-actions").style.display = armVisible ? "" : "none";
    root.getElementById("disarm-actions").style.display = armVisible ? "none" : "";
  }

  _actionButtons() {
    const armVisible = (this._state === 'disarmed');
    return `
      <div id="arm-actions" class="actions">
        ${this._config.states.map(el => `${this._actionButton(el)}`).join('')}
      </div>
      <div id="disarm-actions" class="actions">
        ${this._actionButton('disarm')}
      </div>`;
  }

  _stateIconLabel(state) {
    const stateLabel = state.split("_").pop();
    return stateLabel === "disarmed" ||
      stateLabel === "triggered" ||
      !stateLabel
      ? ""
      : stateLabel;
  }

  _iconLabel() {
    return `
      <ha-label-badge-icon id="badge-icon">
        <div class="badge-container" id="badge-container">
          <div class="label-badge" id="badge">
            <div class="value">
              <ha-icon id="state-icon"/>
            </div>
            <div class="label" id="icon-label">
              <span id="icon-text"/>
            </div>
          </div>
        </div>
    </ha-label-badge-icon>`;	  
  }

  _actionButton(state) {
    return `<mwc-button outlined id="${state}">
      ${this._label("ui.card.alarm_control_panel." + state)}</mwc-button>`;
  }

  _setupActions() {
    const root = this.shadowRoot;
    const card = this.shadowRoot.lastChild;
    const config = this._config;

    if (config.auto_hide) {
      root.getElementById("badge-icon").addEventListener('click', event => {
        var content = root.getElementById("content");
        if (content.style.display === 'none') {
          content.style.display = '';
        } else {
          content.style.display = 'none';
        }
      })
    }

    if (config.auto_enter) {
      card.querySelectorAll(".actions mwc-button").forEach(element => {
        element.classList.remove('autoarm');
        if (element.id === this._arm_action || element.id === 'disarm') {
          element.classList.add('autoarm');
        }
        element.addEventListener('click', event => {
          card.querySelectorAll(".actions mwc-button").forEach(element => {
            element.classList.remove('autoarm');
          })
          element.classList.add('autoarm');
          if (element.id !== 'disarm') this._arm_action = element.id;
        })
      })
    } else {
      card.querySelectorAll(".actions mwc-button").forEach(element => {
        element.addEventListener('click', event => {
          const input = card.querySelector('paper-input');
          const value = input ? input.value : '';
          this._callService(element.id, value);
        })
      })
    }
  }

  _callService(service, code) {
    const input = this.shadowRoot.lastChild.querySelector("paper-input");
    this.myhass.callService('alarm_control_panel', `alarm_${service}`, {
      entity_id: this._config.entity,
      code: code,
    });
    if (input) input.value = '';
  }

  _setupInput() {
    if (this._config.auto_enter) {
      const input = this.shadowRoot.lastChild.querySelector("paper-input");
      input.addEventListener('input', event => { this._autoEnter() })
    }
  }

  _setupKeypad() {
    const root = this.shadowRoot;

    const input = root.lastChild.querySelector('paper-input');
    root.querySelectorAll(".pad button").forEach(element => {
      if (element.getAttribute('value') === 
        this._label("ui.card.alarm_control_panel.clear_code")) {
        element.addEventListener('click', event => {
          input.value = '';
        })
      } else {
        element.addEventListener('click', event => {
          input.value += element.getAttribute('value');
          this._autoEnter();
        })
      }
    });
  }

  _autoEnter() {
    const config = this._config;

    if (config.auto_enter) {
      const card = this.shadowRoot.lastChild;
      const code = card.querySelector("paper-input").value;
      if (code.length == config.auto_enter.code_length) {
        const service = card.querySelector(".actions .autoarm").id;
        this._callService(service, code);
      }
    }
  }

  _keypad(entity) {
    if (this._config.hide_keypad || !entity.attributes.code_format) return '';

    return `
      <div class="pad">
        <div>
          ${this._keypadButton("1", "")}
          ${this._keypadButton("4", "GHI")}
          ${this._keypadButton("7", "PQRS")}
        </div>
        <div>
          ${this._keypadButton("2", "ABC")}
          ${this._keypadButton("5", "JKL")}
          ${this._keypadButton("8", "TUV")}
          ${this._keypadButton("0", "")}
        </div>
        <div>
          ${this._keypadButton("3", "DEF")}
          ${this._keypadButton("6", "MNO")}
          ${this._keypadButton("9", "WXYZ")}
          ${this._keypadButton(this._label("ui.card.alarm_control_panel.clear_code"), "")}
        </div>
      </div>`
  }

  _keypadButton(button, alpha) {
    let letterHTML = '';
    if (this._config.display_letters) {
      letterHTML = `<div class='alpha'>${alpha}</div>`
    }
    return `<button value="${button}">${button}${letterHTML}</button>`;
  }

  _style(icon_style, entity) {
    const style = document.createElement('style');
    style.textContent = `
      ha-card {
        ${(this._config.hide_keypad ||
	   !entity.attributes.code_format) ? 'padding-bottom: 16px;' : '' }
        position: relative;
        --alarm-color-disarmed: var(--label-badge-green);
        --alarm-color-pending: var(--label-badge-yellow);
        --alarm-color-triggered: var(--label-badge-red);
        --alarm-color-armed: var(--label-badge-red);
        --alarm-color-autoarm: rgba(0, 153, 255, .1);
        --alarm-state-color: var(--alarm-color-armed);
        --base-unit: ${this._config.scale};
        font-size: calc(var(--base-unit));
        ${icon_style}
      }
      ha-icon {
        color: var(--alarm-state-color);
	    width: 24px;
	    height: 24px;
      }
      ha-label-badge-icon {
        --ha-label-badge-color: var(--alarm-state-color);
        --label-badge-text-color: var(--alarm-state-color);
        --label-badge-background-color: var(--paper-card-background-color);
        color: var(--alarm-state-color);
        position: absolute;
        right: 12px;
        top: 12px;
      }
      .badge-container {
        display: inline-block;
        text-align: center;
        vertical-align: top;
      }
      .label-badge {
        position: relative;
        display: block;
        margin: 0 auto;
        width: var(--ha-label-badge-size, 2.5em);
        text-align: center;
        height: var(--ha-label-badge-size, 2.5em);
        line-height: var(--ha-label-badge-size, 2.5em);
        font-size: var(--ha-label-badge-font-size, 1.5em);
        border-radius: 50%;
        border: 0.1em solid var(--ha-label-badge-color, var(--primary-color));
        color: var(--label-badge-text-color, rgb(76, 76, 76));
        white-space: nowrap;
        background-color: var(--label-badge-background-color, white);
        background-size: cover;
        transition: border 0.3s ease-in-out;
      }
      .label-badge .value {
        font-size: 90%;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .label-badge .value.big {
        font-size: 70%;
      }
      .label-badge .label {
        position: absolute;
        bottom: -1em;
        /* Make the label as wide as container+border. (parent_borderwidth / font-size) */
        left: -0.2em;
        right: -0.2em;
        line-height: 1em;
        font-size: 0.5em;
      }
      .label-badge .label span {
        box-sizing: border-box;
        max-width: 100%;
        display: inline-block;
        background-color: var(--ha-label-badge-color, var(--primary-color));
        color: var(--ha-label-badge-label-color, white);
        border-radius: 1em;
        padding: 9% 16% 8% 16%; /* mostly apitalized text, not much descenders => bit more top margin */
        font-weight: 500;
        overflow: hidden;
        text-transform: uppercase;
        text-overflow: ellipsis;
        transition: background-color 0.3s ease-in-out;
        text-transform: var(--ha-label-badge-label-text-transform, uppercase);
      }
      .label-badge .label.big span {
        font-size: 90%;
        padding: 10% 12% 7% 12%; /* push smaller text a bit down to center vertically */
      }
      .badge-container .title {
        margin-top: 1em;
        font-size: var(--ha-label-badge-title-font-size, 0.9em);
        width: var(--ha-label-badge-title-width, 5em);
        font-weight: var(--ha-label-badge-title-font-weight, 400);
        overflow: hidden;
        text-overflow: ellipsis;
        line-height: normal;
      }
      .disarmed {
        --alarm-state-color: var(--alarm-color-disarmed);
      }
      .triggered {
        --alarm-state-color: var(--alarm-color-triggered);
        animation: pulse 1s infinite;
      }
      .arming {
        --alarm-state-color: var(--alarm-color-pending);
        animation: pulse 1s infinite;
      }
      .pending {
        --alarm-state-color: var(--alarm-color-pending);
        animation: pulse 1s infinite;
      }
      @keyframes pulse {
        0% {
          --ha-label-badge-color: var(--alarm-state-color);
        }
        100% {
          --ha-label-badge-color: rgba(255, 153, 0, 0.3);
        }
      }
      paper-input {
        margin: auto;
        max-width: 200px;
        font-size: calc(var(--base-unit));
      }
      .state {
        margin-left: 20px;
        font-size: calc(var(--base-unit) * 0.9);
        position: relative;
        bottom: 16px;
        color: var(--alarm-state-color);
        animation: none;
      }
      .pad {
        display: flex;
        justify-content: center;
      }
      .pad div {
        display: flex;
        flex-direction: column;
      }
      .pad button {
        position: relative;
        padding: calc(var(--base-unit)*0.5);
        font-size: calc(var(--base-unit) * 1.6);
        width: calc(var(--base-unit) * 6);
        margin: 8px;
        #background-color: var(--primary-background-color);
        background-color: var(--primary-color);
        border-width: 2px;
        border-style: solid;
        border-color: var(--primary-color);
        border-radius: 4px;
        #color: var(--primary-color);
        color: var(--text-primary-color);
      }
      .pad button:focus {
        background-color: var(--dark-primary-color);
        border-color: var(--primary-color);
        border-width: 2px;
        outline: none;
      }
      .actions {
        margin: 0 8px;
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        font-size: calc(var(--base-unit) * 1);
      }
      .actions mwc-button {
        min-width: calc(var(--base-unit) * 9);
        color: var(--primary-color);
		margin-top: 0px;
		margin-right: 4px;
		margin-bottom: 0px;
		margin-left: 4px;
      }
      .actions .autoarm {
        background: var(--alarm-color-autoarm);
      }
      mwc-button#disarm {
        color: var(--google-red-500);
      }
      .alpha {
        position: absolute;
        text-align: center;
        bottom: calc(var(--base-unit) * 0.1);
        color: var(--secondary-text-color);
        font-size: calc(var(--base-unit) * 0.7);
      }
    `;
    return style;
  }

  _label(label, default_label=undefined) {
    // Just show "raw" label; useful when want to see underlying const
    // so you can define your own label.
    if (this._config.show_label_ids) return label;

    if (this._config.labels && this._config.labels[label])
      return this._config.labels[label];

    const lang = this.myhass.selectedLanguage || this.myhass.language;
    const translations = this.myhass.resources[lang];
    if (translations && translations[label]) return translations[label];

    if (default_label) return default_label;

    // If all else fails then pretify the passed in label const
    const last_bit = label.split('.').pop();
    return last_bit.split('_').join(' ').replace(/^\w/, c => c.toUpperCase());
  }

  getCardSize() {
    return 1;
  }
}

customElements.define('alarm_control_panel-card', AlarmControlPanelCard);

I modified from this copy: https://github.com/JumpMaster/custom-lovelace

If the original writer is reading this, give me a msg if you want me to do a fork and pull.

1 Like

I am probably missing something obvious but how does this make the font bigger, when I use this as a custom card the number pad fonts are still very small?

Anyways, this is the code I am using, if anyone can see where the style for the keypad text size can be edited please let me know.
As you can see I have been able to change everything except the number size.

class AlarmControlPanelCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this._icons = {
      'armed_away': 'mdi:shield-lock',
      'armed_custom_bypass': 'mdi:security',
      'armed_home': 'mdi:shield-home',
      'armed_night': 'mdi:shield-home',
      'disarmed': 'mdi:shield-check',
      'pending': 'mdi:shield-outline',
      'triggered': 'hass:bell-ring',
    }
  }

  set hass(hass) {
    const entity = hass.states[this._config.entity];

    if (entity) {
      this.myhass = hass;
      if(!this.shadowRoot.lastChild) {
        this._createCard(entity);
      }
      if (entity.state != this._state) {
        this._state = entity.state;
        this._updateCardContent(entity);
      }
    }
  }

  _createCard(entity) {
    const config = this._config;

    const card = document.createElement('ha-card');
    card.innerHTML = `
      ${this._iconLabel()}
      ${config.title ? '<div id="state-text"></div>' : ''}
    `;
    const content = document.createElement('div');
    content.id = "content";
    content.style.display = config.auto_hide ? 'none' : '';
    content.innerHTML = `
      ${this._actionButtons()}
      ${entity.attributes.code_format ?
          `<paper-input label='${this._label("ui.card.alarm_control_panel.code")}'
          type="text"></paper-input>` : ''}
      ${this._keypad(entity)}
    `;
    card.appendChild(this._style(config.style, entity));
    card.appendChild(content);
    this.shadowRoot.appendChild(card);

    this._setupInput();
    this._setupKeypad();
    this._setupActions();
  }

  connectedCallback() {
  }

  setConfig(config) {
    if (!config.entity || config.entity.split(".")[0] !== "alarm_control_panel") {
      throw new Error('Please specify an entity from alarm_control_panel domain.');
    }
    if (config.auto_enter) {
      if (!config.auto_enter.code_length || !config.auto_enter.arm_action) {
        throw new
          Error('Specify both code_length and arm_action when using auto_enter.');
      }
      this._arm_action = config.auto_enter.arm_action;
    }
    if (!config.states) config.states = ['arm_away', 'arm_home'];
    if (!config.scale) config.scale = '15px';
    this._config = Object.assign({}, config);

    const root = this.shadowRoot;
    if (root.lastChild) root.removeChild(root.lastChild);
  }

  _updateCardContent(entity) {
    const root = this.shadowRoot;
    const card = root.lastChild;
    const config = this._config;

    const state_str = "state.alarm_control_panel." + this._state;
    if (config.title) {
      card.header = config.title;
      root.getElementById("state-text").innerHTML = this._label(state_str);
      root.getElementById("state-text").className = `state ${this._state}`;
    } else {
      card.header = this._label(state_str);
    }

    root.getElementById("state-icon").setAttribute("icon",
      this._icons[this._state] || 'mdi:shield-outline');
    root.getElementById("badge-icon").className = this._state;

    var iconText = this._stateIconLabel(this._state);
    if (iconText === "") {
      root.getElementById("icon-label").style.display = "none";
    } else {
      root.getElementById("icon-label").style.display = "";
      if (iconText.length > 5) {
        root.getElementById("icon-label").className = "label big";
      } else {
	root.getElementById("icon-label").className = "label";
      }
      root.getElementById("icon-text").innerHTML = iconText;
    }

    const armVisible = (this._state === 'disarmed');
    root.getElementById("arm-actions").style.display = armVisible ? "" : "none";
    root.getElementById("disarm-actions").style.display = armVisible ? "none" : "";
  }

  _actionButtons() {
    const armVisible = (this._state === 'disarmed');
    return `
      <div id="arm-actions" class="actions">
        ${this._config.states.map(el => `${this._actionButton(el)}`).join('')}
      </div>
      <div id="disarm-actions" class="actions">
        ${this._actionButton('disarm')}
      </div>`;
  }

  _stateIconLabel(state) {
    const stateLabel = state.split("_").pop();
    return stateLabel === "disarmed" ||
      stateLabel === "triggered" ||
      !stateLabel
      ? ""
      : stateLabel;
  }

  _iconLabel() {
    return `
      <ha-label-badge-icon id="badge-icon">
        <div class="badge-container" id="badge-container">
          <div class="label-badge" id="badge">
            <div class="value">
              <ha-icon id="state-icon"/>
            </div>
            <div class="label" id="icon-label">
              <span id="icon-text"/>
            </div>
          </div>
        </div>
    </ha-label-badge-icon>`;	  
  }

  _actionButton(state) {
    return `<mwc-button outlined id="${state}">
      ${this._label("ui.card.alarm_control_panel." + state)}</mwc-button>`;
  }

  _setupActions() {
    const root = this.shadowRoot;
    const card = this.shadowRoot.lastChild;
    const config = this._config;

    if (config.auto_hide) {
      root.getElementById("badge-icon").addEventListener('click', event => {
        var content = root.getElementById("content");
        if (content.style.display === 'none') {
          content.style.display = '';
        } else {
          content.style.display = 'none';
        }
      })
    }

    if (config.auto_enter) {
      card.querySelectorAll(".actions mwc-button").forEach(element => {
        element.classList.remove('autoarm');
        if (element.id === this._arm_action || element.id === 'disarm') {
          element.classList.add('autoarm');
        }
        element.addEventListener('click', event => {
          card.querySelectorAll(".actions mwc-button").forEach(element => {
            element.classList.remove('autoarm');
          })
          element.classList.add('autoarm');
          if (element.id !== 'disarm') this._arm_action = element.id;
        })
      })
    } else {
      card.querySelectorAll(".actions mwc-button").forEach(element => {
        element.addEventListener('click', event => {
          const input = card.querySelector('paper-input');
          const value = input ? input.value : '';
          this._callService(element.id, value);
        })
      })
    }
  }

  _callService(service, code) {
    const input = this.shadowRoot.lastChild.querySelector("paper-input");
    this.myhass.callService('alarm_control_panel', `alarm_${service}`, {
      entity_id: this._config.entity,
      code: code,
    });
    if (input) input.value = '';
  }

  _setupInput() {
    if (this._config.auto_enter) {
      const input = this.shadowRoot.lastChild.querySelector("paper-input");
      input.addEventListener('input', event => { this._autoEnter() })
    }
  }

  _setupKeypad() {
    const root = this.shadowRoot;

    const input = root.lastChild.querySelector('paper-input');
    root.querySelectorAll(".pad mwc-button").forEach(element => {
      if (element.getAttribute('value') === 
        this._label("ui.card.alarm_control_panel.clear_code")) {
        element.addEventListener('click', event => {
          input.value = '';
        })
      } else {
        element.addEventListener('click', event => {
          input.value += element.getAttribute('value');
          this._autoEnter();
        })
      }
    });
  }

  _autoEnter() {
    const config = this._config;

    if (config.auto_enter) {
      const card = this.shadowRoot.lastChild;
      const code = card.querySelector("paper-input").value;
      if (code.length == config.auto_enter.code_length) {
        const service = card.querySelector(".actions .autoarm").id;
        this._callService(service, code);
      }
    }
  }

  _keypad(entity) {
    if (this._config.hide_keypad || !entity.attributes.code_format) return '';

    return `
      <div class="pad">
        <div>
          ${this._keypadButton("1", "")}
          ${this._keypadButton("4", "GHI")}
          ${this._keypadButton("7", "PQRS")}
        </div>
        <div>
          ${this._keypadButton("2", "ABC")}
          ${this._keypadButton("5", "JKL")}
          ${this._keypadButton("8", "TUV")}
          ${this._keypadButton("0", "")}
        </div>
        <div>
          ${this._keypadButton("3", "DEF")}
          ${this._keypadButton("6", "MNO")}
          ${this._keypadButton("9", "WXYZ")}
          ${this._keypadButton(this._label("ui.card.alarm_control_panel.clear_code"), "")}
        </div>
      </div>`
  }

  _keypadButton(button, alpha) {
    let letterHTML = '';
    if (this._config.display_letters) {
      letterHTML = `<div class='alpha'>${alpha}</div>`
    }
    return `<mwc-button dense value="${button}">${button}${letterHTML}
      </mwc-button>`;
  }

  _style(icon_style, entity) {
    const style = document.createElement('style');
    style.textContent = `
      ha-card {
        ${(this._config.hide_keypad ||
	   !entity.attributes.code_format) ? 'padding-bottom: 16px;' : '' }
        position: relative;
        --alarm-color-disarmed: var(--label-badge-green);
        --alarm-color-pending: var(--label-badge-yellow);
        --alarm-color-triggered: var(--label-badge-red);
        --alarm-color-armed: var(--label-badge-red);
        --alarm-color-autoarm: rgba(0, 153, 255, .1);
        --alarm-state-color: var(--alarm-color-armed);
        --base-unit: ${this._config.scale};
        font-size: calc(var(--base-unit) * 1.5);
        ${icon_style}
      }
      ha-icon {
        color: var(--alarm-state-color);
        width: calc(var(--base-unit) * 3);
        height: calc(var(--base-unit) * 3);
      }
      ha-label-badge-icon {
        --ha-label-badge-color: var(--alarm-state-color);
        --label-badge-text-color: var(--alarm-state-color);
        --label-badge-background-color: var(--paper-card-background-color);
        color: var(--alarm-state-color);
        position: absolute;
        right: 12px;
        top: 12px;
        margin-bottom: calc(var(--base-unit));
      }
      .badge-container {
        display: inline-block;
        text-align: center;
        vertical-align: top;
      }
      .label-badge {
        position: relative;
        display: block;
        margin: 0 auto;
        width: var(--ha-label-badge-size, 2.5em);
        text-align: center;
        height: var(--ha-label-badge-size, 2.5em);
        line-height: var(--ha-label-badge-size, 2.5em);
        font-size: calc(var(--base-unit) * 1.6);
        border-radius: 50%;
        border: 0.15em solid var(--ha-label-badge-color, var(--primary-color));
        color: var(--label-badge-text-color, rgb(76, 76, 76));
        white-space: nowrap;
        background-color: var(--label-badge-background-color, white);
        background-size: cover;
        transition: border 0.3s ease-in-out;
      }
      .label-badge .value {
        font-size: 90%;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .label-badge .value.big {
        font-size: 70%;
      }
      .label-badge .label {
        position: absolute;
        bottom: -1em;
        /* Make the label as wide as container+border. (parent_borderwidth / font-size) */
        left: -0.2em;
        right: -0.2em;
        line-height: 1em;
        font-size: 0.5em;
      }
      .label-badge .label span {
        box-sizing: border-box;
        max-width: 100%;
        display: inline-block;
        background-color: var(--ha-label-badge-color, var(--primary-color));
        color: var(--ha-label-badge-label-color, white);
        border-radius: 1em;
        padding: 9% 16% 8% 16%; /* mostly apitalized text, not much descenders => bit more top margin */
        font-weight: 500;
        overflow: hidden;
        text-transform: uppercase;
        text-overflow: ellipsis;
        transition: background-color 0.3s ease-in-out;
        text-transform: var(--ha-label-badge-label-text-transform, uppercase);
      }
      .label-badge .label.big span {
        font-size: 90%;
        padding: 10% 12% 7% 12%; /* push smaller text a bit down to center vertically */
      }
      .badge-container .title {
        margin-top: 1em;
        font-size: var(--ha-label-badge-title-font-size, 0.9em);
        width: var(--ha-label-badge-title-width, 5em);
        font-weight: var(--ha-label-badge-title-font-weight, 400);
        overflow: hidden;
        text-overflow: ellipsis;
        line-height: normal;
      }
      .disarmed {
        --alarm-state-color: var(--alarm-color-disarmed);
      }
      .triggered {
        --alarm-state-color: var(--alarm-color-triggered);
        animation: pulse 1s infinite;
      }
      .arming {
        --alarm-state-color: var(--alarm-color-pending);
        animation: pulse 1s infinite;
      }
      .pending {
        --alarm-state-color: var(--alarm-color-pending);
        animation: pulse 1s infinite;
      }
      @keyframes pulse {
        0% {
          --ha-label-badge-color: var(--alarm-state-color);
        }
        100% {
          --ha-label-badge-color: rgba(255, 153, 0, 0.3);
        }
      }
      paper-input {
        margin-top: 0px;;
        margin-left: auto;
        margin-right: auto;
        margin-bottom: 0px;
        max-width: 200px;
        height: fit-content;
      }
      mwc-button {
        margin-right: 5px;
        margin-left: 5px;
        justify-content: center;
      }
      .state {
        margin-left: calc(var(--base-unit) * 1.2);
        font-size: calc(var(--base-unit) * 1.2);
        text-transform: uppercase;
        position: relative;
        bottom: 16px;
        color: var(--alarm-state-color);
        animation: none;
      }
      .pad {
        display: flex;
        justify-content: center;
        margin-left: 40px;
        margin-right: 40px;
        padding: 10px;
      }
      .pad div {
        display: flex;
        flex-direction: column;
        margin-top: 0px;
        margin-left: auto;
        margin-right: auto;
        margin-bottom: auto;
        padding: 0px;
        justify-content: center;
      }
      .pad mwc-button {
        min-height: calc(var(--base-unit) * 4);
        min-width: calc(var(--base-unit) * 5);
        margin-top: 10px;
        margin-bottom: 10px;
        padding: 5px;
        border: solid;
        border-width: 3px;
        border-radius: 15px;
        border-color: var(--primary-color);
        font-size: 28pt;
      }
      .pad mwc-button button.mdc-button.mdc-button--dense {
        font-size: 28pt;
      }
    
      .actions {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        margin-top: calc(var(--base-unit) * 0.5);
      }
      .actions .autoarm {
        background: var(--alarm-color-autoarm);
      }  
      mwc-button#disarm {
        color: red;
      }
      .actions mwc-button {
        min-height: calc(var(--base-unit) * 2.5);
        min-width: calc(var(--base-unit) * 8);
      }
      .alpha {
        position: absolute;
        text-align: center;
        bottom: calc(var(--base-unit) * 0.1);
        color: var(--secondary-text-color);
        font-size: calc(var(--base-unit) * 1.5);
      }
    `;
    return style;
  }

  _label(label, default_label=undefined) {
    // Just show "raw" label; useful when want to see underlying const
    // so you can define your own label.
    if (this._config.show_label_ids) return label;

    if (this._config.labels && this._config.labels[label])
      return this._config.labels[label];

    const lang = this.myhass.selectedLanguage || this.myhass.language;
    const translations = this.myhass.resources[lang];
    if (translations && translations[label]) return translations[label];

    if (default_label) return default_label;

    // If all else fails then pretify the passed in label const
    const last_bit = label.split('.').pop();
    return last_bit.split('_').join(' ').replace(/^\w/, c => c.toUpperCase());
  }

  getCardSize() {
    return 1;
  }
}

customElements.define('alarm_control_panel-card', AlarmControlPanelCard);