From 1ecc5674ac92d6876ac63b552dd49bbc46f06feb Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 4 Mar 2017 14:01:34 -0800 Subject: [PATCH] Add fail handler --- src/Interfaces.ts | 6 ++++++ src/Linkifier.ts | 20 ++++++++++++++------ src/Types.ts | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/Interfaces.ts b/src/Interfaces.ts index ca228ce01..27ea4d4cb 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -85,6 +85,12 @@ export interface LinkMatcherOptions { * false if invalid. */ validationCallback?: LinkMatcherValidationCallback; + /** + * A callback that fires when a link click fails due to ctrl or cmd (mac) not + * being pressed. This allows hinting to the user after a likely failed + * click. + */ + clickFailCallback?: (event: MouseEvent) => any; /** * The priority of the link matcher, this defines the order in which the link * matcher is evaluated relative to others, from highest to lowest. The diff --git a/src/Linkifier.ts b/src/Linkifier.ts index 93248c307..6667af0cf 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -100,6 +100,7 @@ export class Linkifier { handler, matchIndex: options.matchIndex, validationCallback: options.validationCallback, + clickFailCallback: options.clickFailCallback, priority: options.priority || 0 }; this._addLinkMatcherToList(matcher); @@ -158,7 +159,7 @@ export class Linkifier { const matcher = this._linkMatchers[i]; const uri = this._findLinkMatch(text, matcher.regex, matcher.matchIndex); if (uri) { - const linkElement = this._doLinkifyRow(rowIndex, uri, matcher.handler); + const linkElement = this._doLinkifyRow(rowIndex, uri, matcher.handler, matcher.clickFailCallback); // Fire validation callback if (linkElement && matcher.validationCallback) { matcher.validationCallback(uri, isValid => { @@ -180,14 +181,14 @@ export class Linkifier { * @param {handler} handler The handler to trigger when the link is triggered. * @return The link element if it was added, otherwise undefined. */ - private _doLinkifyRow(rowIndex: number, uri: string, handler?: LinkMatcherHandler): HTMLElement { + private _doLinkifyRow(rowIndex: number, uri: string, handler?: LinkMatcherHandler, clickFailHandler?: (event: MouseEvent) => any): HTMLElement { // Iterate over nodes as we want to consider text nodes const nodes = this._rows[rowIndex].childNodes; for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; const searchIndex = node.textContent.indexOf(uri); if (searchIndex >= 0) { - const linkElement = this._createAnchorElement(uri, handler); + const linkElement = this._createAnchorElement(uri, handler, clickFailHandler); if (node.textContent.length === uri.length) { // Matches entire string @@ -230,11 +231,11 @@ export class Linkifier { * @param {string} uri The uri of the link. * @return {HTMLAnchorElement} The link. */ - private _createAnchorElement(uri: string, handler: LinkMatcherHandler): HTMLAnchorElement { + private _createAnchorElement(uri: string, handler: LinkMatcherHandler, failHandler: (event: MouseEvent) => any): HTMLAnchorElement { const element = this._document.createElement('a'); element.textContent = uri; if (handler) { - element.addEventListener('click', (event: KeyboardEvent) => { + element.addEventListener('click', (event: MouseEvent) => { // Don't execute the handler if the link is flagged as invalid if (element.classList.contains(INVALID_LINK_CLASS)) { return; @@ -242,15 +243,22 @@ export class Linkifier { // Require ctrl on click if (isMac ? event.metaKey : event.ctrlKey) { handler(uri); + } else { + if (failHandler) { + failHandler(event); + } } }); } else { element.href = uri; // Force link on another tab so work is not lost element.target = '_blank'; - element.addEventListener('click', (event: KeyboardEvent) => { + element.addEventListener('click', (event: MouseEvent) => { // Require ctrl on click if (isMac ? !event.metaKey : !event.ctrlKey) { + if (failHandler) { + failHandler(event); + } event.preventDefault(); return false; } diff --git a/src/Types.ts b/src/Types.ts index 2dbb47eff..d3e99dd0d 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -8,6 +8,7 @@ export type LinkMatcher = { handler: LinkMatcherHandler, matchIndex?: number, validationCallback?: LinkMatcherValidationCallback, + clickFailCallback?: (event: MouseEvent) => any, priority?: number }; export type LinkMatcherHandler = (uri: string) => void;