mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-07-17 17:32:51 +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:
parent
63243c5855
commit
7c250fd7fe
@ -19,6 +19,12 @@ The list widget creates list element sub-widgets that reach back into the list w
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
var ListWidget = function(parseTreeNode,options) {
|
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);
|
this.initialise(parseTreeNode,options);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,6 +51,8 @@ ListWidget.prototype.execute = function() {
|
|||||||
this.template = this.getAttribute("template");
|
this.template = this.getAttribute("template");
|
||||||
this.editTemplate = this.getAttribute("editTemplate");
|
this.editTemplate = this.getAttribute("editTemplate");
|
||||||
this.variableName = this.getAttribute("variable","currentTiddler");
|
this.variableName = this.getAttribute("variable","currentTiddler");
|
||||||
|
this.storyViewName = this.getAttribute("storyview");
|
||||||
|
this.historyTitle = this.getAttribute("history");
|
||||||
// Compose the list elements
|
// Compose the list elements
|
||||||
this.list = this.getTiddlerList();
|
this.list = this.getTiddlerList();
|
||||||
var members = [],
|
var members = [],
|
||||||
@ -59,6 +67,11 @@ ListWidget.prototype.execute = function() {
|
|||||||
}
|
}
|
||||||
// Construct the child widgets
|
// Construct the child widgets
|
||||||
this.makeChildWidgets(members);
|
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() {
|
ListWidget.prototype.getTiddlerList = function() {
|
||||||
@ -111,13 +124,40 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
ListWidget.prototype.refresh = function(changedTiddlers) {
|
ListWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
// Completely refresh if any of our attributes have changed
|
// 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();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Handle any changes to the list
|
// 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -192,20 +232,30 @@ ListWidget.prototype.findListItem = function(startIndex,title) {
|
|||||||
Insert a new list item at the specified index
|
Insert a new list item at the specified index
|
||||||
*/
|
*/
|
||||||
ListWidget.prototype.insertListItem = function(index,title) {
|
ListWidget.prototype.insertListItem = function(index,title) {
|
||||||
var newItem = this.makeChildWidget(this.makeItemTemplate(title));
|
// Create, insert and render the new child widgets
|
||||||
newItem.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work
|
var widget = this.makeChildWidget(this.makeItemTemplate(title));
|
||||||
this.children.splice(index,0,newItem);
|
widget.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work
|
||||||
var nextSibling = newItem.findNextSiblingDomNode();
|
this.children.splice(index,0,widget);
|
||||||
newItem.render(this.parentDomNode,nextSibling);
|
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;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Remvoe the specified list item
|
Remove the specified list item
|
||||||
*/
|
*/
|
||||||
ListWidget.prototype.removeListItem = function(index) {
|
ListWidget.prototype.removeListItem = function(index) {
|
||||||
// Remove the DOM nodes owned by this item
|
var widget = this.children[index];
|
||||||
this.children[index].removeChildDomNodes();
|
// Animate the removal if required
|
||||||
|
if(this.storyview && this.storyview.remove) {
|
||||||
|
this.storyview.remove(widget);
|
||||||
|
} else {
|
||||||
|
widget.removeChildDomNodes();
|
||||||
|
}
|
||||||
// Remove the child widget
|
// Remove the child widget
|
||||||
this.children.splice(index,1);
|
this.children.splice(index,1);
|
||||||
};
|
};
|
||||||
|
@ -78,7 +78,9 @@ exports.startup = function() {
|
|||||||
});
|
});
|
||||||
// Install the scroller
|
// Install the scroller
|
||||||
$tw.pageScroller = new $tw.utils.PageScroller();
|
$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
|
// Install the save action handler
|
||||||
$tw.wiki.initSavers();
|
$tw.wiki.initSavers();
|
||||||
$tw.rootWidget.addEventListener("tw-save-wiki",function(event) {
|
$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">
|
<section class="story-river">
|
||||||
|
|
||||||
<!-- The main story -->
|
<!-- 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 -->
|
<!-- End of story river -->
|
||||||
</section>
|
</section>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user