mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-24 00:50:28 +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) {
|
||||
// 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>
|
||||
|
Loading…
Reference in New Issue
Block a user