From 3d747499cb41cca48c8d28e4ba1a60d74d992131 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Sat, 3 Nov 2012 16:14:00 +0000 Subject: [PATCH] More enhancements to listview animations Now we've got navigation scrolling back --- core/modules/macros/list/listviews/classic.js | 16 +------- .../modules/macros/list/listviews/sideways.js | 8 ++++ core/modules/macros/scrollable.js | 39 +++++++++++++++++++ core/modules/utils/dom/scroller.js | 30 +++++++++++--- core/styles/tiddlywiki.css | 6 +-- core/templates/PageTemplate.tid | 2 + cssbuild/tiddlywiki.less | 5 ++- tw5.com/tiddlers/samples/CecilyView.tid | 2 +- tw5.com/tiddlers/samples/SidewaysView.tid | 2 +- 9 files changed, 82 insertions(+), 28 deletions(-) diff --git a/core/modules/macros/list/listviews/classic.js b/core/modules/macros/list/listviews/classic.js index 4058e3c23..b28d6e4cf 100644 --- a/core/modules/macros/list/listviews/classic.js +++ b/core/modules/macros/list/listviews/classic.js @@ -25,20 +25,8 @@ ClassicListView.prototype.navigateTo = function(historyInfo) { var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title), listElementNode = this.listMacro.listFrame.children[listElementIndex], targetElement = listElementNode.domNode; - // Get the current height of the element - var currHeight = targetElement.offsetHeight; - // Compute the start and end positions of the target element - var srcRect = historyInfo.fromPageRect; - if(!srcRect) { - srcRect = {left: 0, top: 0, width: window.innerWidth, height: window.innerHeight}; - }; - var dstRect = targetElement.getBoundingClientRect(); - // $tw.sprite.fly(srcRect,dstRect,{ - // text: "Flying along at the speed of pixels\n\n\nBoo", - // style: "background:red;" - // }); - // Scroll the target element into view -// $tw.scroller.scrollIntoView(dstRect); + // Scroll the node into view + $tw.scroller.scrollIntoView(targetElement); }; ClassicListView.prototype.insert = function(index) { diff --git a/core/modules/macros/list/listviews/sideways.js b/core/modules/macros/list/listviews/sideways.js index 9e0e439fc..c854b3930 100644 --- a/core/modules/macros/list/listviews/sideways.js +++ b/core/modules/macros/list/listviews/sideways.js @@ -27,6 +27,14 @@ function SidewaysListView(listMacro) { } } +SidewaysListView.prototype.navigateTo = function(historyInfo) { + var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title), + listElementNode = this.listMacro.listFrame.children[listElementIndex], + targetElement = listElementNode.domNode; + // Scroll the node into view + $tw.scroller.scrollIntoView(targetElement); +}; + SidewaysListView.prototype.insert = function(index) { var listElementNode = this.listMacro.listFrame.children[index], targetElement = listElementNode.domNode, diff --git a/core/modules/macros/scrollable.js b/core/modules/macros/scrollable.js index 172d744dd..7dffc8f19 100644 --- a/core/modules/macros/scrollable.js +++ b/core/modules/macros/scrollable.js @@ -35,6 +35,7 @@ exports.executeMacro = function() { "class": outerClasses, style: { overflow: "scroll", + webkitOverflowScrolling: "touch", "white-space": "nowrap" } }; @@ -57,6 +58,44 @@ exports.executeMacro = function() { }; exports.postRenderInDom = function() { + // Attach a scrollTo() method to the outer wrapper + var self = this; + this.child.children[0].domNode.scrollTo = function(bounds) { + self.scrollTo.call(self,bounds); + }; +}; + +var slowInSlowOut = function(t) { + return (1 - ((Math.cos(t * Math.PI) + 1) / 2)); +}; + +exports.scrollTo = function(bounds) { + this.cancelScroll(); + this.startTime = new Date(); + this.startX = this.child.domNode.scrollLeft; + this.startY = this.child.domNode.scrollTop; + this.endX = bounds.left; + this.endY = bounds.top; + if((this.endX < this.startX) || (this.endX > (this.startX + this.child.domNode.offsetWidth)) || (this.endY < this.startY) || (this.endY > (this.startY + this.child.domNode.offsetHeight))) { + var self = this; + this.scrollTimerId = window.setInterval(function() { + var t = ((new Date()) - self.startTime) / $tw.config.preferences.animationDuration; + if(t >= 1) { + self.cancelScroll(); + t = 1; + } + t = slowInSlowOut(t); + self.child.domNode.scrollLeft = self.startX + (self.endX - self.startX) * t + self.child.domNode.scrollTop = self.startY + (self.endY - self.startY) * t; + }, 10); + } +}; + +exports.cancelScroll = function() { + if(this.scrollTimerId) { + window.clearInterval(this.scrollTimerId); + this.scrollTimerId = null; + } }; })(); diff --git a/core/modules/utils/dom/scroller.js b/core/modules/utils/dom/scroller.js index 487f54044..03488a3e4 100644 --- a/core/modules/utils/dom/scroller.js +++ b/core/modules/utils/dom/scroller.js @@ -30,17 +30,35 @@ Scroller.prototype.cancel = function() { }; /* -Smoothly scroll an element into view if needed +Smoothly scroll an tree node into view if needed */ -Scroller.prototype.scrollIntoView = function(element) { - var elementBounds = element instanceof HTMLElement ? $tw.utils.getBoundingPageRect(element) : element, - scrollPosition = $tw.utils.getScrollPosition(); +Scroller.prototype.scrollIntoView = function(domNode) { + // Get the offset bounds of the element + var bounds = { + left: domNode.offsetLeft, + top: domNode.offsetTop, + width: domNode.offsetWidth, + height: domNode.offsetHeight + }; + // Walk up the tree adjusting the offset bounds by each offsetParent + while(domNode.offsetParent) { + domNode = domNode.offsetParent; + // If the node is scrollable, tell it to scroll + if(domNode.scrollTo) { + domNode.scrollTo(bounds); + return; + } + bounds.left += domNode.offsetLeft; + bounds.top += domNode.offsetTop; + } + // If we got to the top of the tree then we need to scroll the body + var scrollPosition = $tw.utils.getScrollPosition(); this.cancel(); this.startTime = new Date(); this.startX = scrollPosition.x; this.startY = scrollPosition.y; - this.endX = elementBounds.left; - this.endY = elementBounds.top; + this.endX = bounds.left; + this.endY = bounds.top; 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() { diff --git a/core/styles/tiddlywiki.css b/core/styles/tiddlywiki.css index 3a135d947..a1dd69d21 100644 --- a/core/styles/tiddlywiki.css +++ b/core/styles/tiddlywiki.css @@ -6037,15 +6037,11 @@ a.tw-tiddlylink-missing { font-style: inherit; } -.tw-sideways-item { - width: 300px; -} - .tw-list-element { white-space: normal; } -.tw-scrollable-outer { +.tw-well { 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); diff --git a/core/templates/PageTemplate.tid b/core/templates/PageTemplate.tid index e354c03e7..e89514eec 100644 --- a/core/templates/PageTemplate.tid +++ b/core/templates/PageTemplate.tid @@ -97,7 +97,9 @@ title: $:/templates/PageTemplate
+<< <> +>>
diff --git a/cssbuild/tiddlywiki.less b/cssbuild/tiddlywiki.less index f49b193de..f004f30af 100644 --- a/cssbuild/tiddlywiki.less +++ b/cssbuild/tiddlywiki.less @@ -146,11 +146,14 @@ a.tw-tiddlylink-missing { white-space: normal; } -.tw-scrollable-outer { +.tw-well { .box-shadow(inset 1px 1px 4px 1px rgba(0, 0, 0, 0.15)); background: #ccc; } +.tw-scrollable-outer { +} + .tw-scrollable-inner { } diff --git a/tw5.com/tiddlers/samples/CecilyView.tid b/tw5.com/tiddlers/samples/CecilyView.tid index e7e1588f7..c5418f4bb 100644 --- a/tw5.com/tiddlers/samples/CecilyView.tid +++ b/tw5.com/tiddlers/samples/CecilyView.tid @@ -2,6 +2,6 @@ title: CecilyView "Cecily" provides a customisable ZoomableUserInterface to your tiddlers. -<< +<< <> >> diff --git a/tw5.com/tiddlers/samples/SidewaysView.tid b/tw5.com/tiddlers/samples/SidewaysView.tid index 122d6f832..aaa0a9fbc 100644 --- a/tw5.com/tiddlers/samples/SidewaysView.tid +++ b/tw5.com/tiddlers/samples/SidewaysView.tid @@ -2,6 +2,6 @@ title: SidewaysView This view shows your tiddlers stacked horizontally. -<< +<< <> >>