1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-23 10:07:19 +00:00

Dynaview: Simplify visibility tracking logic

This commit is contained in:
Jermolene 2019-03-21 12:56:26 +00:00
parent 7709192cc8
commit 9f0d726f7d
5 changed files with 53 additions and 37 deletions

View File

@ -18,11 +18,14 @@ caption: {{$:/language/SideBar/Open/Caption}}
<$button message="tm-close-tiddler" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class="tc-btn-invisible tc-btn-mini">&times;</$button> <$link to={{!!title}}><$view field="title"/></$link>
<$set name="state" value={{{ [[$:/state/viewtemplate/visibility/]addsuffix<currentTiddler>] }}}>
<$reveal type="match" stateTitle=<<state>> text="true">
<span style="display: inline-block; background: red; color: white; padding: 2px; border-radius: 2px;font-size: 0.5em;line-height: 1;text-shadow: none;font-weight: bold;vertical-align: middle;">LOADED</span>
<$reveal type="match" stateTitle=<<state>> text="0">
<span style="display: inline-block; background: red; color: white; padding: 2px; border-radius: 2px;font-size: 0.5em;line-height: 1;text-shadow: none;font-weight: bold;vertical-align: middle;">OUT OF VIEW</span>
</$reveal>
<$reveal type="match" stateTitle=<<state>> text="false">
<span style="display: inline-block; background: green; color: white; padding: 2px; border-radius: 2px;font-size: 0.5em;line-height: 1;text-shadow: none;font-weight: bold;vertical-align: middle;">UNLOADED</span>
<$reveal type="match" stateTitle=<<state>> text="1">
<span style="display: inline-block; background: green; color: white; padding: 2px; border-radius: 2px;font-size: 0.5em;line-height: 1;text-shadow: none;font-weight: bold;vertical-align: middle;">NEAR</span>
</$reveal>
<$reveal type="match" stateTitle=<<state>> text="2">
<span style="display: inline-block; background: purple; color: white; padding: 2px; border-radius: 2px;font-size: 0.5em;line-height: 1;text-shadow: none;font-weight: bold;vertical-align: middle;">VISIBLE</span>
</$reveal>
</$set>
</div>

View File

@ -8,9 +8,9 @@ caption: Contents
<$vars item=<<currentTiddler>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}} excluded="""[enlist<__exclude__>] -[<__tag__>]""">
<li>
<$link to={{{ [enlist{!!tiddler-list}] }}}>
<$list filter="[enlist{!!tiddler-list}addprefix[$:/state/viewtemplate/visibility/]text[true]limit[1]]" variable="listItem" emptyMessage="""<div style="display:inline-block;width:4px;height:1em;background-color:transparent;"></div>""">
<div style="display:inline-block;width:4px;height:1em;background-color:red;"></div>
</$list>
<$list filter="[enlist{!!tiddler-list}addprefix[$:/state/viewtemplate/visibility/]text[2]limit[1]]" variable="listItem" emptyMessage="""<div style="display:inline-block;width:4px;height:1em;background-color:transparent;"></div>""">
<div style="display:inline-block;width:4px;height:1em;background-color:red;"></div>
</$list>
<$view field='caption'>
<$view field='title'/>
</$view>

View File

@ -12,14 +12,14 @@ $:/state/folded/$(currentTiddler)$
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class=<<frame-classes>>>
<$set name="state" value={{{ [[$:/state/viewtemplate/visibility/]addsuffix<currentTiddler>] }}}>
<$reveal stateTitle=<<state>> type="nomatch" text="" default="" tag="div">
<div class="tc-dynaview-set-tiddler-when-visible tc-dynaview-expand-viewport" data-dynaview-set-tiddler=<<state>> data-dynaview-set-value="true" data-dynaview-unset-value="false">
<div class="tc-dynaview-track-tiddler-when-visible" data-dynaview-track-tiddler=<<state>>>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>>/>
</$list>
</div>
</$reveal>
<$reveal stateTitle=<<state>> type="match" text="" default="" tag="div">
<div class="tc-dynaview-set-tiddler-when-visible tc-dynaview-expand-viewport" style="min-height: 5em;" data-dynaview-set-tiddler=<<state>> data-dynaview-set-value="true" data-dynaview-unset-value="false">
<div class="tc-dynaview-track-tiddler-when-visible" style="min-height: 5em;" data-dynaview-track-tiddler=<<state>>>
</div>
</$reveal>
</$set>

View File

@ -25,17 +25,24 @@ Optionally, ~DynaView can store the current scroll position in local storage and
Note that it is not recommended to use this setting at the same time as the "UpdateAddressBar" option.
!! Set tiddler field when visible
!! Visibility tracking
The background task detects when elements with the class `tc-dynaview-set-tiddler-when-visible` scroll into view. The first time that they do, the background task assigns the value in the attribute `data-dynaview-set-value` to the tiddler whose title is in the attribute `data-dynaview-set-tiddler`.
The background task detects when elements with the class `tc-dynaview-track-tiddler-when-visible` scroll in and out of view. It tracks four different states:
This assignment can be tied to a reveal widget to cause content to be displayed when it becomes visible.
* ''Blank/missing'' -- The element has not yet been scrolled into view
* ''0'' -- The element has been scrolled into view, but subsequently scrolled out of view
* ''1'' -- The element is near the viewport
* ''2'' -- The element is partially or wholly within the viewport
If the class `tc-dynaview-expand-viewport` is set then the viewport is expanded so that the processing occurs when elements move near the viewport.
The processing applied to each element is as follows:
!!! Unset tiddler field when set visible before but then scrolled out of view
* If the element is partially or wholly within the viewport then set the state to "2"
* If the element is near the viewport then set the state to "1"
* If the element is fully outside the viewport then only set the state to "0" if it is currently unset (ie blank/missing)
In addition to the processing described above, if the element also has the attribute `data-dynaview-unset-value` then its value will be assigned to the associated tiddler if the element is out of view and the current value of the tiddler corresponds to the value specified in the `data-dynaview-set-value` attribute.
Attributes on the tracked element specify the following parameters:
* ''data-dynaview-track-tiddler'' -- specifies the tiddler in which the element tracking state will be stored
!! Update address bar when scrolling

View File

@ -18,6 +18,10 @@ exports.platforms = ["browser"];
exports.before = ["story"];
exports.synchronous = true;
var STATE_OUT_OF_VIEW = "0",
STATE_NEAR_VIEW = "1",
STATE_IN_VIEW = "2";
var isWaitingForAnimationFrame = 0, // Bitmask:
ANIM_FRAME_CAUSED_BY_LOAD = 1, // Animation frame was requested because of page load
ANIM_FRAME_CAUSED_BY_SCROLL = 2, // Animation frame was requested because of page scroll
@ -106,7 +110,7 @@ function setZoomClasses() {
}
function checkVisibility() {
var elements = document.querySelectorAll(".tc-dynaview-set-tiddler-when-visible");
var elements = document.querySelectorAll(".tc-dynaview-track-tiddler-when-visible");
$tw.utils.each(elements,function(element) {
// Calculate whether the element is visible
var elementRect = element.getBoundingClientRect(),
@ -118,28 +122,30 @@ function checkVisibility() {
top: 0,
bottom: viewportHeight
},
title = element.getAttribute("data-dynaview-set-tiddler"),
setValue = element.getAttribute("data-dynaview-set-value") || "",
unsetValue = element.getAttribute("data-dynaview-unset-value") || "";
if(element.classList.contains("tc-dynaview-expand-viewport")) {
viewportRect.left -= viewportWidth;
viewportRect.right += viewportWidth;
viewportRect.top -= viewportHeight;
viewportRect.bottom += viewportHeight;
}
if(elementRect.left > viewportRect.right ||
elementRect.right < viewportRect.left ||
elementRect.top > viewportRect.bottom ||
elementRect.bottom < viewportRect.top) {
// Element is not visible
// Set the unset tiddler if required
if(title && unsetValue && $tw.wiki.getTiddlerText(title) === setValue) {
$tw.wiki.addTiddler(new $tw.Tiddler({title: title, text: unsetValue}));
title = element.getAttribute("data-dynaview-track-tiddler");
if(title) {
var currValue = $tw.wiki.getTiddlerText(title),
newValue = currValue;
// Within viewport
if(!(elementRect.left > viewportRect.right ||
elementRect.right < viewportRect.left ||
elementRect.top > viewportRect.bottom ||
elementRect.bottom < viewportRect.top)) {
newValue = STATE_IN_VIEW;
// Near viewport
} else if(!(elementRect.left > (viewportRect.right + viewportWidth) ||
elementRect.right < (viewportRect.left - viewportWidth) ||
elementRect.top > (viewportRect.bottom + viewportHeight) ||
elementRect.bottom < (viewportRect.top - viewportHeight))) {
newValue = STATE_NEAR_VIEW;
} else {
// Outside viewport
if(currValue !== undefined) {
newValue = STATE_OUT_OF_VIEW;
}
}
} else {
// Element is visible
if(title && $tw.wiki.getTiddlerText(title) !== setValue) {
$tw.wiki.addTiddler(new $tw.Tiddler({title: title, text: setValue}));
if(newValue !== currValue) {
$tw.wiki.addTiddler(new $tw.Tiddler({title: title, text: newValue}));
}
}
});