mirror of
				https://github.com/Jermolene/TiddlyWiki5
				synced 2025-10-25 12:47:40 +00:00 
			
		
		
		
	Re-introduce listviews
Now called storyviews because they're aware of the history structure as well as the list structure.
This commit is contained in:
		| @@ -19,6 +19,12 @@ The list widget creates list element sub-widgets that reach back into the list w | ||||
| */ | ||||
|  | ||||
| var ListWidget = function(parseTreeNode,options) { | ||||
| 	// Initialise the storyviews if they've not been done already | ||||
| 	if(!this.storyViews) { | ||||
| 		ListWidget.prototype.storyViews = {}; | ||||
| 		$tw.modules.applyMethods("storyview",this.storyViews); | ||||
| 	} | ||||
| 	// Main initialisation inherited from widget.js | ||||
| 	this.initialise(parseTreeNode,options); | ||||
| }; | ||||
|  | ||||
| @@ -45,6 +51,8 @@ ListWidget.prototype.execute = function() { | ||||
| 	this.template = this.getAttribute("template"); | ||||
| 	this.editTemplate = this.getAttribute("editTemplate"); | ||||
| 	this.variableName = this.getAttribute("variable","currentTiddler"); | ||||
| 	this.storyViewName = this.getAttribute("storyview"); | ||||
| 	this.historyTitle = this.getAttribute("history"); | ||||
| 	// Compose the list elements | ||||
| 	this.list = this.getTiddlerList(); | ||||
| 	var members = [], | ||||
| @@ -59,6 +67,11 @@ ListWidget.prototype.execute = function() { | ||||
| 	} | ||||
| 	// Construct the child widgets | ||||
| 	this.makeChildWidgets(members); | ||||
| 	// Clear the last history | ||||
| 	this.history = []; | ||||
| 	// Construct the storyview | ||||
| 	var StoryView = this.storyViews[this.storyViewName]; | ||||
| 	this.storyview = StoryView ? new StoryView(this) : null; | ||||
| }; | ||||
|  | ||||
| ListWidget.prototype.getTiddlerList = function() { | ||||
| @@ -111,15 +124,42 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of | ||||
| ListWidget.prototype.refresh = function(changedTiddlers) { | ||||
| 	var changedAttributes = this.computeAttributes(); | ||||
| 	// Completely refresh if any of our attributes have changed | ||||
| 	if(changedAttributes.filter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage) { | ||||
| 	if(changedAttributes.filter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) { | ||||
| 		this.refreshSelf(); | ||||
| 		return true; | ||||
| 	} else { | ||||
| 		// Handle any changes to the list | ||||
| 		return this.handleListChanges(changedTiddlers);	 | ||||
| 		var hasChanged = this.handleListChanges(changedTiddlers); | ||||
| 		// Handle any changes to the history stack | ||||
| 		if(this.historyTitle && changedTiddlers[this.historyTitle]) { | ||||
| 			this.handleHistoryChanges(); | ||||
| 		} | ||||
| 		return hasChanged; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Handle any changes to the history list | ||||
| */ | ||||
| ListWidget.prototype.handleHistoryChanges = function() { | ||||
| 	// Get the history data | ||||
| 	var newHistory = this.wiki.getTiddlerData(this.historyTitle,[]); | ||||
| 	// Ignore any entries of the history that match the previous history | ||||
| 	var entry = 0; | ||||
| 	while(entry < newHistory.length && entry < this.history.length && newHistory[entry].title === this.history[entry].title) { | ||||
| 		entry++; | ||||
| 	} | ||||
| 	// Navigate forwards to each of the new tiddlers | ||||
| 	while(entry < newHistory.length) { | ||||
| 		if(this.storyview && this.storyview.navigateTo) { | ||||
| 			this.storyview.navigateTo(newHistory[entry]); | ||||
| 		} | ||||
| 		entry++; | ||||
| 	} | ||||
| 	// Update the history | ||||
| 	this.history = newHistory; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Process any changes to the list | ||||
| */ | ||||
| @@ -192,20 +232,30 @@ ListWidget.prototype.findListItem = function(startIndex,title) { | ||||
| Insert a new list item at the specified index | ||||
| */ | ||||
| ListWidget.prototype.insertListItem = function(index,title) { | ||||
| 	var newItem = this.makeChildWidget(this.makeItemTemplate(title)); | ||||
| 	newItem.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work | ||||
| 	this.children.splice(index,0,newItem); | ||||
| 	var nextSibling = newItem.findNextSiblingDomNode(); | ||||
| 	newItem.render(this.parentDomNode,nextSibling); | ||||
| 	// Create, insert and render the new child widgets | ||||
| 	var widget = this.makeChildWidget(this.makeItemTemplate(title)); | ||||
| 	widget.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work | ||||
| 	this.children.splice(index,0,widget); | ||||
| 	var nextSibling = widget.findNextSiblingDomNode(); | ||||
| 	widget.render(this.parentDomNode,nextSibling); | ||||
| 	// Animate the insertion if required | ||||
| 	if(this.storyview && this.storyview.insert) { | ||||
| 		this.storyview.insert(widget); | ||||
| 	} | ||||
| 	return true; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Remvoe the specified list item | ||||
| Remove the specified list item | ||||
| */ | ||||
| ListWidget.prototype.removeListItem = function(index) { | ||||
| 	// Remove the DOM nodes owned by this item | ||||
| 	this.children[index].removeChildDomNodes(); | ||||
| 	var widget = this.children[index]; | ||||
| 	// Animate the removal if required | ||||
| 	if(this.storyview && this.storyview.remove) { | ||||
| 		this.storyview.remove(widget); | ||||
| 	} else { | ||||
| 		widget.removeChildDomNodes(); | ||||
| 	} | ||||
| 	// Remove the child widget | ||||
| 	this.children.splice(index,1); | ||||
| }; | ||||
|   | ||||
| @@ -78,7 +78,9 @@ exports.startup = function() { | ||||
| 		}); | ||||
| 		// Install the scroller | ||||
| 		$tw.pageScroller = new $tw.utils.PageScroller(); | ||||
| 		$tw.rootWidget.addEventListener("tw-scroll",$tw.pageScroller); | ||||
| 		$tw.rootWidget.addEventListener("tw-scroll",function(event) { | ||||
| 			$tw.pageScroller.handleEvent(event); | ||||
| 		}); | ||||
| 		// Install the save action handler | ||||
| 		$tw.wiki.initSavers(); | ||||
| 		$tw.rootWidget.addEventListener("tw-save-wiki",function(event) { | ||||
|   | ||||
							
								
								
									
										94
									
								
								core/modules/storyviews/classic.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								core/modules/storyviews/classic.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /*\ | ||||
| title: $:/core/modules/storyviews/classic.js | ||||
| type: application/javascript | ||||
| module-type: storyview | ||||
|  | ||||
| Views the story as a linear sequence | ||||
|  | ||||
| \*/ | ||||
| (function(){ | ||||
|  | ||||
| /*jslint node: true, browser: true */ | ||||
| /*global $tw: false */ | ||||
| "use strict"; | ||||
|  | ||||
| var ClassicStoryView = function(listWidget) { | ||||
| 	this.listWidget = listWidget; | ||||
| } | ||||
|  | ||||
| ClassicStoryView.prototype.navigateTo = function(historyInfo) { | ||||
| 	var listElementIndex = this.listWidget.findListItem(0,historyInfo.title); | ||||
| 	if(listElementIndex === undefined) { | ||||
| 		return; | ||||
| 	} | ||||
| 	var listItemWidget = this.listWidget.children[listElementIndex], | ||||
| 		targetElement = listItemWidget.findFirstDomNode(); | ||||
| 	// Scroll the node into view | ||||
| 	this.listWidget.dispatchEvent({type: "tw-scroll", target: targetElement}); | ||||
| }; | ||||
|  | ||||
| ClassicStoryView.prototype.insert = function(widget) { | ||||
| 	var targetElement = widget.findFirstDomNode(), | ||||
| 		duration = $tw.utils.getAnimationDuration(); | ||||
| 	// Get the current height of the tiddler | ||||
| 	var computedStyle = window.getComputedStyle(targetElement), | ||||
| 		currMarginBottom = parseInt(computedStyle.marginBottom,10), | ||||
| 		currMarginTop = parseInt(computedStyle.marginTop,10), | ||||
| 		currHeight = targetElement.offsetHeight + currMarginTop; | ||||
| 	// Reset the margin once the transition is over | ||||
| 	setTimeout(function() { | ||||
| 		$tw.utils.setStyle(targetElement,[ | ||||
| 			{transition: "none"}, | ||||
| 			{marginBottom: ""} | ||||
| 		]); | ||||
| 	},duration); | ||||
| 	// Set up the initial position of the element | ||||
| 	$tw.utils.setStyle(targetElement,[ | ||||
| 		{transition: "none"}, | ||||
| 		{marginBottom: (-currHeight) + "px"}, | ||||
| 		{opacity: "0.0"} | ||||
| 	]); | ||||
| 	$tw.utils.forceLayout(targetElement); | ||||
| 	// Transition to the final position | ||||
| 	$tw.utils.setStyle(targetElement,[ | ||||
| 		{transition: "opacity " + duration + "ms ease-in-out, " + | ||||
| 					"margin-bottom " + duration + "ms ease-in-out"}, | ||||
| 		{marginBottom: currMarginBottom + "px"}, | ||||
| 		{opacity: "1.0"} | ||||
| 	]); | ||||
| }; | ||||
|  | ||||
| ClassicStoryView.prototype.remove = function(widget) { | ||||
| 	var targetElement = widget.findFirstDomNode(), | ||||
| 		duration = $tw.utils.getAnimationDuration(); | ||||
| 	// Get the current height of the tiddler | ||||
| 	var currWidth = targetElement.offsetWidth, | ||||
| 		computedStyle = window.getComputedStyle(targetElement), | ||||
| 		currMarginBottom = parseInt(computedStyle.marginBottom,10), | ||||
| 		currMarginTop = parseInt(computedStyle.marginTop,10), | ||||
| 		currHeight = targetElement.offsetHeight + currMarginTop; | ||||
| 	// Remove the dom nodes of the widget at the end of the transition | ||||
| 	setTimeout(function() { | ||||
| 		widget.removeChildDomNodes(); | ||||
| 	},duration); | ||||
| 	// Animate the closure | ||||
| 	$tw.utils.setStyle(targetElement,[ | ||||
| 		{transition: "none"}, | ||||
| 		{transform: "translateX(0px)"}, | ||||
| 		{marginBottom:  currMarginBottom + "px"}, | ||||
| 		{opacity: "1.0"} | ||||
| 	]); | ||||
| 	$tw.utils.forceLayout(targetElement); | ||||
| 	$tw.utils.setStyle(targetElement,[ | ||||
| 		{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in-out, " + | ||||
| 					"opacity " + duration + "ms ease-in-out, " + | ||||
| 					"margin-bottom " + duration + "ms ease-in-out"}, | ||||
| 		{transform: "translateX(-" + currWidth + "px)"}, | ||||
| 		{marginBottom: (-currHeight) + "px"}, | ||||
| 		{opacity: "0.0"} | ||||
| 	]); | ||||
| }; | ||||
|  | ||||
| exports.classic = ClassicStoryView; | ||||
|  | ||||
| })(); | ||||
| @@ -26,7 +26,7 @@ title: $:/core/ui/PageTemplate | ||||
| <section class="story-river"> | ||||
|  | ||||
| <!-- The main story --> | ||||
| <$list filter="[list[$:/StoryList]]" history="$:/HistoryList" template="$:/core/ui/ViewTemplate" editTemplate="$:/core/ui/EditTemplate" listview={{$:/view}} /> | ||||
| <$list filter="[list[$:/StoryList]]" history="$:/HistoryList" template="$:/core/ui/ViewTemplate" editTemplate="$:/core/ui/EditTemplate" storyview={{$:/view}} /> | ||||
|  | ||||
| <!-- End of story river --> | ||||
| </section> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jeremy Ruston
					Jeremy Ruston