1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-10-03 01:10:45 +00:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bram Chen 2014-03-27 00:53:15 +08:00
commit c0f78df48d
36 changed files with 625 additions and 69 deletions

View File

@ -0,0 +1,4 @@
title: $:/core/images/home-button
tags: $:/tags/Image
<svg class="tw-image-home-button tw-image-button" viewBox="81 513 64 54" width="22pt" height="22pt"><g><path d="M 97.04536 522.62083 L 81.364685 531.49067 L 87.85863 531.49067 L 87.85863 566.9699 L 107.49902 566.9699 L 107.49902 552.99265 L 117.95268 552.99265 L 117.95268 566.9699 L 137.59307 566.9699 L 137.59307 531.49067 L 144.086885 531.49067 L 112.72591 513.751 L 107.49902 516.70758 L 107.49902 513.751 L 97.04536 513.751 Z M 94.669443 534.17844 L 103.222493 534.17844 L 103.222493 545.19854 L 94.669443 545.19854 Z M 108.449266 534.17844 L 117.002435 534.17844 L 117.002435 545.19854 L 108.449266 545.19854 Z M 122.387575 534.17844 L 130.9405 534.17844 L 130.9405 545.19854 L 122.387575 545.19854 Z"/></g></svg>

View File

@ -0,0 +1,4 @@
title: $:/core/images/menu-button
tags: $:/tags/Image
<svg class="tw-image-menu-button tw-image-button" viewBox="216 585 63 45" width="22pt" height="22pt"><g><path d="M 274.5 585 L 229.5 585 C 227.01472 585 225 587.01472 225 589.5 L 225 589.5 C 225 591.98528 227.01472 594 229.5 594 L 274.5 594 C 276.98528 594 279 591.98528 279 589.5 L 279 589.5 C 279 587.01472 276.98528 585 274.5 585 Z"/><path d="M 274.5 603 L 229.5 603 C 227.01472 603 225 605.01472 225 607.5 L 225 607.5 C 225 609.98528 227.01472 612 229.5 612 L 274.5 612 C 276.98528 612 279 609.98528 279 607.5 L 279 607.5 C 279 605.01472 276.98528 603 274.5 603 Z"/><path d="M 274.5 621 L 229.5 621 C 227.01472 621 225 623.01472 225 625.5 L 225 625.5 C 225 627.9853 227.01472 630 229.5 630 L 274.5 630 C 276.98528 630 279 627.9853 279 625.5 L 279 625.5 C 279 623.01472 276.98528 621 274.5 621 Z"/></g></svg>

View File

@ -5,6 +5,7 @@ ClassicWarning/Upgrade/Caption: upgrade
CloseAll/Button: close all
ConfirmDeleteTiddler: Do you wish to delete the tiddler "<$text text=<<title>>/>"?
ConfirmOverwriteTiddler: Do you wish to overwrite the tiddler "<$text text=<<title>>/>"?
InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters and the characters underscore (`_`), hyphen (`-`) and period (`.`)
MissingTiddler/Hint: Missing tiddler "<$text text=<<currentTiddler>>/>" - click {{$:/core/images/edit-button}} to create
RecentChanges/DateFormat: DDth MMM YYYY
RelativeDate/Future/Days: <<period>> days from now

View File

@ -25,7 +25,7 @@ var ZoominListView = function(listWidget) {
}
domNode.style.position = "absolute";
});
}
};
ZoominListView.prototype.navigateTo = function(historyInfo) {
var duration = $tw.utils.getAnimationDuration(),

View File

@ -55,25 +55,20 @@ Handle a scroll event hitting the page document
*/
PageScroller.prototype.scrollIntoView = function(element) {
var duration = $tw.utils.getAnimationDuration();
// Get the offset bounds of the element
var bounds = {
left: element.offsetLeft,
top: element.offsetTop,
width: element.offsetWidth,
height: element.offsetHeight
};
// Walk up the tree adjusting the offset bounds by each offsetParent
while(element.offsetParent) {
element = element.offsetParent;
bounds.left += element.offsetLeft;
bounds.top += element.offsetTop;
}
// Now get ready to scroll the body
this.cancelScroll();
this.startTime = new Date();
var scrollPosition = $tw.utils.getScrollPosition(),
// We'll consider the horizontal and vertical scroll directions separately via this function
getEndPos = function(targetPos,targetSize,currentPos,currentSize) {
var scrollPosition = $tw.utils.getScrollPosition();
// Get the client bounds of the element and adjust by the scroll position
var clientBounds = element.getBoundingClientRect(),
bounds = {
left: clientBounds.left + scrollPosition.x,
top: clientBounds.top + scrollPosition.y,
width: clientBounds.width,
height: clientBounds.height
};
// We'll consider the horizontal and vertical scroll directions separately via this function
var getEndPos = function(targetPos,targetSize,currentPos,currentSize) {
// If the target is above/left of the current view, then scroll to it's top/left
if(targetPos <= currentPos) {
return targetPos;

View File

@ -71,10 +71,20 @@ FieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {
};
FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
var tiddler = this.wiki.getTiddler(this.mangleTitle);
var tiddler = this.wiki.getTiddler(this.mangleTitle),
fieldValidatorRegEx = /^[a-z\-\._]+$/mg;
if(tiddler && typeof event.param === "string") {
var name = event.param.toLowerCase();
if(name !== "" && !$tw.utils.hop(tiddler.fields,name)) {
if(!fieldValidatorRegEx.test(name)) {
alert($tw.language.getString(
"InvalidFieldName",
{variables:
{fieldName: name}
}
));
return true;
}
var addition = this.wiki.getModificationFields();
addition[name] = "";
this.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));

View File

@ -0,0 +1,184 @@
/*\
title: $:/core/modules/widgets/scrollable.js
type: application/javascript
module-type: widget
Scrollable widget
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var ScrollableWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
this.scaleFactor = 1;
this.addEventListeners([
{type: "tw-scroll", handler: "handleScrollEvent"}
]);
if($tw.browser) {
this.requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) {
return window.setTimeout(callback, 1000/60);
};
this.cancelAnimationFrame = window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.webkitCancelRequestAnimationFrame ||
window.mozCancelAnimationFrame ||
window.mozCancelRequestAnimationFrame ||
function(id) {
window.clearTimeout(id);
};
}
};
/*
Inherit from the base widget class
*/
ScrollableWidget.prototype = new Widget();
ScrollableWidget.prototype.cancelScroll = function() {
if(this.idRequestFrame) {
this.cancelAnimationFrame.call(window,this.idRequestFrame);
this.idRequestFrame = null;
}
};
/*
Handle a scroll event
*/
ScrollableWidget.prototype.handleScrollEvent = function(event) {
// Pass the scroll event through if our offsetsize is larger than our scrollsize
if(this.outerDomNode.scrollWidth <= this.outerDomNode.offsetWidth && this.outerDomNode.scrollHeight <= this.outerDomNode.offsetHeight && this.fallthrough === "yes") {
return true;
}
this.scrollIntoView(event.target);
return false; // Handled event
};
/*
Scroll an element into view
*/
ScrollableWidget.prototype.scrollIntoView = function(element) {
var duration = $tw.utils.getAnimationDuration();
this.cancelScroll();
this.startTime = new Date();
var scrollPosition = {
x: this.outerDomNode.scrollLeft,
y: this.outerDomNode.scrollTop
};
// Get the client bounds of the element and adjust by the scroll position
var scrollableBounds = this.outerDomNode.getBoundingClientRect(),
clientTargetBounds = element.getBoundingClientRect(),
bounds = {
left: clientTargetBounds.left + scrollPosition.x - scrollableBounds.left,
top: clientTargetBounds.top + scrollPosition.y - scrollableBounds.top,
width: clientTargetBounds.width,
height: clientTargetBounds.height
};
// We'll consider the horizontal and vertical scroll directions separately via this function
var getEndPos = function(targetPos,targetSize,currentPos,currentSize) {
// If the target is already visible then stay where we are
if(targetPos >= currentPos && (targetPos + targetSize) <= (currentPos + currentSize)) {
return currentPos;
// If the target is above/left of the current view, then scroll to its top/left
} else if(targetPos <= currentPos) {
return targetPos;
// If the target is smaller than the window and the scroll position is too far up, then scroll till the target is at the bottom of the window
} else if(targetSize < currentSize && currentPos < (targetPos + targetSize - currentSize)) {
return targetPos + targetSize - currentSize;
// If the target is big, then just scroll to the top
} else if(currentPos < targetPos) {
return targetPos;
// Otherwise, stay where we are
} else {
return currentPos;
}
},
endX = getEndPos(bounds.left,bounds.width,scrollPosition.x,this.outerDomNode.offsetWidth),
endY = getEndPos(bounds.top,bounds.height,scrollPosition.y,this.outerDomNode.offsetHeight);
// Only scroll if necessary
if(endX !== scrollPosition.x || endY !== scrollPosition.y) {
var self = this,
drawFrame;
drawFrame = function () {
var t;
if(duration <= 0) {
t = 1;
} else {
t = ((new Date()) - self.startTime) / duration;
}
if(t >= 1) {
self.cancelScroll();
t = 1;
}
t = $tw.utils.slowInSlowOut(t);
self.outerDomNode.scrollLeft = scrollPosition.x + (endX - scrollPosition.x) * t;
self.outerDomNode.scrollTop = scrollPosition.y + (endY - scrollPosition.y) * t;
if(t < 1) {
self.idRequestFrame = self.requestAnimationFrame.call(window,drawFrame);
}
};
drawFrame();
}
};
/*
Render this widget into the DOM
*/
ScrollableWidget.prototype.render = function(parent,nextSibling) {
var self = this;
// Remember parent
this.parentDomNode = parent;
// Compute attributes and execute state
this.computeAttributes();
this.execute();
// Create elements
this.outerDomNode = this.document.createElement("div");
$tw.utils.setStyle(this.outerDomNode,[
{overflowY: "auto"},
{overflowX: "auto"},
{webkitOverflowScrolling: "touch"}
]);
this.innerDomNode = this.document.createElement("div");
this.outerDomNode.appendChild(this.innerDomNode);
// Assign classes
this.outerDomNode.className = this["class"] || "";
// Insert element
parent.insertBefore(this.outerDomNode,nextSibling);
this.renderChildren(this.innerDomNode,null);
this.domNodes.push(this.outerDomNode);
};
/*
Compute the internal state of the widget
*/
ScrollableWidget.prototype.execute = function() {
// Get attributes
this.fallthrough = this.getAttribute("fallthrough","yes");
this["class"] = this.getAttribute("class");
// Make child widgets
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ScrollableWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes["class"]) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.scrollable = ScrollableWidget;
})();

View File

@ -0,0 +1,29 @@
/*\
title: $:/core/modules/filters/storyviews.js
type: application/javascript
module-type: filteroperator
Filter operator for returning the names of the story views in this wiki
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.storyviews = function(source,operator,options) {
var results = [],
storyviews = {};
$tw.modules.applyMethods("storyview",storyviews);
$tw.utils.each(storyviews,function(info,name) {
results.push(name);
});
results.sort();
return results;
};
})();

View File

@ -5,10 +5,19 @@ tags: $:/tags/EditTemplate
\define tag-styles()
background-color:$(backgroundColor)$;
\end
<div class="tw-edit-tags"><$fieldmangler><$list filter="[is[current]tags[]sort[title]]" storyview="pop"><$set name="backgroundColor" value={{!!color}}><span style=<<tag-styles>> class="tw-tag-label"><$view field="title" format="text" /><$button message="tw-remove-tag" param={{!!title}} class="btn-invisible tw-remove-tag-button">&times;</$button></span></$set>
</$list>
<div class="tw-edit-tags">
<$fieldmangler>
<$list filter="[is[current]tags[]sort[title]]" storyview="pop" template="$:/core/ui/TagEditTemplate"/>
<div class="tw-edit-add-tag"><span class="tw-add-tag-name"><$edit-text tiddler="$:/temp/NewTagName" tag="input" default="" placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}} focusPopup=<<qualify "$:/state/tagsAutoComplete">> class="tw-edit-texteditor"/></span> <$button popup=<<qualify "$:/state/tagsAutoComplete">> class="btn-invisible btn-dropdown">{{$:/core/images/down-arrow}}</$button> <span class="tw-add-tag-button"><$button message="tw-add-tag" param={{$:/temp/NewTagName}} set="$:/temp/NewTagName" setTo="" class=""><<lingo Tags/Add/Button>></$button></span></div>
<div class="tw-edit-add-tag">
<span class="tw-add-tag-name">
<$edit-text tiddler="$:/temp/NewTagName" tag="input" default="" placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}} focusPopup=<<qualify "$:/state/tagsAutoComplete">> class="tw-edit-texteditor"/>
</span> <$button popup=<<qualify "$:/state/tagsAutoComplete">> class="btn-invisible btn-dropdown">{{$:/core/images/down-arrow}}</$button> <span class="tw-add-tag-button">
<$button message="tw-add-tag" param={{$:/temp/NewTagName}} set="$:/temp/NewTagName" setTo="" class="">
<<lingo Tags/Add/Button>>
</$button>
</span>
</div>
<div class="tw-block-dropdown-wrapper">
@ -18,7 +27,13 @@ background-color:$(backgroundColor)$;
<$linkcatcher set="$:/temp/NewTagName" setTo="" message="tw-add-tag">
<$list filter="[!is[shadow]tags[]search{$:/temp/NewTagName}sort[title]]">
<$link><$set name="backgroundColor" value={{!!color}}><span style=<<tag-styles>> class="tw-tag-label"><$view field="title" format="text"/></span></$set></$link>
<$link>
<$set name="backgroundColor" value={{!!color}}>
<span style=<<tag-styles>> class="tw-tag-label">
<$view field="title" format="text"/>
</span>
</$set>
</$link>
</$list>
</$linkcatcher>

View File

@ -42,6 +42,16 @@ $$$text/vnd.tiddlywiki>text/html
$src$
$$$
\end
\define wikitext-example-without-html(src)
```
$src$
```
Renders as:
$src$
\end
\define lingo-base()
$:/lingo/

View File

@ -0,0 +1,8 @@
title: $:/core/ui/PageTemplate/alerts
tags: $:/tags/PageTemplate
<div class="tw-alerts">
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/Alert]] [!is[shadow]!has[draft.of]tag[$:/tags/Alert]] +[sort[modified]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>
</div>

View File

@ -1,7 +1,11 @@
title: $:/core/ui/PageTemplate/sidebar
tags: $:/tags/PageTemplate
<header class="sidebar-header">
<$scrollable fallthrough="no" class="tw-sidebar-scrollable">
<div class="sidebar-header">
<$reveal state="$:/state/sidebar" type="match" text="yes" default="yes" retain="yes">
<div class="titlebar">{{$:/SiteTitle}}</div>
<div class="tw-subtitle">{{$:/SiteSubtitle}}</div>
@ -14,4 +18,8 @@ tags: $:/tags/PageTemplate
{{$:/core/ui/SideBarLists}}
</header>
</$reveal>
</div>
</$scrollable>

View File

@ -3,15 +3,6 @@ tags: $:/tags/PageTemplate
<section class="story-river">
<!-- Alerts -->
<div class="tw-alerts">
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/Alert]] [!is[shadow]!has[draft.of]tag[$:/tags/Alert]] +[sort[modified]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>
</div>
<!-- The main story -->
<$list filter="[list[$:/StoryList]]" history="$:/HistoryList" template="$:/core/ui/ViewTemplate" editTemplate="$:/core/ui/EditTemplate" storyview={{$:/view}} />
<!-- End of story river -->
</section>

View File

@ -0,0 +1,6 @@
title: $:/core/ui/PageTemplate/topleftbar
tags: $:/tags/PageTemplate
<span class="tw-topbar tw-topbar-left">
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/TopLeftBar]] [!is[shadow]!has[draft.of]tag[$:/tags/TopLeftBar]] +[tag[$:/tags/TopLeftBar]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list>
</span>

View File

@ -0,0 +1,6 @@
title: $:/core/ui/PageTemplate/toprightbar
tags: $:/tags/PageTemplate
<span class="tw-topbar tw-topbar-right">
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/TopRightBar]] [!is[shadow]!has[draft.of]tag[$:/tags/TopRightBar]] +[tag[$:/tags/TopRightBar]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list>
</span>

View File

@ -0,0 +1,16 @@
title: $:/core/ui/TagEditTemplate
\define tag-styles()
background-color:$(backgroundColor)$;
\end
<$set name="backgroundColor" value={{!!color}}>
<$button popup=<<qualify "$:/state/tagpopup">> class="btn-invisible tw-tag-label" style=<<tag-styles>>>
<$view field="title" format="text" />
<$button message="tw-remove-tag" param={{!!title}} class="btn-invisible tw-remove-tag-button">&times;</$button>
</$button>
</$set>
<$reveal state=<<qualify "$:/state/tagpopup">> type="popup" position="below" animate="yes"><div class="tw-drop-down"><$transclude tiddler="$:/core/ui/ListItemTemplate"/>
<hr>
<$list filter="[is[current]tagging[]]" template="$:/core/ui/ListItemTemplate"/>
</div>
</$reveal>

View File

@ -0,0 +1,4 @@
title: $:/core/ui/TopBar/home
tags: $:/tags/TopLeftBar
<$button message="tw-home" class="btn-invisible">{{$:/core/images/home-button}}</$button>

View File

@ -0,0 +1,9 @@
title: $:/core/ui/TopBar/menu
tags: $:/tags/TopRightBar
<$reveal state="$:/state/sidebar" type="nomatch" text="no">
<$button set="$:/state/sidebar" setTo="no" class="btn-invisible">{{$:/core/images/menu-button}}</$button>
</$reveal>
<$reveal state="$:/state/sidebar" type="match" text="no">
<$button set="$:/state/sidebar" setTo="yes" class="btn-invisible">{{$:/core/images/menu-button}}</$button>
</$reveal>

View File

@ -1,3 +1,3 @@
title: $:/tags/PageTemplate
list: [[$:/core/ui/PageTemplate/sidebar]] [[$:/core/ui/PageTemplate/story]]
list: [[$:/core/ui/PageTemplate/sidebar]] [[$:/core/ui/PageTemplate/story]] [[$:/core/ui/PageTemplate/alerts]] [[$:/core/ui/PageTemplate/topleftbar]] [[$:/core/ui/PageTemplate/toprightbar]]

View File

@ -3,7 +3,7 @@ title: $:/snippets/viewswitcher
\define lingo-base() $:/language/ControlPanel/Appearance/StoryView/
<<lingo Prompt>> {{$:/view}}
<$linkcatcher to="$:/view"><$list filter="classic zoomin pop"><div><$reveal state="$:/view" type="match" text={{!!title}}>&bull;</$reveal><$reveal state="$:/view" type="nomatch" text={{!!title}}>&nbsp;</$reveal> <$link to={{!!title}}><$view field="title"/></$link>
<$linkcatcher to="$:/view"><$list filter="[storyviews[]]"><div><$reveal state="$:/view" type="match" text={{!!title}}>&bull;</$reveal><$reveal state="$:/view" type="nomatch" text={{!!title}}>&nbsp;</$reveal> <$link to={{!!title}}><$view field="title"/></$link>
</div>
</$list>
</$linkcatcher>

View File

@ -14,10 +14,10 @@ We have an email discussion list, too: https://groups.google.com/forum/#!members
The second OXTWIG meeting was held on Thursday 16th January 2014:
<iframe width="560" height="315" src="//www.youtube.com/embed/WOK_nVBf_6U" frameborder="0" allowfullscreen></iframe>
<iframe width="560" height="315" src="http://www.youtube.com/embed/WOK_nVBf_6U" frameborder="0" allowfullscreen></iframe>
! OXTWIG #1
The first OXTWIG meeting was held on Thursday 21st November 2013:
<iframe width="560" height="315" src="//www.youtube.com/embed/tpNf_Dms_TE" frameborder="0" allowfullscreen></iframe>
<iframe width="560" height="315" src="http://www.youtube.com/embed/tpNf_Dms_TE" frameborder="0" allowfullscreen></iframe>

View File

@ -1,6 +1,7 @@
title: FilterOperators
created: 20140303091312363
modified: 20140303091312363
modified: 20140324221721972
title: FilterOperators
type: text/vnd.tiddlywiki
The available filter operators are listed here. See TiddlerFilters for an introduction to tiddler filters and how they are used.
@ -39,6 +40,8 @@ The available filter operators are listed here. See TiddlerFilters for an introd
* ''bl'': another synonym for ''butlast''
* ''nth'': selects the n-th tiddler of the list. Defaults to n = 1
* ''indexes'': selects the names of the indexes within a [[DataTiddler|DataTiddlers]]
* ''moduletypes'': selects the list of types of all the loaded modules
* ''storyviews'': selects the list of names of loaded storyviews
The operands available with the `is` operator are:

View File

@ -0,0 +1,3 @@
title: $:/CurvedText
Everything in federation

View File

@ -0,0 +1,26 @@
created: 20140324223413403
modified: 20140324223524945
tags: howto
title: Making curved text with SVG
type: text/vnd.tiddlywiki
\define textOnPath(text)
$$$.svg
<svg width="100%" height="100%" viewBox="0 0 1000 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="MyPath" d="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"/>
</defs>
<use xlink:href="#MyPath" fill="none" stroke="#ddd"/>
<text font-family="'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif" font-size="42.5">
<textPath xlink:href="#MyPath">
$text$
</textPath>
</text>
</svg>
$$$
\end
This demo shows how to use SVG to render transcluded text along a path. Enter some text in the textbox below to try it out; view the source to see how it is done.
<$edit-text tiddler="$:/CurvedText" tag="input" placeholder="Type text here" default=""/>
<$macrocall $name="textOnPath" text={{$:/CurvedText}}/>

View File

@ -1,5 +1,8 @@
title: $:/editions/tw5.com/github-fork-ribbon
tags: $:/tags/PageTemplate
tags: $:/tags/PageControls
<div class="github-fork-ribbon-wrapper right" style>
<div class="github-fork-ribbon" style="background-color:#A3D53A;"><$link to="ReleaseHistory"><<version>></$link></div>
<div class="github-fork-ribbon-wrapper right" style><div class="github-fork-ribbon" style="background-color:#A3D53A;"><$link to="ReleaseHistory"><<version>></$link></div>
</div>

View File

@ -32,3 +32,10 @@ tags: $:/tags/stylesheet
font-weight: 500;
font-size: 16px;
}
.tw-scrollable-demo {
border: 1px solid <<colour message-border>>;
background-color: <<colour message-background>>;
padding: 1em;
height: 400px;
}

View File

@ -0,0 +1,46 @@
created: 20140324223413403
modified: 20140324223524945
tags: widget
title: ScrollableWidget
type: text/vnd.tiddlywiki
! Introduction
The scrollable widget wraps its content in a scrollable frame. The user can scroll the contents with the mouse or with touch gestures. Code can use the [[WidgetMessage: tw-scroll]] to programmatically scroll specific DOM nodes into view.
! Content and Attributes
The content of the `<$scrollable>` widget is displayed within a pair of wrapper DIVs. If the inner DIV is larger then it scrolls within the outer one. CSS is used to specify the size of the outer wrapper.
|!Attribute |!Description |
|class |The CSS class(es) to be applied to the outer DIV |
|fallthrough |See below |
If a scrollable widget can't handle the `tw-scroll` message because the inner DIV fits within the outer DIV, then by default the message falls through to the parent widget. Setting the ''fallthrough'' attribute to `no` prevents this behaviour.
! Examples
This example requires the following CSS definitions from [[$:/_tw5.com-styles]]:
```
.tw-scrollable-demo {
border: 1px solid <<colour message-border>>;
background-color: <<colour message-background>>;
padding: 1em;
height: 400px;
}
```
This wiki text shows how to display a list within the scrollable widget:
<<wikitext-example-without-html "<$scrollable class='tw-scrollable-demo'>
<$list filter='[!is[system]]'>
<$view field='title'/>: <$list filter='[is[current]links[]sort[title]]' storyview='pop'>
<$link><$view field='title'/></$link>
</$list>
</$list>
</$scrollable>
">>

View File

@ -1,5 +1,6 @@
{
"plugins": [
"tiddlywiki/cecily",
"tiddlywiki/fullscreen",
"tiddlywiki/googleanalytics",
"tiddlywiki/nodewebkitsaver",

View File

@ -0,0 +1,143 @@
/*\
title: $:/plugins/tiddlywiki/cecily/cecily.js
type: application/javascript
module-type: storyview
Positions tiddlers on a 2D map
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var CecilyStoryView = function(listWidget) {
var self = this;
this.listWidget = listWidget;
// Load the map
this.loadMap();
// Position the existing tiddlers
$tw.utils.each(this.listWidget.children,function(itemWidget,index) {
var domNode = itemWidget.findFirstDomNode();
domNode.style.position = "absolute";
var title = itemWidget.parseTreeNode.itemTitle;
self.positionTiddler(title,domNode);
});
};
CecilyStoryView.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});
};
CecilyStoryView.prototype.insert = function(widget) {
var domNode = widget.findFirstDomNode(),
duration = $tw.utils.getAnimationDuration();
// Make the newly inserted node position absolute
$tw.utils.setStyle(domNode,[
{position: "absolute"},
{transition: ""},
{opacity: "0.0"}
]);
// Position it
var title = widget.parseTreeNode.itemTitle;
this.positionTiddler(title,domNode);
$tw.utils.forceLayout(domNode);
// Animate it in
$tw.utils.setStyle(domNode,[
{transition: "opacity " + duration + "ms ease-out"},
{opacity: "1.0"}
]);
};
CecilyStoryView.prototype.remove = function(widget) {
var targetElement = widget.findFirstDomNode(),
duration = $tw.utils.getAnimationDuration();
// Remove the widget at the end of the transition
setTimeout(function() {
widget.removeChildDomNodes();
},duration);
// Animate the closure
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{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"},
{transform: "scale(0.01)"},
{opacity: "0.0"}
]);
};
/*
Load the current map
*/
CecilyStoryView.prototype.loadMap = function() {
this.map = this.listWidget.wiki.getTiddlerData(this.getMapTiddlerTitle(),{
positions: {},
newTiddlerPosition: {x: 0, y: 0}
});
};
CecilyStoryView.prototype.getMapTiddlerTitle = function() {
return this.listWidget.getAttribute("map","$:/TiddlerMap");
};
/*
Position a tiddler according to the map
*/
CecilyStoryView.prototype.positionTiddler = function(title,domNode) {
var pos = this.lookupTiddlerInMap(title,domNode),
scale = pos.w/domNode.offsetWidth;
$tw.utils.setStyle(domNode,[
{transformOrigin: "0% 0%"},
{transform: "translateX(" + pos.x + "px) translateY(" + pos.y + "px) scale(" + scale + ")"}
]);
};
// Get the position of a particular tiddler
CecilyStoryView.prototype.lookupTiddlerInMap = function(title,domNode) {
// If this is a draft tiddler then look for the position of the original tiddler
var tiddler = this.listWidget.wiki.getTiddler(title);
if(tiddler) {
var draftOf = tiddler.fields["draft.of"];
if(draftOf && this.map.positions[draftOf]) {
return this.map.positions[draftOf]
}
}
// Try looking the target tiddler up in the map
if(this.map.positions[title]) {
return this.map.positions[title];
}
// If the tiddler wasn't in the map we'll have to compute it
var newPosition;
switch(this.map.positionNew) {
default: // "right"
newPosition = {
x: this.map.newTiddlerPosition.x,
y: this.map.newTiddlerPosition.y,
w: 200,
h: 200
};
this.map.newTiddlerPosition.x += newPosition.w * 1.1;
break;
}
// A default position
newPosition = newPosition || {x: 0,y: 0,w: 100,h: 100};
// Save the position back to the map
this.map.positions[title] = newPosition;
return newPosition;
};
exports.cecily = CecilyStoryView;
})();

View File

@ -0,0 +1,6 @@
{
"title": "$:/plugins/tiddlywiki/cecily",
"description": "Zoomable User Interface for TiddlyWiki",
"author": "JeremyRuston",
"core-version": ">=5.0.0"
}

View File

@ -17,10 +17,10 @@ tags: [[$:/tags/stylesheet]]
text-align: left;
}
html .sidebar-header {
html .tw-sidebar-scrollable {
text-align: left;
left: 50%;
right: 0;
padding-left: 413px;
margin-left: 343px;
}
}

View File

@ -1,8 +0,0 @@
title: $:/themes/tiddlywiki/nighttime/base
tags: [[$:/tags/stylesheet]]
\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline
html body.tw-body {
background-color: #5C5D8E;
}

View File

@ -1,9 +0,0 @@
{
"title": "$:/themes/tiddlywiki/nighttime",
"name": "Night-time",
"author": "JeremyRuston",
"core-version": ">=5.0.0",
"plugin-type": "theme",
"description": "A darker theme",
"dependents": ["$:/themes/tiddlywiki/vanilla"]
}

View File

@ -7,10 +7,6 @@ tags: [[$:/tags/stylesheet]]
text-shadow: 0 1px 0 <<colour sidebar-foreground-shadow>>;
}
.tw-page-controls svg {
<<transition "fill 150ms ease-in-out">>
}
.tw-tiddler-info {
<<box-shadow "inset 1px 2px 3px rgba(0,0,0,0.1)">>
}
@ -27,7 +23,7 @@ tags: [[$:/tags/stylesheet]]
}
}
.tw-tiddler-controls button svg {
.tw-page-controls button svg, .tw-tiddler-controls button svg, .tw-topbar button svg {
<<transition "fill 150ms ease-in-out">>
}

View File

@ -14,7 +14,7 @@ Placeholder for a more thorough refinement of Snow White
src: local("Arvo"), url(<<datauri "$:/themes/tiddlywiki/starlight/arvo.woff">>) format("woff");
}
html body {
html body, .tw-sidebar-scrollable-backdrop {
font-family: "Arvo", "Times";
background: url(<<datauri "$:/themes/tiddlywiki/starlight/ltbg.jpg">>);
}

View File

@ -245,6 +245,10 @@ a.tw-tiddlylink-external:hover {
line-height: 1.4em;
}
.tw-sidebar-lists input {
color: <<colour foreground>>;
}
.tw-sidebar-lists button {
color: <<colour sidebar-button-foreground>>;
}
@ -253,7 +257,7 @@ a.tw-tiddlylink-external:hover {
color: <<colour sidebar-muted-foreground>>;
}
.btn-mini:hover {
.tw-sidebar-lists button.btn-mini:hover {
color: <<colour sidebar-muted-foreground-hover>>;
}
@ -312,6 +316,33 @@ a.tw-tiddlylink-external:hover {
** Page layout
*/
.tw-topbar {
position: fixed;
z-index: 1200;
}
.tw-topbar-left {
left: 0;
top: 0;
}
.tw-topbar-right {
top: 0;
right: 0;
}
.tw-topbar button {
padding: 8px;
}
.tw-topbar svg {
fill: <<colour muted-foreground>>;
}
.tw-topbar svg:hover {
fill: <<colour foreground>>;
}
.sidebar-header {
color: <<colour sidebar-foreground>>;
}
@ -386,8 +417,10 @@ a.tw-tiddlylink-external:hover {
}
@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics##storywidth}}) {
.sidebar-header {
padding: 14px;
min-height: 32px;
}
.story-river {
@ -397,7 +430,12 @@ a.tw-tiddlylink-external:hover {
}
@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics##storywidth}}) {
.sidebar-header {
.tw-message-box {
margin: 21px -21px 21px -21px;
}
.tw-sidebar-scrollable {
position: fixed;
top: {{$:/themes/tiddlywiki/vanilla/metrics##storytop}};
left: {{$:/themes/tiddlywiki/vanilla/metrics##storyright}};
@ -1067,7 +1105,6 @@ canvas.tw-edit-bitmapeditor {
border: 1px solid <<colour message-border>>;
background: <<colour message-background>>;
padding: 0px 21px 0px 21px;
margin: 21px -21px 21px -21px;
font-size: 12px;
line-height: 18px;
color: <<colour message-foreground>>;
@ -1122,3 +1159,5 @@ canvas.tw-edit-bitmapeditor {
margin: 4px;
border: 1px solid #000;
}