customElements.whenDefined('card-tools').then(() => { var ct = customElements.get('card-tools'); const BUILTIN_ACTIONS = [ { matches: '^((magnet:.*)|(.*\.torrent.*))$', name: 'Add to Transmission', icon: 'mdi:progress-download', service: 'transmission.add_torrent', service_data: { torrent: '{1}' }, } ]; const matchAndReplace = (text, matches) => { for (var i = 0; i < matches.length; i++) { text = text.replace('{' + i + '}', matches[i]); } return text; } class SearchCard extends ct.LitElement { static get properties() { return { config: {}, hass: {}, }; } setConfig(config) { this.results = []; this.config = config; this.active_actions = []; this.max_results = this.config.max_results || 10; this.search_text = this.config.search_text || "Type to search..."; this.actions = BUILTIN_ACTIONS.concat(this.config.actions || []); this.included_domains = this.config.included_domains; this.excluded_domains = this.config.excluded_domains || []; } getCardSize() { return 4; } render() { var results = this.results.slice(0, this.max_results).sort(); var rows = results.map((entity_id) => this._createResultRow(entity_id)); var actions = this.active_actions.map((x) => this._createActionRow(x[0], x[1])); return ct.LitHtml `
${results.length > 0 ? ct.LitHtml `
Showing ${results.length} of ${this.results.length} results
` : ''}
${(rows.length > 0 || actions.length > 0) ? ct.LitHtml `
${actions}${rows}
` : ''}
`; } _createResultRow(entity_id) { var row = ct.createEntityRow({entity: entity_id}); row.addEventListener("click", () => ct.moreInfo(entity_id)); row.hass = this.hass; return row; } _createActionRow(action, matches) { var service_data = action.service_data; for (var key in service_data) { service_data[key] = matchAndReplace(service_data[key], matches); } const elem = cardTools.createThing("service-row", { type: "call", name: matchAndReplace(action.name, matches), icon: action.icon || 'mdi:lamp', service: action.service, service_data: service_data, }); elem.hass = this.hass; return elem; } _clearInput() { this.shadowRoot.getElementById('searchText').value = ''; this._updateSearchResults(''); } _valueChanged(ev) { var searchText = ev.target.value; this._updateSearchResults(searchText); } _updateSearchResults(searchText) { this.results = []; this.active_actions = []; if (!this.config || !this.hass || searchText === "") { this.update(); return; } try { var searchRegex = new RegExp(searchText, 'i'); for (var entity_id in this.hass.states) { if ( ( entity_id.search(searchRegex) >= 0 || this.hass.states[entity_id].attributes.friendly_name?.search(searchRegex) >= 0 ) && ( this.included_domains ? this.included_domains.includes(entity_id.split(".")[0]) : !this.excluded_domains.includes(entity_id.split(".")[0]) ) ) { this.results.push(entity_id); } } } catch (err) { console.warn(err); } this.active_actions = this._getActivatedActions(searchText); this.update(); } _getActivatedActions(searchText) { var active = []; for (const action of this.actions) { if (this._serviceExists(action.service)) { var matches = searchText.match(action.matches); if (matches != null) { active.push([action, matches]); } } } return active; } _serviceExists(serviceCall) { var [domain, service] = serviceCall.split('.'); var servicesForDomain = this.hass.services[domain]; return servicesForDomain && service in servicesForDomain; } static get styles() { return ct.LitCSS ` #searchContainer { width: 90%; display: block; margin-left: auto; margin-right: auto; } #searchTextFieldContainer { display: flex; padding-top: 5px; padding-bottom: 5px; } #searchText { flex-grow: 1; } #count { text-align: right; font-style: italic; } #results { width: 90%; display: block; padding-bottom: 15px; margin-top: 15px; margin-left: auto; margin-right: auto; } `; } } customElements.define('search-card', SearchCard); }); setTimeout(() => { if(customElements.get('card-tools')) return; customElements.define('search-card', class extends HTMLElement{ setConfig() { throw new Error("Can't find card-tools. See https://github.com/thomasloven/lovelace-card-tools");} }); }, 2000); window.customCards = window.customCards || []; window.customCards.push({ type: "search-card", name: "Search Card", preview: true, description: "Card to search entities" });