1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-04 17:16:18 +00:00

Lots of tweaks to list view animations

There's a regression in that navigation animations are currently not
working
This commit is contained in:
Jeremy Ruston 2012-11-03 12:34:36 +00:00
parent 921162ccdf
commit 5443c8243a
12 changed files with 140 additions and 220 deletions

View File

@ -36,7 +36,7 @@ exports.handleEvent = function (event) {
navEvent.initEvent("tw-navigate",true,true); navEvent.initEvent("tw-navigate",true,true);
navEvent.navigateTo = this.linkInfo.to; navEvent.navigateTo = this.linkInfo.to;
navEvent.navigateFromNode = this; navEvent.navigateFromNode = this;
navEvent.navigateFromPageRect = $tw.utils.getBoundingPageRect(this.child.domNode); navEvent.navigateFromClientRect = this.child.domNode.getBoundingClientRect();
event.target.dispatchEvent(navEvent); event.target.dispatchEvent(navEvent);
event.preventDefault(); event.preventDefault();
return false; return false;

View File

@ -18,7 +18,6 @@ function CecilyListView(listMacro) {
// Prepare the list frame // Prepare the list frame
var listFrame = this.listMacro.listFrame, var listFrame = this.listMacro.listFrame,
listFrameDomNode = listFrame.domNode; listFrameDomNode = listFrame.domNode;
listFrameDomNode.style.position = "relative";
// Position the initial list entries on the map // Position the initial list entries on the map
this.loadMap(); this.loadMap();
for(var t=0; t<listFrame.children.length; t++) { for(var t=0; t<listFrame.children.length; t++) {

View File

@ -14,90 +14,59 @@ Views the list as a linear sequence
function ClassicListView(listMacro) { function ClassicListView(listMacro) {
this.listMacro = listMacro; this.listMacro = listMacro;
var listFrame = this.listMacro.listFrame,
listFrameDomNode = listFrame.domNode;
$tw.utils.setStyle(listFrameDomNode,[
{perspective: 50000},
]);
} }
ClassicListView.prototype.navigateTo = function(historyInfo) { ClassicListView.prototype.navigateTo = function(historyInfo) {
var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title), var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title),
listElementNode = this.listMacro.listFrame.children[listElementIndex], listElementNode = this.listMacro.listFrame.children[listElementIndex],
targetElement = listElementNode.domNode; targetElement = listElementNode.domNode;
// Remove any transform on the target element
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{transformOrigin: "0% 0%"},
{height: "auto"}
]);
// Get the current height of the element // Get the current height of the element
var currHeight = targetElement.offsetHeight; var currHeight = targetElement.offsetHeight;
// Compute the start and end positions of the target element // Compute the start and end positions of the target element
var srcRect = historyInfo.fromPageRect; var srcRect = historyInfo.fromPageRect;
if(!srcRect) { if(!srcRect) {
var scrollPos = $tw.utils.getScrollPosition(); srcRect = {left: 0, top: 0, width: window.innerWidth, height: window.innerHeight};
srcRect = {
left: scrollPos.x,
top: scrollPos.y,
right: scrollPos.x + window.innerWidth,
bottom: scrollPos.y + window.innerHeight,
width: window.innerWidth,
height: window.innerHeight
};
}; };
var dstRect = $tw.utils.getBoundingPageRect(targetElement); var dstRect = targetElement.getBoundingClientRect();
// Compute the transformations // $tw.sprite.fly(srcRect,dstRect,{
var scale = srcRect.width / dstRect.width; // text: "Flying along at the speed of pixels\n\n\nBoo",
// Reset the height once the transition is over // style: "background:red;"
targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) { // });
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{height: "auto"}
]);
},false);
// Position the target element over the source rectangle
$tw.utils.setStyle(targetElement,[
{transform: "translateX(" + (srcRect.left-dstRect.left) + "px) translateY(" + (srcRect.top-dstRect.top) + "px) scale(" + scale + ")"},
{height: "0px"}
]);
$tw.utils.forceLayout(targetElement);
// Transition the target element to its final resting place
$tw.utils.setStyle(targetElement,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
"opacity " + $tw.config.preferences.animationDurationMs + " ease-out, " +
"height " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transform: "none"},
{height: currHeight + "px"}
]);
// Scroll the target element into view // Scroll the target element into view
$tw.scroller.scrollIntoView(dstRect); // $tw.scroller.scrollIntoView(dstRect);
}; };
ClassicListView.prototype.insert = function(index) { ClassicListView.prototype.insert = function(index) {
var listElementNode = this.listMacro.listFrame.children[index], var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode; targetElement = listElementNode.domNode;
// Get the current height of the tiddler // Get the current height of the tiddler
var currHeight = targetElement.offsetHeight; var currHeight = targetElement.offsetHeight + parseInt(window.getComputedStyle(targetElement).marginTop,10);
// Reset the height once the transition is over // Reset the margin once the transition is over
targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) { targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
$tw.utils.setStyle(targetElement,[ $tw.utils.setStyle(targetElement,[
{transition: "none"}, {transition: "none"},
{height: "auto"} {marginBottom: "auto"}
]); ]);
},false); },false);
// Set up the initial position of the element // Set up the initial position of the element
$tw.utils.setStyle(targetElement,[ $tw.utils.setStyle(targetElement,[
{transition: "none"}, {transition: "none"},
{transformOrigin: "0% 0%"}, {marginBottom: (-currHeight) + "px"},
{transform: "translateX(" + window.innerWidth + "px)"}, {opacity: "0.0"}
{opacity: "0.0"},
{height: "0px"}
]); ]);
$tw.utils.forceLayout(targetElement); $tw.utils.forceLayout(targetElement);
// Transition to the final position // Transition to the final position
$tw.utils.setStyle(targetElement,[ $tw.utils.setStyle(targetElement,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out, " + {transition: "opacity " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
"opacity " + $tw.config.preferences.animationDurationMs + " ease-out, " + "margin-bottom " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
"height " + $tw.config.preferences.animationDurationMs + " ease-in-out"}, {transform: "rotateX(0deg)"},
{transform: "translateX(0px)"}, {marginBottom: "0px"},
{opacity: "1.0"}, {opacity: "1.0"}
{height: currHeight + "px"}
]); ]);
}; };
@ -105,32 +74,29 @@ ClassicListView.prototype.remove = function(index) {
var listElementNode = this.listMacro.listFrame.children[index], var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode; targetElement = listElementNode.domNode;
// Get the current height of the tiddler // Get the current height of the tiddler
var currHeight = targetElement.offsetHeight; var currWidth = targetElement.offsetWidth,
// Put a wrapper around the dom node we're closing currHeight = targetElement.offsetHeight + parseInt(window.getComputedStyle(targetElement).marginTop,10);
var wrapperElement = document.createElement("div");
targetElement.parentNode.insertBefore(wrapperElement,targetElement);
wrapperElement.appendChild(targetElement);
// Attach an event handler for the end of the transition // Attach an event handler for the end of the transition
wrapperElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) { targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
if(wrapperElement.parentNode) { if(targetElement.parentNode) {
wrapperElement.parentNode.removeChild(wrapperElement); targetElement.parentNode.removeChild(targetElement);
} }
},false); },false);
// Animate the closure // Animate the closure
$tw.utils.setStyle(wrapperElement,[ $tw.utils.setStyle(targetElement,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out, " + {transition: "none"},
"opacity " + $tw.config.preferences.animationDurationMs + " ease-out, " +
"height " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transformOrigin: "0% 0%"},
{transform: "translateX(0px)"}, {transform: "translateX(0px)"},
{opacity: "1.0"}, {marginBottom: "0px"},
{height: currHeight + "px"} {opacity: "1.0"}
]); ]);
$tw.utils.forceLayout(wrapperElement); $tw.utils.forceLayout(targetElement);
$tw.utils.setStyle(wrapperElement,[ $tw.utils.setStyle(targetElement,[
{transform: "translateX(-" + window.innerWidth + "px)"}, {transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
{opacity: "0.0"}, "opacity " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
{height: "0px"} "margin-bottom " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transform: "translateX(" + currWidth + "px)"},
{marginBottom: (-currHeight) + "px"},
{opacity: "0.0"}
]); ]);
// Returning true causes the DOM node not to be deleted // Returning true causes the DOM node not to be deleted
return true; return true;

View File

@ -14,54 +14,27 @@ Views the list as a sideways linear sequence
function SidewaysListView(listMacro) { function SidewaysListView(listMacro) {
this.listMacro = listMacro; this.listMacro = listMacro;
// Prepare the list frame
var listFrame = this.listMacro.listFrame,
listFrameDomNode = listFrame.domNode;
for(var t=0; t<listFrame.children.length; t++) {
var title = listFrame.children[t].listElementInfo.title,
domNode = listFrame.children[t].domNode;
$tw.utils.setStyle(domNode,[
{verticalAlign: "top"},
{display: "inline-block"}
]);
}
} }
SidewaysListView.prototype.navigateTo = function(historyInfo) {
var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title),
listElementNode = this.listMacro.listFrame.children[listElementIndex],
targetElement = listElementNode.domNode,
currWidth = targetElement.offsetWidth;
// Compute the start and end positions of the target element
var srcRect = historyInfo.fromPageRect;
if(!srcRect) {
var scrollPos = $tw.utils.getScrollPosition();
srcRect = {
left: scrollPos.x,
top: scrollPos.y,
right: scrollPos.x + window.innerWidth,
bottom: scrollPos.y + window.innerHeight,
width: window.innerWidth,
height: window.innerHeight
};
};
var dstRect = $tw.utils.getBoundingPageRect(targetElement);
// Compute the transformations
var scale = srcRect.width / dstRect.width;
// Position the target element over the source rectangle
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{transform: "translateX(" + (srcRect.left-dstRect.left) + "px) translateY(" + (srcRect.top-dstRect.top) + "px) scale(" + scale + ")"},
{marginRight: (-currWidth) + "px"}
]);
$tw.utils.forceLayout(targetElement);
// Transition the target element to its final resting place
$tw.utils.setStyle(targetElement,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
"opacity " + $tw.config.preferences.animationDurationMs + " ease-out, " +
"margin-right " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transform: "none"},
{marginRight: "0px"}
]);
// Scroll the target element into view
//$tw.scroller.scrollIntoView(dstRect);
};
SidewaysListView.prototype.insert = function(index) { SidewaysListView.prototype.insert = function(index) {
var listElementNode = this.listMacro.listFrame.children[index], var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode, targetElement = listElementNode.domNode,
currWidth = targetElement.offsetWidth; currWidth = targetElement.offsetWidth + parseInt(window.getComputedStyle(targetElement).marginLeft,10);
// Set up the initial position of the element // Set up the initial position of the element
$tw.utils.setStyle(targetElement,[ $tw.utils.setStyle(targetElement,[
{verticalAlign: "top"},
{display: "inline-block"},
{transition: "none"}, {transition: "none"},
{opacity: "0.0"}, {opacity: "0.0"},
{marginRight: (-currWidth) + "px"} {marginRight: (-currWidth) + "px"}
@ -79,7 +52,7 @@ SidewaysListView.prototype.insert = function(index) {
SidewaysListView.prototype.remove = function(index) { SidewaysListView.prototype.remove = function(index) {
var listElementNode = this.listMacro.listFrame.children[index], var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode, targetElement = listElementNode.domNode,
currWidth = targetElement.offsetWidth; currWidth = targetElement.offsetWidth + parseInt(window.getComputedStyle(targetElement).marginLeft,10);
// Attach an event handler for the end of the transition // Attach an event handler for the end of the transition
targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) { targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
if(targetElement.parentNode) { if(targetElement.parentNode) {

View File

@ -75,7 +75,7 @@ exports.eventMap["tw-navigate"] = function(event) {
} }
// Add a new record to the top of the history stack // Add a new record to the top of the history stack
this.history = this.wiki.getTiddlerData(this.historyTitle,[]); this.history = this.wiki.getTiddlerData(this.historyTitle,[]);
this.history.push({title: event.navigateTo, fromPageRect: event.navigateFromPageRect}); this.history.push({title: event.navigateTo, fromPageRect: event.navigateFromClientRect});
this.wiki.setTiddlerData(this.historyTitle,this.history); this.wiki.setTiddlerData(this.historyTitle,this.history);
event.stopPropagation(); event.stopPropagation();
return false; return false;

View File

@ -0,0 +1,62 @@
/*\
title: $:/core/modules/macros/scrollable.js
type: application/javascript
module-type: macro
Creates a scrollable frame around its content
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "scrollable",
params: {
width: {byName: true, type: "text"},
height: {byName: true, type: "text"},
"class": {byName: true, type: "text"}
}
};
exports.executeMacro = function() {
var innerClasses = ["tw-scrollable-inner"],
innerAttributes = {
"class": innerClasses,
style: {
overflow: "visible",
position: "relative"
}
},
outerClasses = ["tw-scrollable","tw-scrollable-outer"],
outerAttributes = {
"class": outerClasses,
style: {
overflow: "scroll",
"white-space": "nowrap"
}
};
if(this.hasParameter("class")) {
outerClasses.push(this.params["class"]);
}
if(this.classes) {
$tw.utils.pushTop(outerClasses,this.classes);
}
if(this.hasParameter("width")) {
outerAttributes.style.width = this.params["width"];
}
if(this.hasParameter("height")) {
outerAttributes.style.height = this.params["height"];
}
var innerFrame = $tw.Tree.Element("div",innerAttributes,this.content),
outerFrame = $tw.Tree.Element("div",outerAttributes,[innerFrame]);
outerFrame.execute(this.parents,this.tiddlerTitle);
return outerFrame;
};
exports.postRenderInDom = function() {
};
})();

View File

@ -30,8 +30,7 @@ Scroller.prototype.cancel = function() {
}; };
/* /*
Smoothly scroll an element back into view if needed Smoothly scroll an element into view if needed
element: element or clientrect object
*/ */
Scroller.prototype.scrollIntoView = function(element) { Scroller.prototype.scrollIntoView = function(element) {
var elementBounds = element instanceof HTMLElement ? $tw.utils.getBoundingPageRect(element) : element, var elementBounds = element instanceof HTMLElement ? $tw.utils.getBoundingPageRect(element) : element,

View File

@ -6037,65 +6037,25 @@ a.tw-tiddlylink-missing {
font-style: inherit; font-style: inherit;
} }
/* .tw-sideways-item {
Cecily views width: 300px;
*/ }
.mediumCecilyView { .tw-list-element {
width: 100%; white-space: normal;
height: 400px; }
padding: 10px 10px 10px 10px;
overflow: scroll; .tw-scrollable-outer {
white-space: nowrap;
background: #ccc; background: #ccc;
-webkit-box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15); -webkit-box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15);
-moz-box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15); -moz-box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15);
box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15); box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15);
-webkit-overflow-scrolling: touch;
} }
.mediumCecilyView .tw-list-element { .tw-scrollable .tw-tiddler-frame {
overflow: auto;
white-space: normal;
}
.mediumCecilyView .tw-cecily-tiddler-frame {
width: 400px;
padding: 30px 30px 30px 30px;
background-color: #fff;
-webkit-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.4);
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.4);
}
/*
Sideways views
*/
.mediumSidewaysView {
width: 100%;
height: 400px;
padding: 10px 10px 10px 10px;
overflow: scroll;
white-space: nowrap;
background: #ccc;
-webkit-box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15);
-moz-box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15);
box-shadow: inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15);
-webkit-overflow-scrolling: touch;
}
.mediumSidewaysView .tw-list-element {
overflow: auto;
white-space: normal;
}
.mediumSidewaysView .tw-sideways-tiddler-frame {
display: inline-block;
width: 400px; width: 400px;
padding: 30px 30px 30px 30px; padding: 30px 30px 30px 30px;
margin: 10px 10px 10px 10px; margin: 10px 10px 10px 10px;
vertical-align: top;
background-color: #fff; background-color: #fff;
-webkit-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.4); -webkit-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.4); -moz-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.4);

View File

@ -1,7 +1,6 @@
title: $:/templates/ViewTemplate title: $:/templates/ViewTemplate
modifier: JeremyRuston modifier: JeremyRuston
<div class="tw-tiddler-frame">
<div class="title"> <div class="title">
<span><<view title>></span> <span> <<reveal state:[[$:/EditMode]] type:match text:yes>< <<button EditTiddler class:"btn-invisible"><[img[$:/core/images/edit-button.svg]]>> >> </span> <span><<view title>></span> <span> <<reveal state:[[$:/EditMode]] type:match text:yes>< <<button EditTiddler class:"btn-invisible"><[img[$:/core/images/edit-button.svg]]>> >> </span>
<<button close class:"btn-invisible pull-right"><[img[$:/core/images/close-button.svg]]>> <<button close class:"btn-invisible pull-right"><[img[$:/core/images/close-button.svg]]>>
@ -13,4 +12,3 @@ modifier: JeremyRuston
<div class="body"> <div class="body">
<<view text wikified>> <<view text wikified>>
</div> </div>
</div>

View File

@ -142,56 +142,19 @@ a.tw-tiddlylink-missing {
font-style: inherit; font-style: inherit;
} }
/* .tw-list-element {
Cecily views white-space: normal;
*/ }
.mediumCecilyView { .tw-scrollable-outer {
overflow: scroll;
-webkit-overflow-scrolling: touch;
white-space: nowrap;
.box-shadow(inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15)); .box-shadow(inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15));
background: #ccc; background: #ccc;
padding: 10px 10px 10px 10px;
width: 100%;
height: 400px;
} }
.mediumCecilyView .tw-list-element { .tw-scrollable-inner {
white-space: normal;
overflow: auto;
} }
.mediumCecilyView .tw-cecily-tiddler-frame { .tw-scrollable .tw-tiddler-frame {
padding: 30px 30px 30px 30px;
.box-shadow(1px 1px 6px rgba(0,0,0,0.4));
background-color: #fff;
width: 400px;
}
/*
Sideways views
*/
.mediumSidewaysView {
overflow: scroll;
-webkit-overflow-scrolling: touch;
white-space: nowrap;
.box-shadow(inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15));
background: #ccc;
padding: 10px 10px 10px 10px;
width: 100%;
height: 400px;
}
.mediumSidewaysView .tw-list-element {
white-space: normal;
overflow: auto;
}
.mediumSidewaysView .tw-sideways-tiddler-frame {
vertical-align: top;
display: inline-block;
margin: 10px 10px 10px 10px; margin: 10px 10px 10px 10px;
padding: 30px 30px 30px 30px; padding: 30px 30px 30px 30px;
.box-shadow(1px 1px 6px rgba(0,0,0,0.4)); .box-shadow(1px 1px 6px rgba(0,0,0,0.4));

View File

@ -2,6 +2,6 @@ title: CecilyView
"Cecily" provides a customisable ZoomableUserInterface to your tiddlers. "Cecily" provides a customisable ZoomableUserInterface to your tiddlers.
{{mediumCecilyView{ <<scrollable width:"100%" height:"400px"><
<<list filter:"[list[$:/StoryList]]" history:"$:/HistoryList" template:"CecilyTemplate" listview:cecily itemClass:"tw-cecily-tiddler-frame">> <<list filter:"[list[$:/StoryList]]" history:"$:/HistoryList" template:"CecilyTemplate" listview:cecily itemClass:"tw-tiddler-frame">>
}}} >>

View File

@ -2,6 +2,6 @@ title: SidewaysView
This view shows your tiddlers stacked horizontally. This view shows your tiddlers stacked horizontally.
{{mediumSidewaysView{ <<scrollable width:"100%" height:"400px"><
<<list filter:"[list[$:/StoryList]]" history:"$:/HistoryList" template:"CecilyTemplate" listview:sideways itemClass:"tw-sideways-tiddler-frame">> <<list filter:"[list[$:/StoryList]]" history:"$:/HistoryList" template:"CecilyTemplate" listview:sideways itemClass:"tw-tiddler-frame">>
}}} >>