Guest User

Untitled

a guest
Mar 8th, 2020
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
CSS 11.87 KB | None | 0 0
  1. const LitElement = Object.getPrototypeOf(
  2.   customElements.get("ha-panel-lovelace")
  3. );
  4. const html = LitElement.prototype.html;
  5.  
  6. const weatherIconsDay = {
  7.   clear: "day",
  8.   "clear-night": "night",
  9.   cloudy: "cloudy",
  10.   fog: "cloudy",
  11.   hail: "rainy-7",
  12.   lightning: "thunder",
  13.   "lightning-rainy": "thunder",
  14.   partlycloudy: "cloudy-day-3",
  15.   pouring: "rainy-6",
  16.   rainy: "rainy-5",
  17.   snowy: "snowy-6",
  18.   "snowy-rainy": "rainy-7",
  19.   sunny: "day",
  20.   windy: "cloudy",
  21.   "windy-variant": "cloudy-day-3",
  22.   exceptional: "!!"
  23. };
  24.  
  25. const weatherIconsNight = {
  26.   ...weatherIconsDay,
  27.   clear: "night",
  28.   sunny: "night",
  29.   partlycloudy: "cloudy-night-3",
  30.   "windy-variant": "cloudy-night-3"
  31. };
  32.  
  33. const windDirections = [
  34.   "N",
  35.   "NNE",
  36.   "NE",
  37.   "ENE",
  38.   "E",
  39.   "ESE",
  40.   "SE",
  41.   "SSE",
  42.   "S",
  43.   "SSW",
  44.   "SW",
  45.   "WSW",
  46.   "W",
  47.   "WNW",
  48.   "NW",
  49.   "NNW",
  50.   "N"
  51. ];
  52.  
  53. const fireEvent = (node, type, detail, options) => {
  54.   options = options || {};
  55.   detail = detail === null || detail === undefined ? {} : detail;
  56.   const event = new Event(type, {
  57.     bubbles: options.bubbles === undefined ? true : options.bubbles,
  58.     cancelable: Boolean(options.cancelable),
  59.     composed: options.composed === undefined ? true : options.composed
  60.   });
  61.   event.detail = detail;
  62.   node.dispatchEvent(event);
  63.   return event;
  64. };
  65.  
  66. function hasConfigOrEntityChanged(element, changedProps) {
  67.   if (changedProps.has("_config")) {
  68.     return true;
  69.   }
  70.  
  71.   const oldHass = changedProps.get("hass");
  72.   if (oldHass) {
  73.     return (
  74.       oldHass.states[element._config.entity] !==
  75.         element.hass.states[element._config.entity] ||
  76.       oldHass.states["sun.sun"] !== element.hass.states["sun.sun"]
  77.     );
  78.   }
  79.  
  80.   return true;
  81. }
  82.  
  83. class WeatherCard extends LitElement {
  84.   static get properties() {
  85.     return {
  86.       _config: {},
  87.       hass: {}
  88.     };
  89.   }
  90.  
  91.   static async getConfigElement() {
  92.     await import("./weather-card-editor.js");
  93.     return document.createElement("weather-card-editor");
  94.   }
  95.  
  96.   static getStubConfig() {
  97.     return {};
  98.   }
  99.  
  100.   setConfig(config) {
  101.     if (!config.entity) {
  102.       throw new Error("Please define a weather entity");
  103.     }
  104.     this._config = config;
  105.   }
  106.  
  107.   shouldUpdate(changedProps) {
  108.     return hasConfigOrEntityChanged(this, changedProps);
  109.   }
  110.  
  111.   render() {
  112.     if (!this._config || !this.hass) {
  113.       return html``;
  114.     }
  115.  
  116.     const stateObj = this.hass.states[this._config.entity];
  117.     const localTemp = this.hass.states[this._config.local_sensor];
  118.  
  119.     if (!stateObj) {
  120.       return html`
  121.         <style>
  122.           .not-found {
  123.             flex: 1;
  124.             background-color: yellow;
  125.             padding: 8px;
  126.           }
  127.         </style>
  128.         <ha-card>
  129.           <div class="not-found">
  130.             Entity not available: ${this._config.entity}
  131.           </div>
  132.         </ha-card>
  133.       `;
  134.     }
  135.  
  136.     const lang = this.hass.selectedLanguage || this.hass.language;
  137.  
  138.     const next_rising = new Date(
  139.       this.hass.states["sun.sun"].attributes.next_rising
  140.     );
  141.     const next_setting = new Date(
  142.       this.hass.states["sun.sun"].attributes.next_setting
  143.     );
  144.  
  145.     return html`
  146.       ${this.renderStyle()}
  147.       <ha-card @click="${this._handleClick}">
  148.         <span
  149.           class="icon bigger"
  150.           style="background: none, url(${
  151.            this.getWeatherIcon(
  152.              stateObj.state.toLowerCase(),
  153.              this.hass.states["sun.sun"].state
  154.            )
  155.          }) no-repeat; background-size: contain;"
  156.           >${stateObj.state}
  157.         </span>
  158.         ${
  159.           this._config.name
  160.             ? html`
  161.                 <span class="title"> ${this._config.name} </span>
  162.               `
  163.             : ""
  164.         }
  165.         <span class="temp"
  166.           >${
  167.             this.getUnit("temperature") == "Β°F"
  168.               ? Math.round(localTemp.state)
  169.               : localTemp.state
  170.           }</span
  171.         >
  172.         <span class="tempc"> ${this.getUnit("temperature")}</span>
  173.         <span>
  174.           <ul class="variations">
  175.             <li>
  176.               <span class="ha-icon"
  177.                 ><ha-icon icon="mdi:water-percent"></ha-icon
  178.               ></span>
  179.               ${stateObj.attributes.humidity}<span class="unit"> % </span>
  180.               <br />
  181.               <span class="ha-icon"
  182.                 ><ha-icon icon="mdi:weather-windy"></ha-icon
  183.               ></span>
  184.               ${
  185.                 windDirections[
  186.                   parseInt((stateObj.attributes.wind_bearing + 11.25) / 22.5)
  187.                 ]
  188.               }
  189.               ${stateObj.attributes.wind_speed}<span class="unit">
  190.                 ${this.getUnit("length")}/h
  191.               </span>
  192.               <br />
  193.               <span class="ha-icon"
  194.                 ><ha-icon icon="mdi:weather-sunset-up"></ha-icon
  195.               ></span>
  196.               ${next_rising.toLocaleTimeString()}
  197.             </li>
  198.             <li>
  199.               <span class="ha-icon"><ha-icon icon="mdi:gauge"></ha-icon></span
  200.               >${stateObj.attributes.pressure}<span class="unit">
  201.                 ${this.getUnit("air_pressure")}
  202.               </span>
  203.               <br />
  204.               <span class="ha-icon"
  205.                 ><ha-icon icon="mdi:weather-fog"></ha-icon
  206.               ></span>
  207.               ${stateObj.attributes.visibility}<span class="unit">
  208.                 ${this.getUnit("length")}
  209.               </span>
  210.               <br />
  211.               <span class="ha-icon"
  212.                 ><ha-icon icon="mdi:weather-sunset-down"></ha-icon
  213.               ></span>
  214.               ${next_setting.toLocaleTimeString()}
  215.             </li>
  216.           </ul>
  217.         </span>
  218.         ${
  219.           stateObj.attributes.forecast &&
  220.           stateObj.attributes.forecast.length > 0
  221.             ? html`
  222.                 <div class="forecast clear">
  223.                   ${
  224.                     stateObj.attributes.forecast.slice(0, 5).map(
  225.                       daily => html`
  226.                         <div class="day">
  227.                           <span class="dayname"
  228.                             >${
  229.                               new Date(daily.datetime).toLocaleDateString(
  230.                                 lang,
  231.                                 {
  232.                                   weekday: "short"
  233.                                 }
  234.                               )
  235.                             }</span
  236.                           >
  237.                           <br /><i
  238.                             class="icon"
  239.                             style="background: none, url(${
  240.                              this.getWeatherIcon(daily.condition.toLowerCase())
  241.                            }) no-repeat; background-size: contain;"
  242.                           ></i>
  243.                           <br /><span class="highTemp"
  244.                             >${daily.temperature}${
  245.                               this.getUnit("temperature")
  246.                             }</span
  247.                           >
  248.                           ${
  249.                             typeof daily.templow !== 'undefined'
  250.                               ? html`
  251.                                   <br /><span class="lowTemp"
  252.                                     >${daily.templow}${
  253.                                       this.getUnit("temperature")
  254.                                     }</span
  255.                                   >
  256.                                 `
  257.                               : ""
  258.                           }
  259.                         </div>
  260.                       `
  261.                     )
  262.                   }
  263.                 </div>
  264.               `
  265.             : ""
  266.         }
  267.       </ha-card>
  268.     `;
  269.   }
  270.  
  271.   getWeatherIcon(condition, sun) {
  272.     return `${
  273.       this._config.icons
  274.         ? this._config.icons
  275.         : "https://cdn.jsdelivr.net/gh/bramkragten/weather-card@master/dist/icons/"
  276.     }${
  277.       sun && sun == "below_horizon"
  278.         ? weatherIconsNight[condition]
  279.         : weatherIconsDay[condition]
  280.     }.svg`;
  281.   }
  282.  
  283.   getUnit(measure) {
  284.     const lengthUnit = this.hass.config.unit_system.length;
  285.     switch (measure) {
  286.       case "air_pressure":
  287.         return lengthUnit === "km" ? "hPa" : "inHg";
  288.       case "length":
  289.         return lengthUnit;
  290.       case "precipitation":
  291.         return lengthUnit === "km" ? "mm" : "in";
  292.       default:
  293.         return this.hass.config.unit_system[measure] || "";
  294.     }
  295.   }
  296.  
  297.   _handleClick() {
  298.     fireEvent(this, "hass-more-info", { entityId: this._config.entity });
  299.   }
  300.  
  301.   getCardSize() {
  302.     return 3;
  303.   }
  304.  
  305.   renderStyle() {
  306.     return html`
  307.       <style>
  308.         ha-card {
  309.           cursor: pointer;
  310.           margin: auto;
  311.           padding-top: 2.5em;
  312.           padding-bottom: 1.3em;
  313.           padding-left: 1em;
  314.           padding-right: 1em;
  315.           position: relative;
  316.         }
  317.  
  318.         .clear {
  319.           clear: both;
  320.         }
  321.  
  322.         .ha-icon {
  323.           height: 18px;
  324.           margin-right: 5px;
  325.           color: var(--paper-item-icon-color);
  326.         }
  327.  
  328.         .title {
  329.           position: absolute;
  330.           left: 3em;
  331.           top: 0.6em;
  332.           font-weight: 300;
  333.           font-size: 3em;
  334.           color: var(--primary-text-color);
  335.         }
  336.         .temp {
  337.           font-weight: 300;
  338.           font-size: 4em;
  339.           color: var(--primary-text-color);
  340.           position: absolute;
  341.           right: 1em;
  342.           top: 0.3em;
  343.         }
  344.  
  345.         .tempc {
  346.           font-weight: 300;
  347.           font-size: 1.5em;
  348.           vertical-align: super;
  349.           color: var(--primary-text-color);
  350.           position: absolute;
  351.           right: 1em;
  352.           margin-top: -14px;
  353.           margin-right: 7px;
  354.         }
  355.  
  356.         .variations {
  357.           display: flex;
  358.           flex-flow: row wrap;
  359.           justify-content: space-between;
  360.           font-weight: 300;
  361.           color: var(--primary-text-color);
  362.           list-style: none;
  363.           margin-top: 4.5em;
  364.           padding: 0;
  365.         }
  366.  
  367.         .variations li {
  368.           flex-basis: auto;
  369.         }
  370.  
  371.         .variations li:first-child {
  372.           padding-left: 1em;
  373.         }
  374.  
  375.         .variations li:last-child {
  376.           padding-right: 1em;
  377.         }
  378.  
  379.         .unit {
  380.           font-size: 0.8em;
  381.         }
  382.  
  383.         .forecast {
  384.           width: 100%;
  385.           margin: 0 auto;
  386.           height: 9em;
  387.         }
  388.  
  389.         .day {
  390.           display: block;
  391.           width: 20%;
  392.           float: left;
  393.           text-align: center;
  394.           color: var(--primary-text-color);
  395.           border-right: 0.1em solid #d9d9d9;
  396.           line-height: 2;
  397.           box-sizing: border-box;
  398.         }
  399.  
  400.         .dayname {
  401.           text-transform: uppercase;
  402.         }
  403.  
  404.         .forecast .day:first-child {
  405.           margin-left: 0;
  406.         }
  407.  
  408.         .forecast .day:nth-last-child(1) {
  409.           border-right: none;
  410.           margin-right: 0;
  411.         }
  412.  
  413.         .highTemp {
  414.           font-weight: bold;
  415.         }
  416.  
  417.         .lowTemp {
  418.           color: var(--secondary-text-color);
  419.         }
  420.  
  421.         .icon.bigger {
  422.           width: 10em;
  423.           height: 10em;
  424.           margin-top: -4em;
  425.           position: absolute;
  426.           left: 0em;
  427.         }
  428.  
  429.         .icon {
  430.           width: 50px;
  431.           height: 50px;
  432.           margin-right: 5px;
  433.           display: inline-block;
  434.           vertical-align: middle;
  435.           background-size: contain;
  436.           background-position: center center;
  437.           background-repeat: no-repeat;
  438.           text-indent: -9999px;
  439.         }
  440.  
  441.         .weather {
  442.           font-weight: 300;
  443.           font-size: 1.5em;
  444.           color: var(--primary-text-color);
  445.           text-align: left;
  446.           position: absolute;
  447.           top: -0.5em;
  448.           left: 6em;
  449.           word-wrap: break-word;
  450.           width: 30%;
  451.         }
  452.       </style>
  453.     `;
  454.   }
  455. }
  456. customElements.define("weather-card", WeatherCard);
Advertisement
Add Comment
Please, Sign In to add comment