Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!--
- Floorplan for Home Assistant
- Version: 1.0.13
- https://github.com/pkozul/ha-floorplan
- *added multilayer support
- *fix for mutilayer floor conflit with mdi icon named SVG
- -->
- <script src="lib/jquery-3.2.1.min.js"></script>
- <script src="lib/moment.min.js"></script>
- <script src="lib/svg-pan-zoom.min.js"></script>
- <script src="lib/custom_js.js"></script>
- <!-- As documented here for chrome, removes the need for touchstart -->
- <meta name="viewport" content="width=device-width">
- <dom-module id="ha-floorplan">
- <template>
- <style>
- .loading-container {
- text-align: center;
- padding: 8px;
- }
- .loading {
- height: 0px;
- overflow: hidden;
- }
- #errors {
- color: #FF0000;
- display: none;
- }
- #warnings {
- color: #FF851B;
- display: none;
- }
- #debug {
- color: #000000;
- display: none;
- }
- </style>
- <template is='dom-if' if='[[isLoading]]'>
- <div class='loading-container'>
- <paper-spinner active alt='Loading'></paper-spinner>
- </div>
- </template>
- <div id="errors">
- <ul></ul>
- </div>
- <div id="warnings">
- <ul></ul>
- </div>
- <div id="debug">
- <ul></ul>
- </div>
- <div id="floorplan" on-tap="stopPropagation"></div>
- </template>
- </dom-module>
- <script>
- //fix for mutilayer floor conflit with mdi icon named SVG
- var g_svg= ‘’;
- class HaFloorplan extends Polymer.Element {
- static get is() { return 'ha-floorplan'; }
- static get properties() {
- return {
- hass: {
- type: Object,
- observer: 'hassChanged'
- },
- inDialog: {
- type: Boolean,
- value: false,
- },
- isPanel: {
- type: Boolean,
- value: false,
- },
- config: {
- type: Object,
- },
- isLoading: {
- type: Boolean,
- value: true,
- },
- timeDifference: {
- type: Number,
- value: undefined,
- },
- entityConfigs: {
- type: Array,
- value: () => { return []; },
- },
- elementConfigs: {
- type: Array,
- value: () => { return []; },
- },
- cssRules: {
- type: Array,
- value: () => { return []; },
- },
- isInitialized: {
- type: Boolean,
- value: false,
- },
- };
- }
- connectedCallback() {
- super.connectedCallback();
- if (!this.isInitialized) {
- this.initFloorplan();
- }
- }
- stopPropagation(e) {
- e.stopPropagation();
- }
- hassChanged(newHass, oldHass) {
- this.handleEntities(newHass.states);
- }
- initFloorplan() {
- this.isInitialized = true;
- window.onerror = this.handleWindowError.bind(this);
- if (!this.config.groups) {
- this.isLoading = false;
- this.warn(`Cannot find 'groups' in floorplan configuration`);
- return;
- }
- let invalidGroups = this.config.groups.filter(x => x.entities && x.elements);
- if (invalidGroups.length) {
- this.isLoading = false;
- this.warn(`A group cannot contain both 'entities' and 'elements' in floorplan configuration`);
- return;
- }
- invalidGroups = this.config.groups.filter(x => !x.entities && !x.elements);
- if (invalidGroups.length) {
- this.isLoading = false;
- this.warn(`A group must contain either 'entities' or 'elements' in floorplan configuration`);
- return;
- }
- this.hass.connection.socket.addEventListener('message', event => {
- let data = JSON.parse(event.data);
- // Store the time difference between the local web browser and the Home Assistant server
- if (data.event && data.event.time_fired) {
- let lastEventFiredTime = moment(data.event.time_fired).toDate();
- this.timeDifference = moment().diff(moment(lastEventFiredTime), 'milliseconds');
- }
- });
- this.addExternalCss(() => {
- this.loadFloorPlan(() => {
- this.isLoading = false;
- this.handleEntities(this.hass.states);
- //original mutilayer addon
- //$(document).trigger( “floorplan:loaded”, [this, svg]);
- //fix for mutilayer floor conflit with mdi icon named SVG
- $(document).trigger( “floorplan:loaded”, [this, g_svg]);
- });
- });
- if (this.config.groups.find(entityGroup => entityGroup.state_transitions)) {
- setInterval(this.updateStateTransitions.bind(this), 100);
- }
- }
- handleWindowError(msg, url, lineNo, columnNo, error) {
- if (msg.toLowerCase().indexOf("script error") >= 0) {
- this.error('Script error: See browser console for detail');
- }
- else {
- let message = [
- msg,
- 'URL: ' + url,
- 'Line: ' + lineNo + ', column: ' + columnNo,
- 'Error: ' + JSON.stringify(error)
- ].join('<br>');
- this.error(message);
- }
- return false;
- }
- addExternalCss(callback) {
- if (!this.config.stylesheet) {
- callback();
- }
- this.loadStyleSheet(this.config.stylesheet + '?cacheBuster=' + (new Date().getTime()), function (success, link) {
- if (success) {
- this.instance.root.appendChild(link);
- let styleSheet = link['sheet'];
- setTimeout(() => {
- this.instance.cssRules = this.instance.getArray(styleSheet.cssRules);
- callback();
- }, 1000);
- }
- else {
- this.instance.error("Error loading stylesheet");
- }
- }.bind({ instance: this, callback: callback }));
- }
- loadFloorPlan(callback) {
- jQuery.ajax({
- url: this.config.image + '?cacheBuster=' + (new Date().getTime()),
- success: function (result) {
- let svg = $(result).find('svg')[0];
- //fix for mutilayer floor conflit with mdi icon named SVG
- g_svg = svg;
- $(svg).height('100%');
- $(svg).width('100%');
- $(svg).css('position', this.instance.isPanel ? 'absolute' : 'relative');
- $(svg).css('cursor', 'default');
- this.instance.$.floorplan.appendChild(svg);
- let uniqueId = (new Date()).getTime();
- let svgElements = $(svg).find('*').toArray();
- let elementGroups = this.instance.config.groups.filter(x => x.elements);
- for (let elementGroup of elementGroups) {
- for (let elementId of elementGroup.elements) {
- let svgElement = $(svg).find(`[id="${elementId}"]`);
- if (svgElement.length) {
- $(svgElement).on('click', this.instance.onElementClick.bind({ instance: this.instance, elementId: elementId }));
- $(svgElement).css('cursor', 'pointer');
- let elementConfig = {
- group: elementGroup,
- };
- this.instance.elementConfigs[elementId] = elementConfig;
- if (elementGroup.action.data.elements) {
- for (let otherElementId of elementGroup.action.data.elements) {
- let otherSvgElement = $(svg).find(`[id="${otherElementId}"]`);
- $(otherSvgElement).addClass(elementGroup.action.data.default_class);
- }
- }
- }
- else {
- this.instance.warn(`Cannot find '${elementId}' in SVG file`);
- }
- }
- }
- let entityGroups = this.instance.config.groups.filter(x => x.entities);
- for (let entityGroup of entityGroups) {
- let targetEntityIds = [];
- // Split out HA entity groups into separate entities
- if (entityGroup.groups) {
- for (let entityId of entityGroup.groups) {
- let group = this.instance.hass.states[entityId];
- if (group) {
- for (let targetEntityId of group.attributes.entity_id) {
- targetEntityIds.push(targetEntityId);
- }
- }
- else {
- this.instance.warn(`Cannot find '${entityId}' in HA group configuration`);
- }
- }
- }
- // HA entities treated as is
- if (entityGroup.entities) {
- for (let entityId of entityGroup.entities) {
- let entity = this.instance.hass.states[entityId];
- if (entity) {
- targetEntityIds.push(entityId);
- }
- else {
- this.instance.warn(`Cannot find '${entityId}' in HA group configuration`);
- }
- }
- }
- for (let entityId of targetEntityIds) {
- let entityConfig = {
- group: entityGroup,
- lastState: undefined,
- lastChangedTime: undefined,
- svgElementConfigs: {},
- imageUrl: undefined
- };
- this.instance.entityConfigs[entityId] = entityConfig;
- let svgElement = svgElements.find(svgElement => svgElement.id === entityId);
- if (!svgElement) {
- this.instance.warn(`Cannot find element '${entityId}' in SVG file`);
- continue;
- }
- entityConfig.svgElementConfigs[svgElement.id] = {
- svgElementId: svgElement.id,
- svgElement: svgElement,
- clonedsvgElement: svgElement.cloneNode(true),
- entityId: entityId
- };
- $(svgElement).find('*').each((i, svgNestedElement) => {
- // Ensure that all child elements have an Id.
- if (!svgNestedElement.id) {
- svgNestedElement.id = uniqueId++;
- }
- entityConfig.svgElementConfigs[svgNestedElement.id] = {
- svgElementId: svgNestedElement.id,
- svgElement: svgNestedElement,
- clonedsvgElement: svgNestedElement.cloneNode(true),
- entityId: entityId
- };
- });
- for (let svgElementId in entityConfig.svgElementConfigs) {
- let svgElementConfig = entityConfig.svgElementConfigs[svgElementId];
- let svgElement = $(svgElementConfig.svgElement);
- // Create a title element (to support hover over text)
- svgElement.append(document.createElementNS('http://www.w3.org/2000/svg', 'title'));
- if (svgElement.length) {
- svgElementConfig.svgElement = svgElement[0];
- $(svgElement).on('click', this.instance.onEntityClick.bind({ instance: this.instance, entityId: entityId }));
- $(svgElement).css('cursor', 'pointer');
- $(svgElement).addClass('ha-entity');
- if ((svgElement[0].nodeName === 'text') && (svgElement[0].id === entityId)) {
- let boundingBox = svgElement[0].getBBox();
- let rect = $(document.createElementNS("http://www.w3.org/2000/svg", 'rect'))
- .attr('id', entityId + '.background')
- .attr('height', boundingBox.height + 1)
- .attr('width', boundingBox.width + 2)
- .height(boundingBox.height + 1)
- .width(boundingBox.width + 2)
- .attr('x', boundingBox.x - 1)
- .attr('y', boundingBox.y - 0.5)
- .css('fill-opacity', 0);
- $(rect).insertBefore($(svgElement));
- }
- }
- }
- }
- }
- // Enable pan / zoom if enabled in config
- if ((this.instance.config.pan_zoom === null) || (this.instance.config.pan_zoom !== undefined)) {
- svgPanZoom($(svg)[0], {
- zoomEnabled: true,
- controlIconsEnabled: true,
- fit: true,
- center: true,
- });
- }
- this.callback();
- }.bind({ instance: this, callback: callback })
- });
- }
- handleEntities(entities) {
- let svg = this.$.floorplan.querySelector('svg');
- for (let entityId in entities) {
- let entityState = entities[entityId];
- let entityConfig = this.entityConfigs[entityId];
- if (!entityConfig)
- continue;
- entityConfig.lastState = entityState.state;
- for (let svgElementId in entityConfig.svgElementConfigs) {
- let svgElementConfig = entityConfig.svgElementConfigs[svgElementId];
- let svgElement = svgElementConfig.svgElement;
- if (!svgElement)
- continue;
- this.setHoverOverText(svgElement, entityState);
- if (svgElement.nodeName === 'text') {
- let text = entityConfig.group.text_template ?
- this.assemble(entityConfig.group.text_template, entityState, entities) : entityState.state;
- let tspan = $(svgElement).find('tspan');
- if (tspan.length) {
- $(tspan).text(text);
- }
- else {
- let title = $(svgElement).find('title');
- $(svgElement).text(text);
- if (title.length) {
- $(svgElement).append(title);
- }
- }
- let rect = $(svgElement).parent().find(`[id="${entityId}.background"]`);
- if (rect.length) {
- let boundingBox = svgElement.getBBox();
- $(rect)
- .attr("x", boundingBox.x - 1)
- .attr("y", boundingBox.y - 0.5)
- .attr('height', boundingBox.height + 1)
- .attr('width', boundingBox.width + 2)
- .height(boundingBox.height + 1)
- .width(boundingBox.width + 2);
- }
- }
- if (!this.cssRules || !this.cssRules.length)
- return;
- let wasTransitionHandled = false;
- if (entityConfig.group.states && entityConfig.group.state_transitions) {
- let transitionConfig = entityConfig.group.state_transitions.find(transitionConfig => (transitionConfig.to_state === entityState.state));
- if (transitionConfig && transitionConfig.from_state && transitionConfig.to_state && transitionConfig.duration) {
- // Determine the current time on the server (based on the local vs. server time difference)
- let serverMoment = this.getServerMoment();
- let lastChangedMoment = moment(entityState.last_changed);
- let elapsed = Math.max(serverMoment.diff(lastChangedMoment, 'milliseconds'), 0);
- let remaining = (transitionConfig.duration * 1000) - elapsed;
- if (remaining > 0) {
- entityConfig.lastChangedTime = lastChangedMoment.toDate();
- }
- else {
- this.setEntityStyle(svgElementConfig, svgElement, entityConfig);
- }
- wasTransitionHandled = true;
- }
- }
- if (entityConfig.group.image_template) {
- let imageUrl = this.assemble(entityConfig.group.image_template, entityState, entities);
- if (entityConfig.imageUrl !== imageUrl) {
- entityConfig.imageUrl = imageUrl;
- this.loadImage(imageUrl, entityId, entityState, (embeddedSvg, entityState) => {
- this.setHoverOverText(embeddedSvg, entityState);
- });
- }
- let embeddedSvg = $(svg).find(`[id="image.${entityId}"]`)[0];
- this.setHoverOverText(embeddedSvg, entityState);
- }
- let targetClass = undefined;
- let obsoleteClasses = [];
- if (entityConfig.group.class_template) {
- targetClass = this.assemble(entityConfig.group.class_template, entityState, entities);
- }
- let originalClasses = this.getArray(svgElementConfig.clonedsvgElement.classList);
- // Get the config for the current state
- if (entityConfig.group.states) {
- let stateConfig = entityConfig.group.states.find(stateConfig => (stateConfig.state === entityState.state));
- if (stateConfig && stateConfig.class && !wasTransitionHandled) {
- targetClass = stateConfig.class;
- }
- // Remove any other previously-added state classes
- for (let otherStateConfig of entityConfig.group.states) {
- if (!stateConfig || (otherStateConfig.state != stateConfig.state)) {
- if (otherStateConfig.class && (otherStateConfig.class != 'ha-entity') && $(svgElement).hasClass(otherStateConfig.class)) {
- if (originalClasses.indexOf(otherStateConfig.class) < 0) {
- obsoleteClasses.push(otherStateConfig.class);
- }
- }
- }
- }
- }
- else {
- for (let otherClassName of this.getArray(svgElement.classList)) {
- if ((otherClassName != targetClass) && (otherClassName != 'ha-entity')) {
- if (originalClasses.indexOf(otherClassName) < 0) {
- obsoleteClasses.push(otherClassName);
- }
- }
- }
- }
- // Remove any obsolete classes from the entity
- this.removeClasses(entityId, svgElement, obsoleteClasses);
- // Add the target class to the entity
- if (targetClass) {
- this.addClass(entityId, svgElement, targetClass);
- }
- if (this.config.last_motion_entity && this.config.last_motion_class && entities[this.config.last_motion_entity] &&
- (entityState.attributes.friendly_name === entities[this.config.last_motion_entity].state)) {
- if (!$(svgElement).hasClass(this.config.last_motion_class)) {
- $(svgElement).addClass(this.config.last_motion_class);
- }
- }
- else {
- if ($(svgElement).hasClass(this.config.last_motion_class)) {
- $(svgElement).removeClass(this.config.last_motion_class);
- }
- }
- }
- }
- }
- setHoverOverText(element, entityState) {
- let title = $(element).find('title');
- if (title.length) {
- let dateFormat = this.config.date_format ? this.config.date_format : 'DD-MMM-YYYY';
- let titleText = entityState.attributes.friendly_name + '\n' +
- 'State: ' + entityState.state + '\n' +
- 'Last changed date: ' + moment(entityState.last_changed).format(dateFormat) + '\n' +
- 'Last changed time: ' + moment(entityState.last_changed).format('HH:mm:ss');
- $(title).html(titleText);
- }
- }
- loadImage(imageUrl, entityId, entityState, callback) {
- let svg = this.$.floorplan.querySelector('svg');
- jQuery.ajax({
- url: imageUrl, // allow the browser cache to be used
- success: function (result) {
- let svgElement = $(svg).find(`[id="${entityId}"]`);
- let bbox = svgElement[0].getBBox();
- let clientRect = svgElement[0].getBoundingClientRect();
- let embeddedSvg = $(result).find('svg');
- embeddedSvg.attr('id', `image.${entityId}`);
- embeddedSvg.attr('preserveAspectRatio', 'xMinYMin meet')
- embeddedSvg
- .attr('height', bbox.height)
- .attr('width', bbox.width)
- .attr('x', bbox.x)
- .attr('y', bbox.y);
- $(embeddedSvg).find('*').append(document.createElementNS('http://www.w3.org/2000/svg', 'title'))
- .on('click', this.onEntityClick.bind({ instance: this, entityId: entityId }))
- .css('cursor', 'pointer')
- .addClass('ha-entity');
- // Remove previous SVG
- let previousEmbeddedSvg = $(svg).find(`[id="${embeddedSvg.attr('id')}"]`);
- $(previousEmbeddedSvg).find('*')
- .off('click')
- .remove();
- $(svg).append(embeddedSvg);
- callback(embeddedSvg, entityState);
- }.bind(this)
- });
- }
- addClass(entityId, svgElement, className) {
- if ($(svgElement).hasClass('ha-leave-me-alone')) {
- return;
- }
- if (!$(svgElement).hasClass(className)) {
- //console.log(`${entityId}: adding class "${className}" for current state "${entityState.state}" (${svgElement.id})`);
- $(svgElement).addClass(className);
- if ((svgElement.nodeName === 'text')) {
- let rect = $(svgElement).parent().find(`[id="${entityId}.background"]`);
- if (rect.length) {
- if (!$(rect).hasClass(className + '-background')) {
- $(rect).addClass(className + '-background');
- }
- }
- }
- }
- }
- removeClasses(entityId, svgElement, classes) {
- for (let className of classes) {
- //console.log(`${entityId}: removing class "${className}" (${svgElement.id})`);
- if ($(svgElement).hasClass(className)) {
- $(svgElement).removeClass(className);
- if ((svgElement.nodeName === 'text')) {
- let rect = $(svgElement).parent().find(`[id="${entityId}.background"]`);
- if (rect.length) {
- if ($(rect).hasClass(className + '-background')) {
- $(rect).removeClass(className + '-background');
- }
- }
- }
- }
- }
- }
- updateStateTransitions() {
- if (!this.cssRules || !this.cssRules.length)
- return;
- let svg = this.$.floorplan.querySelector('svg');
- for (let entityId in this.entityConfigs) {
- let entityConfig = this.entityConfigs[entityId];
- if (!entityConfig || !entityConfig.group.states || !entityConfig.group.state_transitions || (entityConfig.lastChangedTime === undefined))
- continue;
- for (let svgElementId in entityConfig.svgElementConfigs) {
- let svgElementConfig = entityConfig.svgElementConfigs[svgElementId];
- let svgElement = svgElementConfig.svgElement;
- if (!svgElement)
- continue;
- let wasTransitionHandled = false;
- let transitionConfig = entityConfig.group.state_transitions.find(transitionConfig => (transitionConfig.to_state === entityConfig.lastState));
- if (transitionConfig && transitionConfig.from_state && transitionConfig.to_state && transitionConfig.duration) {
- let serverMoment = this.getServerMoment();
- let fromStateConfig = entityConfig.group.states.find(stateConfig => (stateConfig.state === transitionConfig.from_state));
- let toStateConfig = entityConfig.group.states.find(stateConfig => (stateConfig.state === transitionConfig.to_state));
- if (fromStateConfig && toStateConfig) {
- let fromFill = this.getFill(fromStateConfig);
- let toFill = this.getFill(toStateConfig);
- if (fromFill && toFill) {
- let elapsed = serverMoment.diff(moment(entityConfig.lastChangedTime), 'milliseconds');
- if (elapsed < 0) {
- this.setTransitionFill(svgElement, fromFill, toFill, 1);
- }
- else {
- if (elapsed < (transitionConfig.duration * 1000)) {
- this.setTransitionFill(svgElement, fromFill, toFill, elapsed / (transitionConfig.duration * 1000));
- }
- else {
- this.setTransitionFill(svgElement, fromFill, toFill, 0);
- entityConfig.lastChangedTime = undefined;
- }
- }
- wasTransitionHandled = true;
- }
- }
- }
- if (!wasTransitionHandled) {
- this.setEntityStyle(svgElementConfig, svgElement, entityConfig);
- }
- }
- }
- }
- setEntityStyle(svgElementConfig, svgElement, entityConfig, state) {
- let stateConfig = entityConfig.group.states.find(stateConfig => (stateConfig.state === entityConfig.lastState));
- if (stateConfig) {
- let stroke = this.getStroke(stateConfig);
- if (stroke) {
- svgElement.style.stroke = stroke;
- }
- else {
- if (svgElementConfig.clonedsvgElement) {
- svgElement.style.stroke = svgElementConfig.clonedsvgElement.style.stroke;
- }
- else {
- // ???
- }
- }
- let fill = this.getFill(stateConfig);
- if (fill) {
- svgElement.style.fill = fill;
- }
- else {
- if (svgElementConfig.clonedsvgElement) {
- svgElement.style.fill = svgElementConfig.clonedsvgElement.style.fill;
- }
- else {
- // ???
- }
- }
- }
- }
- onElementClick(e) {
- e.stopPropagation();
- let svgElement = e.target;
- let elementConfig = this.instance.elementConfigs[this.elementId];
- if (elementConfig.group.action) {
- let action = elementConfig.group.action;
- if (action.service) {
- switch (action.domain) {
- case 'class':
- switch (action.service) {
- case 'toggle':
- let svg = this.instance.$.floorplan.querySelector('svg');
- let classes = action.data.classes;
- for (let otherElementId of action.data.elements) {
- let otherSvgElement = $(svg).find(`[id="${otherElementId}"]`);
- if ($(otherSvgElement).hasClass(classes[0])) {
- $(otherSvgElement).removeClass(classes[0]);
- $(otherSvgElement).addClass(classes[1]);
- }
- else if ($(otherSvgElement).hasClass(classes[1])) {
- $(otherSvgElement).removeClass(classes[1]);
- $(otherSvgElement).addClass(classes[0]);
- }
- else {
- $(otherSvgElement).addClass(action.data.default_class);
- }
- }
- break;
- }
- break;
- default:
- domain = action.domain
- let data = action.data ? action.data : {};
- if (action.data_template) {
- let entities = this.instance.hass.states;
- let entityState = entities[entityId];
- let result = this.instance.assemble(action.data_template, entityState, entities);
- data = JSON.parse(result);
- }
- this.instance.hass.callService(domain, action.service, data);
- break;
- }
- }
- }
- }
- onEntityClick(e) {
- e.stopPropagation();
- let entityId = this.entityId;
- let entityConfig = this.instance.entityConfigs[entityId];
- if (entityConfig.group.action) {
- let action = entityConfig.group.action;
- if (action.service) {
- let domain = action.domain ? action.domain : entityId.substr(0, entityId.indexOf('.'));
- domain = (domain == 'group') ? 'homeassistant' : domain;
- let data = {};
- if (action.data) {
- data = action.data;
- }
- if (action.data_template) {
- let entities = this.instance.hass.states;
- let entityState = entities[entityId];
- let result = this.instance.assemble(action.data_template, entityState, entities);
- data = JSON.parse(result);
- }
- if (!data.entity_id) {
- data['entity_id'] = entityId;
- }
- this.instance.hass.callService(domain, action.service, data);
- }
- else {
- this.instance.fire('hass-more-info', { entityId: entityId });
- }
- }
- else {
- this.instance.fire('hass-more-info', { entityId: entityId });
- }
- }
- getFill(stateConfig) {
- let fill = undefined;
- for (let cssRule of this.cssRules) {
- if (cssRule.selectorText && cssRule.selectorText.indexOf(`.${stateConfig.class}`) >= 0) {
- if (cssRule.style && cssRule.style.fill) {
- if (cssRule.style.fill[0] === '#') {
- fill = cssRule.style.fill;
- }
- else {
- let rgb = cssRule.style.fill.substring(4).slice(0, -1).split(',').map(x => parseInt(x));
- fill = `#${rgb[0].toString(16)[0]}${rgb[1].toString(16)[0]}${rgb[2].toString(16)[0]}`;
- }
- }
- }
- }
- return fill;
- }
- getStroke(stateConfig) {
- let stroke = undefined;
- for (let cssRule of this.cssRules) {
- if (cssRule.selectorText && cssRule.selectorText.indexOf(`.${stateConfig.class}`) >= 0) {
- if (cssRule.style && cssRule.style.stroke) {
- if (cssRule.style.stroke[0] === '#') {
- stroke = cssRule.style.stroke;
- }
- else {
- let rgb = cssRule.style.stroke.substring(4).slice(0, -1).split(',').map(x => parseInt(x));
- stroke = `#${rgb[0].toString(16)[0]}${rgb[1].toString(16)[0]}${rgb[2].toString(16)[0]}`;
- }
- }
- }
- }
- return stroke;
- }
- setTransitionFill(svgElement, fromFill, toFill, value) {
- if (value >= 1) {
- svgElement.style.fill = fromFill;
- }
- else if (value <= 0) {
- svgElement.style.fill = toFill;
- }
- else {
- let color = this.rgbToHex(this.mix(this.hexToRgb(toFill), this.hexToRgb(fromFill), value));
- svgElement.style.fill = color;
- }
- }
- getServerMoment() {
- let serverMoment = moment();
- if (this.timeDifference >= 0)
- serverMoment.subtract(this.timeDifference, 'milliseconds');
- else
- serverMoment.add(Math.abs(this.timeDifference), 'milliseconds');
- return serverMoment;
- }
- getArray(list) {
- return Array.isArray(list) ? list : Object.keys(list).map(key => list[key]);
- }
- assemble(code, entity, entities) {
- let functionBody = (code.indexOf('return') >= 0) ? code : `return \`${code}\`;`;
- let func = new Function('entity', 'entities', 'hass', 'config', functionBody);
- return func(entity, entities, this.hass, this.config);
- }
- error(message) {
- let errors = this.$.errors;
- $(errors).find('ul').append(`<li>${message}</li>`)
- $(errors).css('display', 'block');
- }
- warn(message) {
- if ((this.config.warnings === null) || (this.config.warnings !== undefined)) {
- let warnings = this.$.warnings;
- $(warnings).find('ul').append(`<li>${message}</li>`)
- $(warnings).css('display', 'block');
- }
- }
- debug(message) {
- let debug = this.$.debug;
- $(debug).find('ul').append(`<li>${message}</li>`)
- $(debug).css('display', 'block');
- }
- loadStyleSheet(path, fn, scope) {
- let head = document.getElementsByTagName('head')[0]; // reference to document.head for appending/ removing link nodes
- let link = document.createElement('link'); // create the link node
- link.setAttribute('href', path);
- link.setAttribute('rel', 'stylesheet');
- link.setAttribute('type', 'text/css');
- let sheet, cssRules;
- // get the correct properties to check for depending on the browser
- if ('sheet' in link) {
- sheet = 'sheet'; cssRules = 'cssRules';
- }
- else {
- sheet = 'styleSheet'; cssRules = 'rules';
- }
- let interval_id = setInterval(function () { // start checking whether the style sheet has successfully loaded
- try {
- if (link[sheet] && link[sheet][cssRules].length) { // SUCCESS! our style sheet has loaded
- clearInterval(interval_id); // clear the counters
- clearTimeout(timeout_id);
- fn.call(scope || window, true, link); // fire the callback with success == true
- }
- } catch (e) { } finally { }
- }, 10), // how often to check if the stylesheet is loaded
- timeout_id = setTimeout(function () { // start counting down till fail
- clearInterval(interval_id); // clear the counters
- clearTimeout(timeout_id);
- head.removeChild(link); // since the style sheet didn't load, remove the link node from the DOM
- fn.call(scope || window, false, link); // fire the callback with success == false
- }, 15000); // how long to wait before failing
- head.appendChild(link); // insert the link node into the DOM and start loading the style sheet
- return link; // return the link node;
- }
- rgbToHex(rgb) {
- return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
- }
- hexToRgb(hex) {
- // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
- let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
- hex = hex.replace(shorthandRegex, (m, r, g, b) => {
- return r + r + g + g + b + b;
- });
- let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
- return result ? {
- r: parseInt(result[1], 16),
- g: parseInt(result[2], 16),
- b: parseInt(result[3], 16)
- } : null;
- }
- mix(color1, color2, weight) {
- let p = weight;
- let w = p * 2 - 1;
- let w1 = ((w / 1) + 1) / 2;
- let w2 = 1 - w1;
- let rgb = [
- Math.round(color1.r * w1 + color2.r * w2),
- Math.round(color1.g * w1 + color2.g * w2),
- Math.round(color1.b * w1 + color2.b * w2)
- ];
- return rgb;
- }
- fire(type, detail, options) {
- options = 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;
- const node = options.node || this;
- node.dispatchEvent(event);
- return event;
- }
- }
- customElements.define(HaFloorplan.is, HaFloorplan);
- </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement