diff --git a/packages/main/src/Breadcrumbs.hbs b/packages/main/src/Breadcrumbs.hbs index c4e737ebcee2..7bd5a456446d 100644 --- a/packages/main/src/Breadcrumbs.hbs +++ b/packages/main/src/Breadcrumbs.hbs @@ -20,7 +20,7 @@ id="{{this._id}}-link-wrapper"> `${x._id}-link` === link.id); - if (!this.fireEvent("item-click", { item }, true)) { + + if (!this.fireEvent("item-click", { item, ...event.detail }, true)) { event.preventDefault(); } } - _onLabelPress() { + _onLabelPress(event) { const items = this.getSlottedNodes("items"), item = items[items.length - 1]; - this.fireEvent("item-click", { item }); + + this.fireEvent("item-click", { item, ...event.detail }); } _onOverflowListItemSelect(event) { diff --git a/packages/main/src/Link.js b/packages/main/src/Link.js index 8c4bd1d74159..f12eb23aa629 100644 --- a/packages/main/src/Link.js +++ b/packages/main/src/Link.js @@ -206,9 +206,20 @@ const metadata = { * * @event * @public - * @native + * @allowPreventDefault + * @param {Boolean} altKey Returns whether the "ALT" key was pressed when the event was triggered. + * @param {Boolean} ctrlKey Returns whether the "CTRL" key was pressed when the event was triggered. + * @param {Boolean} metaKey Returns whether the "META" key was pressed when the event was triggered. + * @param {Boolean} shiftKey Returns whether the "SHIFT" key was pressed when the event was triggered. */ - click: {}, + click: { + detail: { + altKey: { type: Boolean }, + ctrlKey: { type: Boolean }, + metaKey: { type: Boolean }, + shiftKey: { type: Boolean }, + }, + }, }, }; @@ -331,7 +342,25 @@ class Link extends UI5Element { } _onclick(event) { + const { + altKey, + ctrlKey, + metaKey, + shiftKey, + } = event; + event.isMarked = "link"; + + const executeEvent = this.fireEvent("click", { + altKey, + ctrlKey, + metaKey, + shiftKey, + }, true); + + if (!executeEvent) { + event.preventDefault(); + } } _onfocusin(event) { @@ -345,12 +374,7 @@ class Link extends UI5Element { _onkeydown(event) { if (isEnter(event)) { - event.preventDefault(); - const executeEvent = this.fireEvent("click", null, true); - - if (executeEvent) { - this.href && window.open(this.href, this.target); - } + this._onclick(event); } else if (isSpace(event)) { event.preventDefault(); } @@ -364,11 +388,12 @@ class Link extends UI5Element { return; } - event.preventDefault(); + this._onclick(event); + + if (this.href && !event.defaultPrevented) { + const customEvent = new MouseEvent("click"); - const executeEvent = this.fireEvent("click", null, true); - if (executeEvent) { - this.href && window.open(this.href, this.target); + this.getDomRef().dispatchEvent(customEvent); } } } diff --git a/packages/main/test/pages/Breadcrumbs.html b/packages/main/test/pages/Breadcrumbs.html index f3dbc2e16c8d..623800794809 100644 --- a/packages/main/test/pages/Breadcrumbs.html +++ b/packages/main/test/pages/Breadcrumbs.html @@ -178,8 +178,22 @@

Empty Breadcrumbs with Location only

var breadcrumbsPreventDefault = document.querySelector("#breadcrumbsPreventDefault"); breadcrumbsPreventDefault.addEventListener("ui5-item-click", (event) => { + let keyText =''; + + if(event.detail.ctrlKey) { + keyText += 'CTRL:'; + } + if(event.detail.altKey) { + keyText += 'ALT:'; + } + if(event.detail.shiftKey) { + keyText += 'SHIFT:'; + } + if(event.detail.metaKey) { + keyText += 'META:'; + } event.preventDefault(); - result.innerText = event.detail.item.innerText; + result.innerText = keyText + event.detail.item.innerText; }); extendSizeBtn.addEventListener("click", () => resizeContainer(true)); diff --git a/packages/main/test/pages/Link.html b/packages/main/test/pages/Link.html index 4f61aaf9f1f5..4b5106b6452f 100644 --- a/packages/main/test/pages/Link.html +++ b/packages/main/test/pages/Link.html @@ -116,6 +116,12 @@

Link opens a dialog

+
+

Link with prevent default and modifiers

+ Link 1 + +
+ diff --git a/packages/main/test/specs/Breadcrumbs.spec.js b/packages/main/test/specs/Breadcrumbs.spec.js index 6d1075993972..0a48fbec5418 100644 --- a/packages/main/test/specs/Breadcrumbs.spec.js +++ b/packages/main/test/specs/Breadcrumbs.spec.js @@ -1,5 +1,12 @@ const assert = require("chai").assert; const PORT = require("./_port.js"); +const KEYS = { + SHIFT: '\uE008', + CTRL: '\uE009', + ALT: '\uE00A', + META: '\uE03D', + ENTER: '\uE007', +} describe("Breadcrumbs general interaction", () => { before(async () => { @@ -233,4 +240,119 @@ describe("Breadcrumbs general interaction", () => { assert.strictEqual(await eventResult.getText(), await link.getText(), "label for pressed link is correct"); }); + it("passes special keys pressed while item clicked", async () => { + // CTRL key is skipped since there is default browser behavior where popover is opened. + const breadcrumbs = await browser.$("#breadcrumbsPreventDefault"), + link = (await breadcrumbs.shadow$$("ui5-link"))[1]; + let eventResult; + + // Setup for META Key + await browser.performActions([{ + type: 'key', + id: 'keyboard1', + actions: [{ type: 'keyDown', value: KEYS.META }], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + eventResult = await browser.$("#result"); + assert.strictEqual(await eventResult.getText(), 'META:' + await link.getText(), "label for pressed link is correct"); + + // Setup for ALT Key + await browser.performActions([{ + type: 'key', + id: 'keyboard2', + actions: [{ type: 'keyDown', value: KEYS.ALT }], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + eventResult = await browser.$("#result"); + assert.strictEqual(await eventResult.getText(), 'ALT:' + await link.getText(), "label for pressed link is correct"); + + // Setup for SHIFT Key + await browser.performActions([{ + type: 'key', + id: 'keyboard3', + actions: [{ type: 'keyDown', value: KEYS.SHIFT }], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + eventResult = await browser.$("#result"); + assert.strictEqual(await eventResult.getText(), 'SHIFT:' + await link.getText(), "label for pressed link is correct"); + }); + + it("passes special keys pressed while item pressed with keyboard", async () => { + const breadcrumbs = await browser.$("#breadcrumbsPreventDefault"), + link = (await breadcrumbs.shadow$$("ui5-link"))[1]; + + // Setup for META Key + await browser.performActions([{ + type: 'key', + id: 'keyboard1', + actions: [ + { type: 'keyDown', value: KEYS.META }, + { type: 'keyDown', value: KEYS.ENTER } + ], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + eventResult = await browser.$("#result"); + assert.strictEqual(await eventResult.getText(), 'META:' + await link.getText(), "label for pressed link is correct"); + + // Setup for ALT Key + await browser.performActions([{ + type: 'key', + id: 'keyboard2', + actions: [ + { type: 'keyDown', value: KEYS.ALT }, + { type: 'keyDown', value: KEYS.ENTER } + ], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + eventResult = await browser.$("#result"); + assert.strictEqual(await eventResult.getText(), 'ALT:' + await link.getText(), "label for pressed link is correct"); + + // Setup for SHIFT Key + await browser.performActions([{ + type: 'key', + id: 'keyboard3', + actions: [ + { type: 'keyDown', value: KEYS.SHIFT }, + { type: 'keyDown', value: KEYS.ENTER } + ], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + eventResult = await browser.$("#result"); + assert.strictEqual(await eventResult.getText(), 'SHIFT:' + await link.getText(), "label for pressed link is correct"); + + // Setup for CTRL Key + await browser.performActions([{ + type: 'key', + id: 'keyboard3', + actions: [ + { type: 'keyDown', value: KEYS.CTRL }, + { type: 'keyDown', value: KEYS.ENTER } + ], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + eventResult = await browser.$("#result"); + assert.strictEqual(await eventResult.getText(), 'CTRL:' + await link.getText(), "label for pressed link is correct"); + }); + }); diff --git a/packages/main/test/specs/Link.spec.js b/packages/main/test/specs/Link.spec.js index 888fa2771ef1..4d343768e5ab 100644 --- a/packages/main/test/specs/Link.spec.js +++ b/packages/main/test/specs/Link.spec.js @@ -1,5 +1,10 @@ const assert = require("chai").assert; const PORT = require("./_port.js"); +const KEYS = { + SHIFT: '\uE008', + ALT: '\uE00A', + META: '\uE03D', +} describe("General API", () => { before(async () => { @@ -87,4 +92,50 @@ describe("General API", () => { assert.strictEqual(await link.shadow$("a").getAttribute("aria-label"), "more info", "Attribute is reflected"); }); + + it("passes special keys pressed while item clicked", async () => { + // CTRL key is skipped since there is default browser behavior where popover is opened. + const link = await browser.$("#modifierLink"); + let result; + + // Setup for META Key + await browser.performActions([{ + type: 'key', + id: 'keyboard1', + actions: [{ type: 'keyDown', value: KEYS.META }], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + result = await browser.$("#modifierResult"); + assert.strictEqual(await result.getText(), 'META:' + await link.getText(), "label for pressed link is correct"); + + // Setup for ALT Key + await browser.performActions([{ + type: 'key', + id: 'keyboard2', + actions: [{ type: 'keyDown', value: KEYS.ALT }], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + result = await browser.$("#modifierResult"); + assert.strictEqual(await result.getText(), 'ALT:' + await link.getText(), "label for pressed link is correct"); + + // Setup for SHIFT Key + await browser.performActions([{ + type: 'key', + id: 'keyboard3', + actions: [{ type: 'keyDown', value: KEYS.SHIFT }], + }]); + // Action + await link.click(); + await browser.releaseActions(); + // Check + result = await browser.$("#modifierResult"); + assert.strictEqual(await result.getText(), 'SHIFT:' + await link.getText(), "label for pressed link is correct"); + }); + });