mirror of
				https://github.com/Jermolene/TiddlyWiki5
				synced 2025-10-30 23:23:02 +00:00 
			
		
		
		
	refactor: use history mechanism for block level navigation
This commit is contained in:
		| @@ -90,12 +90,12 @@ Story.prototype.saveStoryList = function(storyList) { | |||||||
| 	)); | 	)); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| Story.prototype.addToHistory = function(navigateTo,navigateFromClientRect) { | Story.prototype.addToHistory = function(navigateTo,fromPageRect,anchor) { | ||||||
| 	var titles = $tw.utils.isArray(navigateTo) ? navigateTo : [navigateTo]; | 	var titles = $tw.utils.isArray(navigateTo) ? navigateTo : [navigateTo]; | ||||||
| 	// Add a new record to the top of the history stack | 	// Add a new record to the top of the history stack | ||||||
| 	var historyList = this.wiki.getTiddlerData(this.historyTitle,[]); | 	var historyList = this.wiki.getTiddlerData(this.historyTitle,[]); | ||||||
| 	$tw.utils.each(titles,function(title) { | 	$tw.utils.each(titles,function(title) { | ||||||
| 		historyList.push({title: title, fromPageRect: navigateFromClientRect}); | 		historyList.push({title: title, fromPageRect: fromPageRect, anchor: anchor}); | ||||||
| 	}); | 	}); | ||||||
| 	this.wiki.setTiddlerData(this.historyTitle,historyList,{"current-tiddler": titles[titles.length-1]}); | 	this.wiki.setTiddlerData(this.historyTitle,historyList,{"current-tiddler": titles[titles.length-1]}); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -26,13 +26,26 @@ ClassicStoryView.prototype.navigateTo = function(historyInfo) { | |||||||
| 	} | 	} | ||||||
| 	var listItemWidget = this.listWidget.children[listElementIndex], | 	var listItemWidget = this.listWidget.children[listElementIndex], | ||||||
| 		targetElement = listItemWidget.findFirstDomNode(); | 		targetElement = listItemWidget.findFirstDomNode(); | ||||||
|  | 	// If anchor is provided, find the element the anchor pointing to | ||||||
|  | 	var foundAnchor = false; | ||||||
|  | 	if(targetElement && historyInfo.anchor) { | ||||||
|  | 		var anchorElement = targetElement.querySelector("[data-anchor-id='" + historyInfo.anchor + "']"); | ||||||
|  | 		if(anchorElement) { | ||||||
|  | 			targetElement = anchorElement.parentNode; | ||||||
|  | 			var isBefore = anchorElement.dataset.anchorPreviousSibling === "true"; | ||||||
|  | 			if(isBefore) { | ||||||
|  | 				targetElement = targetElement.previousSibling; | ||||||
|  | 			} | ||||||
|  | 			foundAnchor = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	// Abandon if the list entry isn't a DOM element (it might be a text node) | 	// Abandon if the list entry isn't a DOM element (it might be a text node) | ||||||
| 	if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) { | 	if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	if(duration) { | 	if(duration) { | ||||||
| 		// Scroll the node into view | 		// Scroll the node into view | ||||||
| 		this.listWidget.dispatchEvent({type: "tm-scroll", target: targetElement}); | 		this.listWidget.dispatchEvent({type: "tm-scroll", target: targetElement, highlight: foundAnchor}); | ||||||
| 	} else { | 	} else { | ||||||
| 		targetElement.scrollIntoView(); | 		targetElement.scrollIntoView(); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -49,7 +49,9 @@ Handle an event | |||||||
| */ | */ | ||||||
| PageScroller.prototype.handleEvent = function(event) { | PageScroller.prototype.handleEvent = function(event) { | ||||||
| 	if(event.type === "tm-scroll") { | 	if(event.type === "tm-scroll") { | ||||||
| 		var options = {}; | 		var options = { | ||||||
|  | 			highlight: event.highlight, | ||||||
|  | 		}; | ||||||
| 		if($tw.utils.hop(event.paramObject,"animationDuration")) { | 		if($tw.utils.hop(event.paramObject,"animationDuration")) { | ||||||
| 			options.animationDuration = event.paramObject.animationDuration; | 			options.animationDuration = event.paramObject.animationDuration; | ||||||
| 		} | 		} | ||||||
| @@ -65,14 +67,21 @@ PageScroller.prototype.handleEvent = function(event) { | |||||||
|  |  | ||||||
| /* | /* | ||||||
| Handle a scroll event hitting the page document | Handle a scroll event hitting the page document | ||||||
|  |  | ||||||
|  | options: | ||||||
|  | - animationDuration: total time of scroll animation | ||||||
|  | - highlight: highlight the element after scrolling, to make it evident. Usually to focus an anchor in the middle of the tiddler. | ||||||
| */ | */ | ||||||
| PageScroller.prototype.scrollIntoView = function(element,callback,options) { | PageScroller.prototype.scrollIntoView = function(element,callback,options) { | ||||||
| 	var self = this, | 	var self = this, | ||||||
| 		duration = $tw.utils.hop(options,"animationDuration") ? parseInt(options.animationDuration) : $tw.utils.getAnimationDuration(), | 		duration = $tw.utils.hop(options,"animationDuration") ? parseInt(options.animationDuration) : $tw.utils.getAnimationDuration(), | ||||||
|  | 		highlight = options.highlight || false, | ||||||
| 		srcWindow = element ? element.ownerDocument.defaultView : window; | 		srcWindow = element ? element.ownerDocument.defaultView : window; | ||||||
| 	// Now get ready to scroll the body | 	// Now get ready to scroll the body | ||||||
| 	this.cancelScroll(srcWindow); | 	this.cancelScroll(srcWindow); | ||||||
| 	this.startTime = Date.now(); | 	this.startTime = Date.now(); | ||||||
|  | 	// toggle class to allow trigger the highlight animation | ||||||
|  | 	$tw.utils.removeClass(element,"tc-focus-highlight"); | ||||||
| 	// Get the height of any position:fixed toolbars | 	// Get the height of any position:fixed toolbars | ||||||
| 	var toolbar = srcWindow.document.querySelector(".tc-adjust-top-of-scroll"), | 	var toolbar = srcWindow.document.querySelector(".tc-adjust-top-of-scroll"), | ||||||
| 		offset = 0; | 		offset = 0; | ||||||
| @@ -121,6 +130,15 @@ PageScroller.prototype.scrollIntoView = function(element,callback,options) { | |||||||
| 			srcWindow.scrollTo(scrollPosition.x + (endX - scrollPosition.x) * t,scrollPosition.y + (endY - scrollPosition.y) * t); | 			srcWindow.scrollTo(scrollPosition.x + (endX - scrollPosition.x) * t,scrollPosition.y + (endY - scrollPosition.y) * t); | ||||||
| 			if(t < 1) { | 			if(t < 1) { | ||||||
| 				self.idRequestFrame = self.requestAnimationFrame.call(srcWindow,drawFrame); | 				self.idRequestFrame = self.requestAnimationFrame.call(srcWindow,drawFrame); | ||||||
|  | 			} else { | ||||||
|  | 				// the animation is end. | ||||||
|  | 				if(highlight) { | ||||||
|  | 					element.focus({ focusVisible: true }); | ||||||
|  | 					// Using setTimeout to ensure the removal takes effect before adding the class again. | ||||||
|  | 					setTimeout(function() { | ||||||
|  | 						$tw.utils.addClass(element,"tc-focus-highlight"); | ||||||
|  | 					}, 50); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
| 	drawFrame(); | 	drawFrame(); | ||||||
|   | |||||||
| @@ -23,8 +23,9 @@ AnchorWidget.prototype.render = function(parent,nextSibling) { | |||||||
| 	this.idNode = this.document.createElement("span"); | 	this.idNode = this.document.createElement("span"); | ||||||
| 	this.idNode.setAttribute("data-anchor-id",this.id); | 	this.idNode.setAttribute("data-anchor-id",this.id); | ||||||
| 	this.idNode.setAttribute("data-anchor-title",this.tiddlerTitle); | 	this.idNode.setAttribute("data-anchor-title",this.tiddlerTitle); | ||||||
| 	if(this.before) { | 	// if the actual block is before this node, we need to add a flag to the node | ||||||
| 		this.idNode.setAttribute("data-before","true"); | 	if(this.previousSibling) { | ||||||
|  | 		this.idNode.setAttribute("data-anchor-previous-sibling","true"); | ||||||
| 	} | 	} | ||||||
| 	this.idNode.className = "tc-anchor"; | 	this.idNode.className = "tc-anchor"; | ||||||
| 	parent.insertBefore(this.idNode,nextSibling); | 	parent.insertBefore(this.idNode,nextSibling); | ||||||
|   | |||||||
| @@ -138,9 +138,10 @@ NavigatorWidget.prototype.addToStory = function(title,fromTitle) { | |||||||
| Add a new record to the top of the history stack | Add a new record to the top of the history stack | ||||||
| title: a title string or an array of title strings | title: a title string or an array of title strings | ||||||
| fromPageRect: page coordinates of the origin of the navigation | fromPageRect: page coordinates of the origin of the navigation | ||||||
|  | anchor:optional anchor id in this tiddler | ||||||
| */ | */ | ||||||
| NavigatorWidget.prototype.addToHistory = function(title,fromPageRect) { | NavigatorWidget.prototype.addToHistory = function(title,fromPageRect,anchor) { | ||||||
| 	this.story.addToHistory(title,fromPageRect,this.historyTitle); | 	this.story.addToHistory(title,fromPageRect,anchor); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -150,9 +151,8 @@ NavigatorWidget.prototype.handleNavigateEvent = function(event) { | |||||||
| 	event = $tw.hooks.invokeHook("th-navigating",event); | 	event = $tw.hooks.invokeHook("th-navigating",event); | ||||||
| 	if(event.navigateTo) { | 	if(event.navigateTo) { | ||||||
| 		this.addToStory(event.navigateTo,event.navigateFromTitle); | 		this.addToStory(event.navigateTo,event.navigateFromTitle); | ||||||
| 		event = $tw.hooks.invokeHook("th-navigating-add-history",event); |  | ||||||
| 		if(!event.navigateSuppressNavigation) { | 		if(!event.navigateSuppressNavigation) { | ||||||
| 			this.addToHistory(event.navigateTo,event.navigateFromClientRect); | 			this.addToHistory(event.navigateTo,event.navigateFromClientRect,event.toAnchor); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	$tw.hooks.invokeHook("th-navigated",event); | 	$tw.hooks.invokeHook("th-navigated",event); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 linonetwo
					linonetwo