diff --git a/core/modules/widgets/blockid.js b/core/modules/widgets/blockid.js index 47ce11722..9aef2a3a5 100644 --- a/core/modules/widgets/blockid.js +++ b/core/modules/widgets/blockid.js @@ -9,8 +9,8 @@ var Widget = require("$:/core/modules/widgets/widget.js").widget; var BlockIdWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); // only this widget knows target info (if the block is before this node or not), so we need to hook the focus event, and process it here, instead of in the root widget. - this.hookFocusElementEvent = this.hookFocusElementEvent.bind(this); - $tw.hooks.addHook("th-focus-selector",this.hookFocusElementEvent); + this.hookNavigatedEvent = this.hookNavigatedEvent.bind(this); + $tw.hooks.addHook("th-navigated",this.hookNavigatedEvent); }; BlockIdWidget.prototype = new Widget(); @@ -33,32 +33,34 @@ BlockIdWidget.prototype.render = function(parent,nextSibling) { this.domNodes.push(this.spanDomNode); }; -BlockIdWidget.prototype.hookFocusElementEvent = function(event) { - if(!event || !event.param) return event; - var id = event.param.replace('#',''); - if(id !== this.id) return event; - var selector = event.param || "", - element, - baseElement = event.event && event.event.target ? event.event.target.ownerDocument : document; - element = $tw.utils.querySelectorSafe(selector,baseElement); +BlockIdWidget.prototype.hookNavigatedEvent = function(event) { + if(!event || !event.toBlockId) return event; + if(event.toBlockId !== this.id) return event; + var selector = "#"+event.toBlockId; + var baseElement = event.event && event.event.target ? event.event.target.ownerDocument : document; + // re-query the dom node, because `this.spanDomNode.parentNode` might already be removed from document + var element = $tw.utils.querySelectorSafe(selector,baseElement); if(!element || !element.parentNode) return; + // the actual block is always at the parent level element = element.parentNode; // need to check if the block is before this node if(this.previousSibling && element.previousSibling) { element = element.previousSibling; } - element.focus({ focusVisible: true }); // toggle class to trigger highlight animation $tw.utils.removeClass(element,"tc-focus-highlight"); - // Using setTimeout to ensure the removal takes effect before adding the class again. + // we have enabled `navigateSuppressNavigation` to avoid collision with scroll effect of `tm-navigate` + element.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" }); + element.focus({ focusVisible: true }); setTimeout(function() { + // Using setTimeout to ensure the removal takes effect before adding the class again. $tw.utils.addClass(element,"tc-focus-highlight"); }, 50); return false; }; BlockIdWidget.prototype.removeChildDomNodes = function() { - $tw.hooks.removeHook("th-focus-selector",this.hookFocusElementEvent); + $tw.hooks.removeHook("th-focus-selector",this.hookNavigatedEvent); }; /* diff --git a/core/modules/widgets/link.js b/core/modules/widgets/link.js index 6bb3aa4d2..372a45beb 100755 --- a/core/modules/widgets/link.js +++ b/core/modules/widgets/link.js @@ -150,6 +150,7 @@ LinkWidget.prototype.handleClickEvent = function(event) { this.dispatchEvent({ type: "tm-navigate", navigateTo: this.to, + toBlockId: this.toBlockId, navigateFromTitle: this.getVariable("storyTiddler"), navigateFromNode: this, navigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height @@ -160,24 +161,13 @@ LinkWidget.prototype.handleClickEvent = function(event) { navigateFromClientRight: bounds.right, navigateFromClientBottom: bounds.bottom, navigateFromClientHeight: bounds.height, - navigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1), + navigateSuppressNavigation: this.toBlockId || event.metaKey || event.ctrlKey || (event.button === 1), metaKey: event.metaKey, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey, event: event }); - if(this.toBlockId) { - var duration = $tw.utils.getAnimationDuration(); - var self = this; - setTimeout(function() { - self.dispatchEvent({ - type: "tm-focus-selector", - param: "#" + self.toBlockId, - event: event, - }); - },duration); - } if(this.domNodes[0].hasAttribute("href")) { event.preventDefault(); } diff --git a/core/modules/widgets/navigator.js b/core/modules/widgets/navigator.js index efdbba83f..1ce51d302 100755 --- a/core/modules/widgets/navigator.js +++ b/core/modules/widgets/navigator.js @@ -154,6 +154,7 @@ NavigatorWidget.prototype.handleNavigateEvent = function(event) { this.addToHistory(event.navigateTo,event.navigateFromClientRect); } } + $tw.hooks.invokeHook("th-navigated",event); return false; }; diff --git a/editions/dev/tiddlers/new/Hook__th-navigated.tid b/editions/dev/tiddlers/new/Hook__th-navigated.tid new file mode 100644 index 000000000..0315529ba --- /dev/null +++ b/editions/dev/tiddlers/new/Hook__th-navigated.tid @@ -0,0 +1,11 @@ +tags: HookMechanism +title: Hook: th-navigated +type: text/vnd.tiddlywiki + +This hook allows plugins to do things after navigation takes effect. + +Hook function parameters are same as [[Hook: th-navigating]]: + +Return value: + +* possibly modified event object diff --git a/editions/tw5.com/tiddlers/wikitext/Block Level Links in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Block Level Links in WikiText.tid index f460d1c9b..6b553fc49 100644 --- a/editions/tw5.com/tiddlers/wikitext/Block Level Links in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Block Level Links in WikiText.tid @@ -1,6 +1,6 @@ caption: Block Level Links created: 20230916061138153 -modified: 20230916062623280 +modified: 20230916070710392 tags: WikiText title: Block Level Links in WikiText type: text/vnd.tiddlywiki @@ -35,7 +35,7 @@ Some block, for example, code block, can't be suffixed by `^id`, but we can add ">> -! Link to the block ID +! Link to the block ID ^linkto091607 Adding `^blockID` after the title in the link, will make this link highlight the block with that ID. diff --git a/editions/tw5.com/tiddlers/wikitext/Linking in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Linking in WikiText.tid index 6d401aad6..b7aa53fab 100644 --- a/editions/tw5.com/tiddlers/wikitext/Linking in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Linking in WikiText.tid @@ -1,6 +1,6 @@ caption: Linking created: 20131205155230596 -modified: 20211230145939554 +modified: 20230916070722108 tags: WikiText title: Linking in WikiText type: text/vnd.tiddlywiki @@ -128,4 +128,4 @@ See [[Anchor Links using HTML]] for more information. You can link to a specific block within a tiddler using `^blockId` syntax. You will also get block level backlinks with this technique. Some examples are in [[BlockIdWidget^exampleid1]]. -See [[Block Level Links in WikiText]] for more information. +See [[Block Level Links in WikiText^linkto091607]] for more information.