Skip to content

Commit

Permalink
Merge pull request #338 from ExperienceLovelace/hover-actions
Browse files Browse the repository at this point in the history
Hover actions and multi-line text
  • Loading branch information
exetico authored May 20, 2023
2 parents 14fcd0f + dcbb7ba commit 2044e3f
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 70 deletions.
4 changes: 2 additions & 2 deletions dist/floorplan-examples.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/floorplan.js

Large diffs are not rendered by default.

35 changes: 34 additions & 1 deletion docs/_docs/03-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ Below are the services that are specific to Floorplan.
| `floorplan.class_set` | Set the CSS class of the SVG element(s) | `class` (string) |
| `floorplan.dataset_set` | Set a data attribute of the SVG element(s) | `key` (string)<br /> `value` (string) |
| `floorplan.style_set` | Set the CSS style of the of the SVG element(s) | `style` (string) |
| `floorplan.text_set` | Set the text of the SVG element(s) | `text` (string) |
| `floorplan.text_set` | Set the text of the SVG element(s) | `text` (string)<br />`shift_y_axis: 2em` |
| `floorplan.image_set` | Set the image of the SVG element(s) | `image` (string)<br />`image_refresh_interval` (number)<br />`cache` (boolean) |
| `floorplan.execute` | Execute your own JS, defined in service_data | `<all>` (array) |

Expand Down Expand Up @@ -269,6 +269,39 @@ Below is an example of using JavaScript [template literals](https://developer.mo
class: '${(entity.state === "on") ? "motion-on" : "motion-off"}'
```

#### Using `text_set` to render mulitple tspans on linebreakes

If text_set spots a newline-character (`\n`), the text will be broken into multiple tspans. Find the related example [here](https://experiencelovelace.github.io/ha-floorplan/docs/example-multi-floor/). By providing `shift_y_axis: 2em` as a key, you'll be able to control the offset of each tspan. If a x or/an y offset are defined on the tspan, but not on the text-element, we'll secure that the offset of the tspan, will be used on the text-element.

```yaml
- entities:
- binary_sensor.kitchen
- binary_sensor.laundry
state_action:
action: call-service
service: floorplan.text_set
service_data:
element: sample.multilinegroup_text
shift_y_axis: 1.5em
text: |
> /* Note that this is a JavaScript block, where you normally can do cool stuff like console.log()*/
return 'Multiline\nTSPAN-Print';
```

`shift_y_axis: 2em`

#### Using `hover_action` to set a class while mouse hovering a element

By moving your cursor over a element, you can also trigger over hover action. With the hover_action, it's easy to toggle a `hover` class on a given elemen if needed. Here our element will get a `hover-over` class added, if the mouse hovers over the element related to the entity.

```yaml
- entities:
- binary_sensor.garage
hover_action:
- service: floorplan.class_set
service_data: '${element.matches(":hover") ? "hover-over" : ""}'
```

#### Using `dataset_set` to add data-keys to the DOM-element

Following is an example of using dataset and JavaScript [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) to dynamically evaluate data attribute to use.
Expand Down
8 changes: 8 additions & 0 deletions docs/_docs/floorplan/examples/multi_floor/multi_floor.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,11 @@ g.floorplan-long-click > :not(text):hover,
.button-off tspan {
fill: white !important;
}


/* Hover */

.hover {
stroke: red !important;
stroke-width: 10px !important;
}
22 changes: 19 additions & 3 deletions docs/_docs/floorplan/examples/multi_floor/multi_floor.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 15 additions & 2 deletions docs/_docs/floorplan/examples/multi_floor/multi_floor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ config:
elements:
- first_floor.button
class: button-off
- service: floorplan.text_set
service_data:
element: sample.multilinegroup_text
shift_y_axis: 1.5em
text: |
> /* Split text to two tspans*/
return 'Multiline\nTSPAN-Print';
rules:
- element: ground_floor.button
Expand Down Expand Up @@ -79,5 +86,11 @@ config:
- binary_sensor.garage
- binary_sensor.activity
state_action:
service: floorplan.class_set
service_data: '${ entity.state === "on" ? "binary-sensor-on" : "binary-sensor-off"}'
- service: floorplan.class_set
service_data: '${ entity.state === "on" ? "binary-sensor-on" : "binary-sensor-off"}'

- entities:
- binary_sensor.garage
hover_action:
- service: floorplan.class_set
service_data: '${element.matches(":hover") ? "hover" : ""}'
20 changes: 10 additions & 10 deletions docs/_docs/floorplan/floorplan-examples.js

Large diffs are not rendered by default.

79 changes: 46 additions & 33 deletions src/components/floorplan/floorplan-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,8 @@ export class FloorplanElement extends LitElement {
<div id="floorplan"></div>
<div id="log" style="display: ${this.isShowLog ? 'block' : 'none'};">
<a href="#" onclick="return false;" @click=${
this.clearLog
}>Clear log<a/>
<a href="#" onclick="return false;" @click=${this.clearLog
}>Clear log<a/>
<ul></ul>
</div>
</div>
Expand Down Expand Up @@ -349,9 +348,8 @@ export class FloorplanElement extends LitElement {
script.onerror = (err) => {
reject(
new URIError(
`${
(err as unknown as Record<string, Record<string, unknown>>).target
.src
`${(err as unknown as Record<string, Record<string, unknown>>).target
.src
}`
)
);
Expand Down Expand Up @@ -698,7 +696,7 @@ export class FloorplanElement extends LitElement {
);

svgElement.onmouseover = () => {
this.handleEntityIdSetHoverOver(entityId);
this.handleEntityIdSetHoverOver(entityId, svgElementInfo);
};
}

Expand Down Expand Up @@ -786,7 +784,7 @@ export class FloorplanElement extends LitElement {
);

svgElementInfo.svgElement.onmouseover = () => {
this.handleEntityIdSetHoverOver(entityId);
this.handleEntityIdSetHoverOver(entityId, svgElementInfo);
};

return svg;
Expand Down Expand Up @@ -1087,8 +1085,12 @@ export class FloorplanElement extends LitElement {
);
}

svgElement.onmouseover = () => {
this.handleEntitySetHoverOver(entityInfo);
svgElement.onmouseenter = () => {
this.handleEntitySetHoverOver(entityInfo, svgElementInfo);
};

svgElement.onmouseleave = () => {
this.handleEntitySetHoverOver(entityInfo, svgElementInfo);
};

this.attachClickHandlers(
Expand Down Expand Up @@ -1262,13 +1264,13 @@ export class FloorplanElement extends LitElement {

const singleTapContext = singleTapAction
? new FloorplanClickContext(
this,
entityId,
elementId,
svgElementInfo,
ruleInfo,
singleTapAction
)
this,
entityId,
elementId,
svgElementInfo,
ruleInfo,
singleTapAction
)
: false;

// Use simple function without delay, if doubleTap is not in use
Expand All @@ -1278,13 +1280,13 @@ export class FloorplanElement extends LitElement {
if (doubleTapAction) {
const doubleTapContext = doubleTapAction
? new FloorplanClickContext(
this,
entityId,
elementId,
svgElementInfo,
ruleInfo,
doubleTapAction
)
this,
entityId,
elementId,
svgElementInfo,
ruleInfo,
doubleTapAction
)
: false;

ManyClicks.observe(element as HTMLElement | SVGElement);
Expand Down Expand Up @@ -1483,12 +1485,12 @@ export class FloorplanElement extends LitElement {
}
}

handleEntityIdSetHoverOver(entityId: string): void {
handleEntityIdSetHoverOver(entityId: string, svgElementInfo: FloorplanSvgElementInfo): void {
const entityInfo = this.entityInfos[entityId];
if (entityInfo) this.handleEntitySetHoverOver(entityInfo);
if (entityInfo) this.handleEntitySetHoverOver(entityInfo, svgElementInfo);
}

handleEntitySetHoverOver(entityInfo: FloorplanEntityInfo): void {
handleEntitySetHoverOver(entityInfo: FloorplanEntityInfo, svgElementInfo: FloorplanSvgElementInfo): void {
const entityId = entityInfo.entityId as string;
const entityState = this.hass.states[entityId];

Expand All @@ -1501,7 +1503,7 @@ export class FloorplanElement extends LitElement {
isHoverInfo ||
(typeof ruleInfo.rule.hover_action === 'object' &&
(ruleInfo.rule.hover_action as FloorplanActionConfig).action ===
'hover-info');
'hover-info');
isHoverInfo =
isHoverInfo ||
(Array.isArray(ruleInfo.rule.hover_action) &&
Expand Down Expand Up @@ -1529,9 +1531,8 @@ export class FloorplanElement extends LitElement {

Object.keys(entityState.attributes).map((key) => {
if (!hoverInfoFilter.has(key)) {
titleText += `${key}: ${
(entityState.attributes as Record<string, unknown>)[key]
}\n`;
titleText += `${key}: ${(entityState.attributes as Record<string, unknown>)[key]
}\n`;
}
});
titleText += '\n';
Expand All @@ -1547,6 +1548,15 @@ export class FloorplanElement extends LitElement {
});
}
}
else if (ruleInfo.rule.hover_action) {
this.handleActions(
ruleInfo.rule.hover_action,
entityInfo.entityId,
svgElementInfo,
ruleInfo
);

}
}
}
}
Expand Down Expand Up @@ -1701,7 +1711,7 @@ export class FloorplanElement extends LitElement {
if (
!confirm(
actionConfig.confirmation.text ||
`Are you sure you want to ${actionConfig.action}?`
`Are you sure you want to ${actionConfig.action}?`
)
) {
return;
Expand Down Expand Up @@ -2092,7 +2102,10 @@ export class FloorplanElement extends LitElement {
typeof serviceData === 'string'
? serviceData
: (serviceData.text as string);
Utils.setText(targetSvgElement, text);

// If the text has linebreakes, setText will split them up, into more than a single tspan element. Each tspan will use the shift y axis as a offset (except for the first element)
const shiftYAxis = actionConfig.service_data?.shift_y_axis ? actionConfig.service_data?.shift_y_axis : '1em';
Utils.setText(targetSvgElement, text, shiftYAxis);
}
break;

Expand Down
10 changes: 10 additions & 0 deletions src/components/floorplan/lib/floorplan-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,13 @@ export class FloorplanVariableConfig {
name!: string;
value!: unknown;
}

export class FloorplanCustomEvent extends Event {
detail!: FloorplanCallServiceEventConfig;
}

export interface FloorplanCallServiceEventConfig
extends FloorplanCallServiceActionConfig {
entity?: string;
element?: string;
}
8 changes: 4 additions & 4 deletions src/components/floorplan/lib/floorplan-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ export class FloorplanSvgElementInfo {
public svgElement: SVGGraphicsElement,
public originalSvgElement: SVGGraphicsElement,
public originalBBox: DOMRect
) {}
) { }
}

export class FloorplanRuleInfo {
svgElementInfos: { [key: string]: FloorplanSvgElementInfo } = {};
imageUrl!: string;
imageLoader!: number | undefined;

constructor(public rule: FloorplanRuleConfig) {}
constructor(public rule: FloorplanRuleConfig) { }
}

export class FloorplanEntityInfo {
Expand All @@ -48,5 +48,5 @@ export class FloorplanClickContext {
public svgElementInfo: FloorplanSvgElementInfo,
public ruleInfo: FloorplanRuleInfo,
public actions: Array<FloorplanActionConfig>
) {}
}
) { }
}
Loading

0 comments on commit 2044e3f

Please sign in to comment.