Skip to content

Commit 4359b9a

Browse files
authored
feat(ui5-suggestion-item): enable mouseover|out events (#1784)
The user can now bind for mouseover and mouseout events on the ui5-suggestion-item elements and perform some other action. For example: opening another popover, pointing to particular suggestion, when hovered. FIXES: #1768
1 parent 511cb40 commit 4359b9a

File tree

6 files changed

+109
-15
lines changed

6 files changed

+109
-15
lines changed

packages/main/src/Input.js

+32
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,21 @@ class Input extends UI5Element {
734734
this.valueBeforeItemSelection = this.value;
735735
this.value = item.group ? "" : item.textContent;
736736
this._announceSelectedItem();
737+
this._previewItem = item;
738+
}
739+
740+
/**
741+
* The suggestion item on preview.
742+
* @type { ui5-suggestion-item }
743+
* @readonly
744+
* @public
745+
*/
746+
get previewItem() {
747+
if (!this._previewItem) {
748+
return null;
749+
}
750+
751+
return this.getSuggestionByListItem(this._previewItem);
737752
}
738753

739754
async fireEventByAction(action) {
@@ -795,13 +810,30 @@ class Input extends UI5Element {
795810
return this.getInputId();
796811
}
797812

813+
getSuggestionByListItem(item) {
814+
const key = parseInt(item.getAttribute("data-ui5-key"));
815+
return this.suggestionItems[key];
816+
}
817+
798818
getInputId() {
799819
return `${this._id}-inner`;
800820
}
801821

802822
/* Suggestions interface */
803823
onItemFocused() {}
804824

825+
onItemMouseOver(event) {
826+
const item = event.target;
827+
const suggestion = this.getSuggestionByListItem(item);
828+
suggestion.fireEvent("mouseover", { targetRef: item });
829+
}
830+
831+
onItemMouseOut(event) {
832+
const item = event.target;
833+
const suggestion = this.getSuggestionByListItem(item);
834+
suggestion.fireEvent("mouseout", { targetRef: item });
835+
}
836+
805837
onItemSelected(item, keyboardUsed) {
806838
this.selectSuggestion(item, keyboardUsed);
807839
}

packages/main/src/InputPopover.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
{{/if}}
4949
{{/unless}}
5050

51-
5251
<ui5-list separators="Inner">
5352
{{#each suggestionsTexts}}
5453
{{#if group}}
@@ -61,6 +60,7 @@
6160
info="{{this.info}}"
6261
info-state="{{this.infoState}}"
6362
@ui5-_item-press="{{ fnOnSuggestionItemPress }}"
63+
data-ui5-key="{{key}}"
6464
>{{ this.text }}</ui5-li>
6565
{{/if}}
6666
{{/each}}

packages/main/src/Popover.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,10 @@ class Popover extends Popup {
248248
/**
249249
* Opens the popover.
250250
* @param {HTMLElement} opener the element that the popover is opened by
251+
* @param {boolean} preventInitialFocus prevents applying the focus inside the popover
251252
* @public
252253
*/
253-
openBy(opener) {
254+
openBy(opener, preventInitialFocus = false) {
254255
if (!opener || this.opened) {
255256
return;
256257
}
@@ -266,7 +267,10 @@ class Popover extends Popup {
266267

267268
this.fireEvent("before-open", {});
268269
this.reposition();
269-
this.applyInitialFocus();
270+
271+
if (!preventInitialFocus) {
272+
this.applyInitialFocus();
273+
}
270274

271275
addOpenedPopover(this);
272276

packages/main/src/features/InputSuggestions.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class Suggestions {
3030
// Press and Focus handlers
3131
this.fnOnSuggestionItemPress = this.onItemPress.bind(this);
3232
this.fnOnSuggestionItemFocus = this.onItemFocused.bind(this);
33+
this.fnOnSuggestionItemMouseOver = this.onItemMouseOver.bind(this);
34+
this.fnOnSuggestionItemMouseOut = this.onItemMouseOut.bind(this);
3335

3436
// An integer value to store the currently selected item position,
3537
// that changes due to user interaction.
@@ -45,7 +47,7 @@ class Suggestions {
4547
const inputSuggestionItems = this._getComponent().suggestionItems;
4648

4749
const suggestions = [];
48-
inputSuggestionItems.map(suggestion => {
50+
inputSuggestionItems.map((suggestion, idx) => {
4951
return suggestions.push({
5052
text: suggestion.text || suggestion.textContent, // keep textContent for compatibility
5153
description: suggestion.description || undefined,
@@ -54,6 +56,7 @@ class Suggestions {
5456
info: suggestion.info || undefined,
5557
infoState: suggestion.infoState,
5658
group: suggestion.group,
59+
key: idx,
5760
});
5861
});
5962

@@ -119,6 +122,14 @@ class Suggestions {
119122
this._getComponent().onItemFocused();
120123
}
121124

125+
onItemMouseOver(event) {
126+
this._getComponent().onItemMouseOver(event);
127+
}
128+
129+
onItemMouseOut(event) {
130+
this._getComponent().onItemMouseOut(event);
131+
}
132+
122133
onItemSelected(selectedItem, keyboardUsed) {
123134
const item = selectedItem || this._getItems()[this.selectedItemIndex];
124135

@@ -155,6 +166,10 @@ class Suggestions {
155166
list.addEventListener("ui5-item-press", this.fnOnSuggestionItemPress);
156167
list.removeEventListener("ui5-item-focused", this.fnOnSuggestionItemFocus);
157168
list.addEventListener("ui5-item-focused", this.fnOnSuggestionItemFocus);
169+
list.removeEventListener("mouseover", this.fnOnSuggestionItemMouseOver);
170+
list.addEventListener("mouseover", this.fnOnSuggestionItemMouseOver);
171+
list.removeEventListener("mouseout", this.fnOnSuggestionItemMouseOut);
172+
list.addEventListener("mouseout", this.fnOnSuggestionItemMouseOut);
158173
}
159174

160175
_attachPopupListeners() {

packages/main/test/pages/Input.html

+53-10
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,32 @@ <h3>Input in Compact</h3>
4040
</div>
4141

4242
<h3> Input suggestions with ui5-suggestion-item</h3>
43-
<ui5-input id="inputItemPreviewRes" placeholder="preview item test"></ui5-input>
44-
<ui5-input id="inputItemPreview" show-suggestions style="width: 100%">
45-
<ui5-suggestion-item text="Cozy"></ui5-suggestion-item>
46-
<ui5-suggestion-item text="Compact"></ui5-suggestion-item>
47-
<ui5-suggestion-item text="Condensed"></ui5-suggestion-item>
48-
<ui5-suggestion-item text="Cozy"></ui5-suggestion-item>
49-
<ui5-suggestion-item text="Compact"></ui5-suggestion-item>
50-
<ui5-suggestion-item text="Condensed"></ui5-suggestion-item>
43+
44+
<div style="width: 200px">Input keyp</div>
45+
<ui5-input id="keyupResult" style="width: 100%"></ui5-input> <br>
46+
47+
<div style="width: 200px">Input suggestion-item-preview</div>
48+
<ui5-input id="inputItemPreviewRes" style="width:100%"></ui5-input><br><br>
49+
50+
<div style="width: 200px">mouseover on item</div>
51+
<ui5-input id="mouseoverResult" style="width: 100%"></ui5-input> <br>
52+
53+
<div style="width: 200px">mouseout on item</div>
54+
<ui5-input id="mouseoutResult" style="width:100%"></ui5-input><br>
55+
56+
<ui5-input id="inputPreview" show-suggestions style="width: 200px">
57+
<ui5-suggestion-item class="suggestionItem" text="Cozy"></ui5-suggestion-item>
58+
<ui5-suggestion-item class="suggestionItem" text="Compact"></ui5-suggestion-item>
59+
<ui5-suggestion-item class="suggestionItem" text="Condensed"></ui5-suggestion-item>
60+
<ui5-suggestion-item class="suggestionItem" text="Cozy"></ui5-suggestion-item>
61+
<ui5-suggestion-item class="suggestionItem" text="Compact"></ui5-suggestion-item>
62+
<ui5-suggestion-item class="suggestionItem" text="Condensed"></ui5-suggestion-item>
5163
</ui5-input>
64+
65+
<ui5-popover id="quickViewCard" header-text="My Heading" id="pop" placement-type="Right">
66+
<ui5-button>Click me</ui5-button>
67+
</ui5-popover>
68+
5269
<br/>
5370
<br/>
5471
<h3>Input suggestions with ui5-li</h3>
@@ -314,8 +331,34 @@ <h3> Input with multiple icons</h3>
314331
inputChangeResult.value = ++inputChangeResultCounter;
315332
});
316333

317-
inputItemPreview.addEventListener("ui5-suggestion-item-preview", function (event) {
318-
inputItemPreviewRes.value = event.detail.item.textContent;
334+
// Preview suggestion item events
335+
inputPreview.addEventListener("ui5-suggestion-item-preview", function (event) {
336+
var item = event.detail.item;
337+
inputItemPreviewRes.value = item.textContent;
338+
339+
quickViewCard.close(false, true, true);
340+
quickViewCard.openBy(item, true);
341+
});
342+
343+
inputPreview.addEventListener("keyup", function (event) {
344+
const item = event.target.previewItem;
345+
keyupResult.value = "[key]: " + event.key + " , [preview item]:" + (item && item.text);
346+
});
347+
348+
[].slice.call(document.querySelectorAll(".suggestionItem")).forEach(function(el) {
349+
el.addEventListener("mouseover", function (event) {
350+
const targetRef = event.detail.targetRef;
351+
352+
mouseoverResult.value = targetRef.textContent;
353+
quickViewCard.openBy(targetRef, true);
354+
});
355+
356+
el.addEventListener("mouseout", function (event) {
357+
const targetRef = event.detail.targetRef;
358+
359+
mouseoutResult.value = targetRef.textContent;
360+
quickViewCard.close(false, true, true);
361+
});
319362
});
320363
</script>
321364
</body>

packages/main/test/specs/Input.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ describe("Input general interaction", () => {
130130
});
131131

132132
it("fires suggestion-item-preview", () => {
133-
const inputItemPreview = $("#inputItemPreview").shadow$("input");
133+
const inputItemPreview = $("#inputPreview").shadow$("input");
134134
const inputItemPreviewRes = $("#inputItemPreviewRes");
135135

136136
inputItemPreview.click();

0 commit comments

Comments
 (0)