1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-12-25 01:20:30 +00:00

Lots of fixes to storyview mechanism

And a new scroller mechanism
This commit is contained in:
Jeremy Ruston 2012-07-07 17:14:50 +01:00
parent a21d96adc1
commit f412dd19d9
7 changed files with 241 additions and 150 deletions

View File

@ -17,8 +17,6 @@ exports.info = {
params: { params: {
story: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency story: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency
history: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency history: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency
defaultViewTemplate: {byName: true, type: "tiddler"},
defaultEditTemplate: {byName: true, type: "tiddler"},
set: {byName: true, type: "tiddler"} set: {byName: true, type: "tiddler"}
} }
}; };
@ -64,8 +62,7 @@ exports.eventMap["tw-navigate"] = function(event) {
// Update the story tiddler if specified // Update the story tiddler if specified
if(this.hasParameter("story")) { if(this.hasParameter("story")) {
this.getStory(); this.getStory();
var template = this.params.defaultViewTemplate || "$:/templates/ViewTemplate", var t,tiddler,slot;
t,tiddler,slot;
// See if the tiddler is already there // See if the tiddler is already there
for(t=0; t<this.story.tiddlers.length; t++) { for(t=0; t<this.story.tiddlers.length; t++) {
if(this.story.tiddlers[t].title === event.navigateTo) { if(this.story.tiddlers[t].title === event.navigateTo) {
@ -102,13 +99,46 @@ exports.eventMap["tw-navigate"] = function(event) {
this.history.stack.push({ this.history.stack.push({
title: event.navigateTo, title: event.navigateTo,
fromTitle: event.navigateFromTitle, fromTitle: event.navigateFromTitle,
fromPosition: event.navigateFrom.getNodeBounds() fromPosition: event.navigateFrom.getNodeBounds(),
scrollPosition: $tw.utils.getScrollPosition()
}); });
this.saveHistory(); this.saveHistory();
event.stopPropagation(); event.stopPropagation();
return false; return false;
}; };
// Navigate to a specified tiddler
exports.eventMap["tw-NavigateBack"] = function(event) {
// Pop a record record off the top of the history stack
this.getHistory();
if(this.history.stack.length < 2) {
return false; // Bail if there is not enough entries on the history stack
}
var fromHistoryInfo = this.history.stack.pop(),
toHistoryInfo = this.history.stack[this.history.stack.length-1];
this.saveHistory();
// Make sure that the tiddler we're navigating back to is open in the story
if(this.hasParameter("story") && toHistoryInfo) {
this.getStory();
var t,tiddler,slot;
// See if the tiddler is already there
for(t=0; t<this.story.tiddlers.length; t++) {
if(this.story.tiddlers[t].title === toHistoryInfo.title) {
tiddler = t;
}
}
// If not we need to add it
if(tiddler === undefined) {
// Add the tiddler
this.story.tiddlers.splice(slot,0,{title: toHistoryInfo.title});
// Save the story
this.saveStory();
}
}
event.stopPropagation();
return false;
};
// Place a tiddler in edit mode // Place a tiddler in edit mode
exports.eventMap["tw-EditTiddler"] = function(event) { exports.eventMap["tw-EditTiddler"] = function(event) {
if(this.hasParameter("story")) { if(this.hasParameter("story")) {
@ -204,7 +234,7 @@ exports.executeMacro = function() {
this.content[t].execute(this.parents,this.tiddlerTitle); this.content[t].execute(this.parents,this.tiddlerTitle);
} }
return $tw.Tree.Element("div",attributes,this.content,{ return $tw.Tree.Element("div",attributes,this.content,{
events: ["tw-navigate","tw-EditTiddler","tw-SaveTiddler","tw-CloseTiddler"], events: ["tw-navigate","tw-EditTiddler","tw-SaveTiddler","tw-CloseTiddler","tw-NavigateBack"],
eventHandler: this eventHandler: this
}); });
}; };

View File

@ -19,7 +19,11 @@ And the history tiddler is the stack of tiddlers that were navigated to in turn:
{ {
stack: [ stack: [
{title: <string>} {
title: <string>,
fromTitle: <string>,
fromPosition: {bottom: <num>, height: <num>, top: <num>, right: <num>, left: <num>, width: <num>}
}
] ]
} }
@ -132,6 +136,9 @@ exports.removeStoryElement = function(storyElementIndex) {
// Only delete the DOM element if the storyview.remove() returned false // Only delete the DOM element if the storyview.remove() returned false
storyElement.domNode.parentNode.removeChild(storyElement.domNode); storyElement.domNode.parentNode.removeChild(storyElement.domNode);
} }
} else {
// Always delete the story element if we didn't invoke the storyview
storyElement.domNode.parentNode.removeChild(storyElement.domNode);
} }
// Then delete the actual renderer node // Then delete the actual renderer node
this.storyNode.children.splice(storyElementIndex,1); this.storyNode.children.splice(storyElementIndex,1);
@ -169,8 +176,10 @@ exports.executeMacro = function() {
}; };
exports.postRenderInDom = function() { exports.postRenderInDom = function() {
// Reset the record of the previous history stack // Get the history object and use it to set the previous history
this.prevHistory = {stack: []}; this.getHistory();
this.prevHistory = this.history;
this.history = null;
// Instantiate the story view // Instantiate the story view
var storyviewName; var storyviewName;
if(this.hasParameter("storyviewTiddler")) { if(this.hasParameter("storyviewTiddler")) {
@ -278,7 +287,7 @@ exports.processHistoryChange = function() {
// Read the history tiddler // Read the history tiddler
this.getHistory(); this.getHistory();
if(this.storyview) { if(this.storyview) {
var t,index, var t,indexTo,indexFrom,
topCommon = Math.min(this.history.stack.length,this.prevHistory.stack.length); topCommon = Math.min(this.history.stack.length,this.prevHistory.stack.length);
// Find the common heritage of the new history stack and the previous one // Find the common heritage of the new history stack and the previous one
for(t=0; t<topCommon; t++) { for(t=0; t<topCommon; t++) {
@ -289,16 +298,21 @@ exports.processHistoryChange = function() {
} }
// We now navigate backwards through the previous history to get back to the common ancestor // We now navigate backwards through the previous history to get back to the common ancestor
for(t=this.prevHistory.stack.length-1; t>=topCommon; t--) { for(t=this.prevHistory.stack.length-1; t>=topCommon; t--) {
index = this.findStoryElementByTitle(0,this.prevHistory.stack[t].title); indexTo = this.findStoryElementByTitle(0,this.prevHistory.stack[t].fromTitle);
if(index !== undefined && this.storyview.navigateBack) { indexFrom = this.findStoryElementByTitle(0,this.prevHistory.stack[t].title);
this.storyview.navigateBack(this.storyNode.children[index],this.history.stack[t]); // Call the story view if it defines a navigateBack() method
if(indexTo !== undefined && indexFrom !== undefined && this.storyview.navigateBack) {
this.storyview.navigateBack(this.storyNode.children[indexTo],this.storyNode.children[indexFrom],this.prevHistory.stack[t]);
} }
} }
// And now we navigate forwards through the new history to get to the latest tiddler // And now we navigate forwards through the new history to get to the latest tiddler
for(t=topCommon; t<this.history.stack.length; t++) { for(t=topCommon; t<this.history.stack.length; t++) {
index = this.findStoryElementByTitle(0,this.history.stack[t].title); indexTo = this.findStoryElementByTitle(0,this.history.stack[t].title);
if(index !== undefined && this.storyview.navigateForward) { indexFrom = this.findStoryElementByTitle(0,this.history.stack[t].fromTitle);
this.storyview.navigateForward(this.storyNode.children[index],this.history.stack[t]); if(indexTo !== undefined && this.storyview.navigateForward) {
this.storyview.navigateForward(this.storyNode.children[indexTo],
indexFrom !== undefined ? this.storyNode.children[indexFrom] : undefined,
this.history.stack[t]);
} }
} }
} }

View File

@ -31,7 +31,7 @@ ClassicScroller.prototype.remove = function(storyElementNode) {
} }
},false); },false);
// Animate the closure // Animate the closure
var d = ($tw.config.preferences.animationDuration/1000).toFixed(8) + "s"; var d = $tw.config.preferences.animationDuration + "ms";
wrapperElement.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, " + wrapperElement.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, " +
"opacity " + d + " ease-out, " + "opacity " + d + " ease-out, " +
"height " + d + " ease-in-out"; "height " + d + " ease-in-out";
@ -48,12 +48,12 @@ ClassicScroller.prototype.remove = function(storyElementNode) {
return true; return true;
}; };
ClassicScroller.prototype.navigateBack = function(storyElementNode,historyInfo) { ClassicScroller.prototype.navigateBack = function(toStoryElement,fromStoryElement,historyInfo) {
$tw.utils.scrollIntoView(storyElementNode.domNode); $tw.scroller.scrollIntoView(toStoryElement.domNode);
}; };
ClassicScroller.prototype.navigateForward = function(storyElementNode,historyInfo) { ClassicScroller.prototype.navigateForward = function(toStoryElement,fromStoryElement,historyInfo) {
$tw.utils.scrollIntoView(storyElementNode.domNode); $tw.scroller.scrollIntoView(toStoryElement.domNode);
}; };
exports.classic = ClassicScroller; exports.classic = ClassicScroller;

View File

@ -30,13 +30,23 @@ function SidewaysView(story) {
} }
} }
/*
Visualise navigation to a new tiddler
toStoryElementNode: tree node of the tiddler macro we're navigating to
fromStoryElementNode: optionally, tree node of the tiddler we're navigating from
historyInfo: record from the history tiddler corresponding to this navigation
*/
SidewaysView.prototype.navigateForward = function(toStoryElement,fromStoryElement,historyInfo) {
$tw.scroller.scrollIntoView(toStoryElement.domNode);
};
/* /*
Visualise insertion of the specified tiddler macro, optionally specifying a source node for the visualisation Visualise insertion of the specified tiddler macro, optionally specifying a source node for the visualisation
storyElementNode: tree node of the tiddler macro we're navigating to storyElementNode: tree node of the tiddler macro we're navigating to
*/ */
SidewaysView.prototype.insert = function(storyElementNode) { SidewaysView.prototype.insert = function(storyElementNode) {
setStoryElementStyles(storyElementNode.domNode); setStoryElementStyles(storyElementNode.domNode);
$tw.utils.scrollIntoView(storyElementNode.domNode); $tw.scroller.scrollIntoView(storyElementNode.domNode);
}; };
SidewaysView.prototype.remove = function(storyElementNode) { SidewaysView.prototype.remove = function(storyElementNode) {
@ -48,7 +58,7 @@ SidewaysView.prototype.remove = function(storyElementNode) {
targetElement.parentNode.insertBefore(wrapperElement,targetElement); targetElement.parentNode.insertBefore(wrapperElement,targetElement);
wrapperElement.appendChild(targetElement); wrapperElement.appendChild(targetElement);
// Animate the closure // Animate the closure
var d = ($tw.config.preferences.animationDuration/1000).toFixed(8) + "s"; var d = $tw.config.preferences.animationDuration + "ms";
wrapperElement.style.display = "inline-block"; wrapperElement.style.display = "inline-block";
wrapperElement.style[$tw.browser.transformorigin] = "0% 0%"; wrapperElement.style[$tw.browser.transformorigin] = "0% 0%";
wrapperElement.style[$tw.browser.transform] = "translateY(0px)"; wrapperElement.style[$tw.browser.transform] = "translateY(0px)";

View File

@ -3,7 +3,11 @@ title: $:/core/modules/macros/story/views/zoomin.js
type: application/javascript type: application/javascript
module-type: storyview module-type: storyview
A storyview that shows a single tiddler and navigates by zooming into links A storyview that shows a single tiddler and navigates by zooming into links.
To do this, the story wrapper is set to `position:relative` and then each of the story elements to `position:absolute`. This results in all of the tiddlers being stacked on top of one another flush with the top left of the story wrapper.
Navigating between tiddlers is accomplished by switching the story nodes between `display:block` and `display:none`, but the implementation is considerably more complex due to the animation.
\*/ \*/
(function(){ (function(){
@ -16,6 +20,8 @@ function Zoomin(story) {
// Save the story // Save the story
this.story = story; this.story = story;
this.storyNode = this.story.child.domNode; this.storyNode = this.story.child.domNode;
// Set the current tiddler
this.currentTiddler = this.story.child.children[0];
// Make all the tiddlers position absolute, and hide all but the first one // Make all the tiddlers position absolute, and hide all but the first one
this.storyNode.style.position = "relative"; this.storyNode.style.position = "relative";
for(var t=0; t<this.storyNode.children.length; t++) { for(var t=0; t<this.storyNode.children.length; t++) {
@ -24,10 +30,6 @@ function Zoomin(story) {
} }
this.storyNode.children[t].style.position = "absolute"; this.storyNode.children[t].style.position = "absolute";
} }
// Record the current tiddler node
this.currTiddler = this.story.child.children[0];
// Set up the stack of previously viewed tiddlers
this.prevTiddlers = [this.currTiddler.children[0].params.target];
} }
/* /*
@ -55,128 +57,120 @@ function findTitleNode(node) {
} }
/* /*
Visualise removal of the the specified tiddler macro, optionally specifying a source node for the visualisation Visualise navigation to a new tiddler
storyElementNode: tree node of the tiddler macro we're navigating to toStoryElementNode: tree node of the tiddler macro we're navigating to
fromStoryElementNode: optionally, tree node of the tiddler we're navigating from
historyInfo: record from the history tiddler corresponding to this navigation
*/ */
Zoomin.prototype.navigateForward = function(storyElementNode,historyInfo) { Zoomin.prototype.navigateForward = function(toStoryElement,fromStoryElement,historyInfo) {
// Do nothing if the target tiddler is already the current tiddler // Make the new tiddler be position absolute and visible so that we can measure it
if(storyElementNode === this.currTiddler) { toStoryElement.domNode.style.position = "absolute";
return; toStoryElement.domNode.style.display = "block";
} toStoryElement.domNode.style[$tw.browser.transformorigin] = "0 0";
// Make the new tiddler be position absolute and visible toStoryElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(1)";
storyElementNode.domNode.style.position = "absolute"; toStoryElement.domNode.style[$tw.browser.transition] = "none";
storyElementNode.domNode.style.display = "block"; toStoryElement.domNode.style.opacity = "0.0";
storyElementNode.domNode.style[$tw.browser.transformorigin] = "0 0";
storyElementNode.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(1)";
storyElementNode.domNode.style[$tw.browser.transition] = "none";
// Get the position of the source node, or use the centre of the window as the source position // Get the position of the source node, or use the centre of the window as the source position
var sourceBounds = historyInfo.fromPosition || { var sourceBounds = historyInfo.fromPosition || {
left: window.innerWidth/2 - 2, left: window.innerWidth/2 - 2,
top: window.innerHeight/2 - 2, top: window.innerHeight/2 - 2,
width: 4, width: window.innerWidth/8,
height: 4 height: window.innerHeight/8
}; };
// Try to find the title node in the target tiddler // Try to find the title node in the target tiddler
var titleNode = findTitleNode(storyElementNode) || storyElementNode; var titleNode = findTitleNode(toStoryElement) || toStoryElement,
titleBounds = titleNode.getNodeBounds();
// Compute the transform for the target tiddler to make the title lie over the source rectange // Compute the transform for the target tiddler to make the title lie over the source rectange
var targetBounds = storyElementNode.getNodeBounds(), var targetBounds = toStoryElement.getNodeBounds(),
titleBounds = titleNode.getNodeBounds(),
scale = sourceBounds.width / titleBounds.width, scale = sourceBounds.width / titleBounds.width,
x = sourceBounds.left - targetBounds.left - (titleBounds.left - targetBounds.left) * scale, x = sourceBounds.left - targetBounds.left - (titleBounds.left - targetBounds.left) * scale,
y = sourceBounds.top - targetBounds.top - (titleBounds.top - targetBounds.top) * scale; y = sourceBounds.top - targetBounds.top - (titleBounds.top - targetBounds.top) * scale;
// Transform the target tiddler // Transform the target tiddler to its starting position
storyElementNode.domNode.style[$tw.browser.transform] = "translateX(" + x + "px) translateY(" + y + "px) scale(" + scale + ")"; toStoryElement.domNode.style[$tw.browser.transform] = "translateX(" + x + "px) translateY(" + y + "px) scale(" + scale + ")";
// Get the animation duration // Get the animation duration
var d = ($tw.config.preferences.animationDuration/1000).toFixed(8) + "s"; var d = $tw.config.preferences.animationDuration + "ms";
// Apply the ending transitions with a timeout to ensure that the previously applied transformations are applied first // Apply the ending transitions with a timeout to ensure that the previously applied transformations are applied first
var self = this, var self = this,
currTiddler = this.currTiddler; prevCurrentTiddler = this.currentTiddler;
this.currentTiddler = toStoryElement;
$tw.utils.nextTick(function() { $tw.utils.nextTick(function() {
// Transform the target tiddler // Transform the target tiddler to its natural size
var currTiddlerBounds = currTiddler.getNodeBounds(), toStoryElement.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out";
x = (currTiddlerBounds.left - targetBounds.left), toStoryElement.domNode.style.opacity = "1.0";
y = (currTiddlerBounds.top - targetBounds.top); toStoryElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(1)";
storyElementNode.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out"; toStoryElement.domNode.style.zIndex = "500";
storyElementNode.domNode.style.opacity = "1.0"; // Transform the previous tiddler out of the way and then hide it
storyElementNode.domNode.style[$tw.browser.transform] = "translateX(" + x + "px) translateY(" + y + "px) scale(1)"; if(prevCurrentTiddler && prevCurrentTiddler !== toStoryElement) {
storyElementNode.domNode.style.zIndex = "500";
// Transform the current tiddler
var scale = titleBounds.width / sourceBounds.width; var scale = titleBounds.width / sourceBounds.width;
x = titleBounds.left - targetBounds.left - (sourceBounds.left - currTiddlerBounds.left) * scale; x = titleBounds.left - targetBounds.left - (sourceBounds.left - targetBounds.left) * scale;
y = titleBounds.top - targetBounds.top - (sourceBounds.top - currTiddlerBounds.top) * scale; y = titleBounds.top - targetBounds.top - (sourceBounds.top - targetBounds.top) * scale;
currTiddler.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out"; prevCurrentTiddler.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out";
currTiddler.domNode.style.opacity = "0.0"; prevCurrentTiddler.domNode.style.opacity = "0.0";
currTiddler.domNode.style[$tw.browser.transformorigin] = "0 0"; prevCurrentTiddler.domNode.style[$tw.browser.transformorigin] = "0 0";
currTiddler.domNode.style[$tw.browser.transform] = "translateX(" + x + "px) translateY(" + y + "px) scale(" + scale + ")"; prevCurrentTiddler.domNode.style[$tw.browser.transform] = "translateX(" + x + "px) translateY(" + y + "px) scale(" + scale + ")";
currTiddler.domNode.style.zIndex = "0"; prevCurrentTiddler.domNode.style.zIndex = "0";
var eventHandler = function(event) {
// Hide the DOM node when the transition is over
if(self.currentTiddler !== prevCurrentTiddler) {
prevCurrentTiddler.domNode.style.display = "none";
}
prevCurrentTiddler.domNode.removeEventListener($tw.browser.transitionEnd,eventHandler,true);
};
prevCurrentTiddler.domNode.addEventListener($tw.browser.transitionEnd,eventHandler,true);
}
// Scroll the target into view
$tw.scroller.scrollIntoView(toStoryElement.domNode);
}); });
// Record the new current tiddler
this.currTiddler = storyElementNode;
// Save the tiddler in the stack
this.prevTiddlers.push(storyElementNode.children[0].params.target);
}; };
/* /*
Visualise removing a tiddler Visualise navigating back to the previous tiddler
toStoryElement: story element being navigated back to
fromStoryElement: story element being navigated back from
historyInfo: member of the history stack[] array being navigated back through
*/ */
Zoomin.prototype.remove = function(storyElementNode) { Zoomin.prototype.navigateBack = function(toStoryElement,fromStoryElement,historyInfo) {
// Remove the last entry from the navigation stack, which will be to navigate to the current tiddler
this.prevTiddlers.pop();
// Find the top entry in the navigation stack that still exists
var storyElementIndex,storyElement;
while(this.prevTiddlers.length > 0) {
var title = this.prevTiddlers.pop();
storyElementIndex = this.story.findStoryElementByTitle(0,title);
if(storyElementIndex !== undefined) {
break;
}
}
if(storyElementIndex !== undefined) {
storyElement = this.story.storyNode.children[storyElementIndex];
}
// Get the animation duration // Get the animation duration
var d = ($tw.config.preferences.animationDuration/1000).toFixed(8) + "s"; var d = $tw.config.preferences.animationDuration + "ms";
// Set up the tiddler that is being closed // Set up the tiddler that is being closed
storyElementNode.domNode.style.position = "absolute"; if(fromStoryElement) {
storyElementNode.domNode.style.display = "block"; fromStoryElement.domNode.style.position = "absolute";
storyElementNode.domNode.style[$tw.browser.transformorigin] = "50% 50%"; fromStoryElement.domNode.style.display = "block";
storyElementNode.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(1)"; fromStoryElement.domNode.style[$tw.browser.transformorigin] = "50% 50%";
storyElementNode.domNode.style[$tw.browser.transition] = "none"; fromStoryElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(1)";
storyElementNode.domNode.style.zIndex = "0"; fromStoryElement.domNode.style[$tw.browser.transition] = "none";
// Set up the tiddler we're moving back in fromStoryElement.domNode.style.zIndex = "0";
if(storyElement !== undefined) {
storyElement.domNode.style.position = "absolute";
storyElement.domNode.style.display = "block";
storyElement.domNode.style[$tw.browser.transformorigin] = "50% 50%";
storyElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(10)";
storyElement.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out";
storyElement.domNode.style.opacity = "0.0";
storyElement.domNode.style.zIndex = "500";
// Push the tiddler we're moving back to back on the stack
this.prevTiddlers.push(storyElement.children[0].params.target);
this.currTiddler = storyElement;
} else {
this.currTiddler = null;
} }
// Set up the tiddler we're moving back in
toStoryElement.domNode.style.position = "absolute";
toStoryElement.domNode.style.display = "block";
toStoryElement.domNode.style[$tw.browser.transformorigin] = "50% 50%";
toStoryElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(10)";
toStoryElement.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out";
toStoryElement.domNode.style.opacity = "0.0";
toStoryElement.domNode.style.zIndex = "500";
this.currentTiddler = toStoryElement;
// Animate them both // Animate them both
$tw.utils.nextTick(function() { $tw.utils.nextTick(function() {
// First, the tiddler we're closing // First, the tiddler we're closing
storyElementNode.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out"; if(fromStoryElement) {
storyElementNode.domNode.style.opacity = "0.0"; fromStoryElement.domNode.style[$tw.browser.transition] = "-" + $tw.browser.prefix.toLowerCase() + "-transform " + d + " ease-in-out, opacity " + d + " ease-out";
storyElementNode.domNode.style[$tw.browser.transformorigin] = "50% 50%"; fromStoryElement.domNode.style.opacity = "0.0";
storyElementNode.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(0.1)"; fromStoryElement.domNode.style[$tw.browser.transformorigin] = "50% 50%";
storyElementNode.domNode.style.zIndex = "0"; fromStoryElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(0.1)";
storyElementNode.domNode.addEventListener($tw.browser.transitionEnd,function(event) { fromStoryElement.domNode.style.zIndex = "0";
var eventHandler = function(event) {
// Delete the DOM node when the transition is over // Delete the DOM node when the transition is over
if(storyElementNode.domNode.parentNode) { if(fromStoryElement.domNode.parentNode) {
storyElementNode.domNode.parentNode.removeChild(storyElementNode.domNode); fromStoryElement.domNode.parentNode.removeChild(fromStoryElement.domNode);
}
fromStoryElement.domNode.removeEventListener($tw.browser.transitionEnd,eventHandler,true);
};
fromStoryElement.domNode.addEventListener($tw.browser.transitionEnd,eventHandler,true);
} }
},true);
// Now the tiddler we're going back to // Now the tiddler we're going back to
if(storyElement !== undefined) { toStoryElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(1)";
storyElement.domNode.style[$tw.browser.transform] = "translateX(0px) translateY(0px) scale(1)"; toStoryElement.domNode.style.opacity = "1.0";
storyElement.domNode.style.opacity = "1.0";
}
}); });
return true; // Indicate that we'll delete the DOM node return true; // Indicate that we'll delete the DOM node
}; };

59
core/modules/scroller.js Normal file
View File

@ -0,0 +1,59 @@
/*\
title: $:/core/modules/scroller.js
type: application/javascript
module-type: utils
Plugin that creates a $tw.utils.Scroller object prototype that manages scrolling in the browser
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var slowInSlowOut = function(t) {
return (1 - ((Math.cos(t * Math.PI) + 1) / 2));
};
/*
Creates a Scroller object
*/
var Scroller = function() {
};
Scroller.prototype.cancel = function() {
if(this.timerId) {
window.clearInterval(this.timerId);
this.timerId = null;
}
};
/*
Smoothly scroll an element back into view if needed
*/
Scroller.prototype.scrollIntoView = function(element) {
var scrollPosition = $tw.utils.getScrollPosition();
this.cancel();
this.startTime = new Date();
this.startX = scrollPosition.x;
this.startY = scrollPosition.y;
this.endX = element.offsetLeft;
this.endY = element.offsetTop;
if((this.endX < this.startX) || (this.endX > (this.startX + window.innerWidth)) || (this.endY < this.startY) || (this.endY > (this.startY + window.innerHeight))) {
var self = this;
this.timerId = window.setInterval(function() {
var t = ((new Date()) - self.startTime) / $tw.config.preferences.animationDuration;
if(t >= 1) {
self.cancel();
t = 1;
}
t = slowInSlowOut(t);
window.scrollTo(self.startX + (self.endX - self.startX) * t,self.startY + (self.endY - self.startY) * t);
}, 10);
}
};
exports.Scroller = Scroller;
})();

View File

@ -76,34 +76,18 @@ exports.applyStyleSheet = function(id,css) {
}; };
/* /*
Smoothly scroll an element back into view if needed Get the scroll position of the viewport
*/ Returns:
exports.scrollIntoView = function(element) { {
var slowInSlowOut = function(t) { x: horizontal scroll position in pixels,
return (1 - ((Math.cos(t * Math.PI) + 1) / 2)); y: vertical scroll position in pixels
},
animateScroll = function(startX,startY,endX,endY,duration) {
var startTime = new Date(),
timerId = window.setInterval(function() {
var t = ((new Date()) - startTime) / duration;
if(t >= 1) {
window.clearInterval(timerId);
t = 1;
} }
t = slowInSlowOut(t); */
var x = startX + (endX - startX) * t, exports.getScrollPosition = function() {
y = startY + (endY - startY) * t; if("scrollX" in window) {
window.scrollTo(x,y); return {x: window.scrollX, y: window.scrollY};
}, 10); } else {
}, return {x: document.documentElement.scrollLeft, y: document.documentElement.scrollTop};
x = element.offsetLeft,
y = element.offsetTop,
winWidth = window.innerWidth,
winHeight = window.innerHeight,
scrollLeft = window.scrollX || document.documentElement.scrollLeft,
scrollTop = window.scrollY || document.documentElement.scrollTop;
if((x < scrollLeft) || (x > (scrollLeft + winWidth)) || (y < scrollTop) || (y > (scrollTop + winHeight))) {
animateScroll(scrollLeft,scrollTop,x,y,$tw.config.preferences.animationDuration);
} }
}; };