mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +00:00
Add a new scroller story view
This is the default story view
This commit is contained in:
parent
19d308dd9c
commit
3e899d8daf
@ -28,4 +28,8 @@ exports.dateFormats = {
|
||||
|
||||
exports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };
|
||||
|
||||
exports.preferences = {
|
||||
animationDuration: 400
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -20,17 +20,6 @@ The storyview is a plugin that extends the story macro to implement different na
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
function scrollToTop(duration) {
|
||||
if (duration < 0) {
|
||||
return;
|
||||
}
|
||||
var delta = (-document.body.scrollTop/duration) * 10;
|
||||
window.setTimeout(function() {
|
||||
document.body.scrollTop = document.body.scrollTop + delta;
|
||||
scrollToTop(duration-10);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
exports.info = {
|
||||
name: "story",
|
||||
params: {
|
||||
@ -43,89 +32,118 @@ exports.info = {
|
||||
};
|
||||
|
||||
exports.handleEvent = function(event) {
|
||||
var template, storyTiddler, story, storyRecord, tiddler, storyTiddlerModified, t;
|
||||
switch(event.type) {
|
||||
case "tw-navigate":
|
||||
// Navigate to a specified tiddler
|
||||
template = this.hasParameter("defaultViewTemplate") ? this.params.defaultViewTemplate : "ViewTemplate";
|
||||
storyTiddler = this.wiki.getTiddler(this.params.story);
|
||||
story = {tiddlers: []};
|
||||
if(storyTiddler && $tw.utils.hop(storyTiddler.fields,"text")) {
|
||||
story = JSON.parse(storyTiddler.fields.text);
|
||||
}
|
||||
story.tiddlers.unshift({title: event.navigateTo, template: template});
|
||||
this.wiki.addTiddler(new $tw.Tiddler(storyTiddler,{text: JSON.stringify(story)}));
|
||||
scrollToTop(400);
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
case "tw-EditTiddler":
|
||||
// Put the specified tiddler into edit mode
|
||||
template = this.hasParameter("defaultEditTemplate") ? this.params.defaultEditTemplate : "EditTemplate";
|
||||
storyTiddler = this.wiki.getTiddler(this.params.story);
|
||||
story = {tiddlers: []};
|
||||
if(storyTiddler && $tw.utils.hop(storyTiddler.fields,"text")) {
|
||||
story = JSON.parse(storyTiddler.fields.text);
|
||||
}
|
||||
for(t=0; t<story.tiddlers.length; t++) {
|
||||
storyRecord = story.tiddlers[t];
|
||||
if(storyRecord.title === event.tiddlerTitle && storyRecord.template !== template) {
|
||||
storyRecord.title = "Draft " + (new Date()) + " of " + event.tiddlerTitle;
|
||||
storyRecord.template = template;
|
||||
tiddler = this.wiki.getTiddler(event.tiddlerTitle);
|
||||
this.wiki.addTiddler(new $tw.Tiddler(
|
||||
{
|
||||
text: "Type the text for the tiddler '" + event.tiddlerTitle + "'"
|
||||
},
|
||||
tiddler,
|
||||
{
|
||||
title: storyRecord.title,
|
||||
"draft.title": event.tiddlerTitle,
|
||||
"draft.of": event.tiddlerTitle
|
||||
}));
|
||||
}
|
||||
}
|
||||
this.wiki.addTiddler(new $tw.Tiddler(storyTiddler,{text: JSON.stringify(story)}));
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
case "tw-SaveTiddler":
|
||||
template = this.hasParameter("defaultViewTemplate") ? this.params.defaultEditTemplate : "ViewTemplate";
|
||||
storyTiddler = this.wiki.getTiddler(this.params.story);
|
||||
story = {tiddlers: []};
|
||||
storyTiddlerModified = false;
|
||||
if(storyTiddler && $tw.utils.hop(storyTiddler.fields,"text")) {
|
||||
story = JSON.parse(storyTiddler.fields.text);
|
||||
}
|
||||
for(t=0; t<story.tiddlers.length; t++) {
|
||||
storyRecord = story.tiddlers[t];
|
||||
if(storyRecord.title === event.tiddlerTitle && storyRecord.template !== template) {
|
||||
tiddler = this.wiki.getTiddler(storyRecord.title);
|
||||
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.title")) {
|
||||
// Save the draft tiddler as the real tiddler
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: tiddler.fields["draft.title"],"draft.title": undefined, "draft.of": undefined}));
|
||||
// Remove the draft tiddler
|
||||
this.wiki.deleteTiddler(storyRecord.title);
|
||||
// Remove the original tiddler if we're renaming it
|
||||
if(tiddler.fields["draft.of"] !== tiddler.fields["draft.title"]) {
|
||||
this.wiki.deleteTiddler(tiddler.fields["draft.of"]);
|
||||
}
|
||||
// Make the story record point to the newly saved tiddler
|
||||
storyRecord.title = tiddler.fields["draft.title"];
|
||||
storyRecord.template = template;
|
||||
// Check if we're modifying the story tiddler itself
|
||||
if(tiddler.fields["draft.title"] === this.params.story) {
|
||||
storyTiddlerModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!storyTiddlerModified) {
|
||||
this.wiki.addTiddler(new $tw.Tiddler(storyTiddler,{text: JSON.stringify(story)}));
|
||||
}
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
if(this.eventMap[event.type]) {
|
||||
this.eventMap[event.type].call(this,event);
|
||||
}
|
||||
};
|
||||
|
||||
exports.eventMap = {};
|
||||
|
||||
// Navigate to a specified tiddler
|
||||
exports.eventMap["tw-navigate"] = function(event) {
|
||||
var template = this.params.defaultViewTemplate || "ViewTemplate",
|
||||
storyTiddler = this.wiki.getTiddler(this.params.story),
|
||||
story = {tiddlers: []},
|
||||
navTiddler,t,tiddler;
|
||||
// Get the story
|
||||
if(storyTiddler && $tw.utils.hop(storyTiddler.fields,"text")) {
|
||||
story = JSON.parse(storyTiddler.fields.text);
|
||||
}
|
||||
// See if the tiddler we want is already there
|
||||
for(t=0; t<story.tiddlers.length; t++) {
|
||||
if(story.tiddlers[t].title === event.navigateTo) {
|
||||
navTiddler = t;
|
||||
}
|
||||
}
|
||||
if(typeof(navTiddler) !== "undefined") {
|
||||
// If we found our tiddler, just tell the storyview to navigate to it
|
||||
if(this.storyview && this.storyview.navigate) {
|
||||
this.storyview.navigate(this.children[0].children[navTiddler],false,event);
|
||||
}
|
||||
} else {
|
||||
// Add the tiddler to the bottom of the story (subsequently there will be a refreshInDom() call which is when we'll actually do the navigation)
|
||||
story.tiddlers.push({title: event.navigateTo, template: template});
|
||||
this.wiki.addTiddler(new $tw.Tiddler(storyTiddler,{text: JSON.stringify(story)}));
|
||||
// Record the details of the navigation for us to pick up in refreshInDom()
|
||||
this.lastNavigationEvent = event;
|
||||
}
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
// Place a tiddler in edit mode
|
||||
exports.eventMap["tw-EditTiddler"] = function(event) {
|
||||
var template, storyTiddler, story, storyRecord, tiddler, t;
|
||||
// Put the specified tiddler into edit mode
|
||||
template = this.params.defaultEditTemplate || "EditTemplate";
|
||||
storyTiddler = this.wiki.getTiddler(this.params.story);
|
||||
story = {tiddlers: []};
|
||||
if(storyTiddler && $tw.utils.hop(storyTiddler.fields,"text")) {
|
||||
story = JSON.parse(storyTiddler.fields.text);
|
||||
}
|
||||
for(t=0; t<story.tiddlers.length; t++) {
|
||||
storyRecord = story.tiddlers[t];
|
||||
if(storyRecord.title === event.tiddlerTitle && storyRecord.template !== template) {
|
||||
storyRecord.title = "Draft " + (new Date()) + " of " + event.tiddlerTitle;
|
||||
storyRecord.template = template;
|
||||
tiddler = this.wiki.getTiddler(event.tiddlerTitle);
|
||||
this.wiki.addTiddler(new $tw.Tiddler(
|
||||
{
|
||||
text: "Type the text for the tiddler '" + event.tiddlerTitle + "'"
|
||||
},
|
||||
tiddler,
|
||||
{
|
||||
title: storyRecord.title,
|
||||
"draft.title": event.tiddlerTitle,
|
||||
"draft.of": event.tiddlerTitle
|
||||
}));
|
||||
}
|
||||
}
|
||||
this.wiki.addTiddler(new $tw.Tiddler(storyTiddler,{text: JSON.stringify(story)}));
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
// Take a tiddler out of edit mode, saving the changes
|
||||
exports.eventMap["tw-SaveTiddler"] = function(event) {
|
||||
var template, storyTiddler, story, storyRecord, tiddler, storyTiddlerModified, t;
|
||||
template = this.params.defaultEditTemplate || "ViewTemplate";
|
||||
storyTiddler = this.wiki.getTiddler(this.params.story);
|
||||
story = {tiddlers: []};
|
||||
storyTiddlerModified = false;
|
||||
if(storyTiddler && $tw.utils.hop(storyTiddler.fields,"text")) {
|
||||
story = JSON.parse(storyTiddler.fields.text);
|
||||
}
|
||||
for(t=0; t<story.tiddlers.length; t++) {
|
||||
storyRecord = story.tiddlers[t];
|
||||
if(storyRecord.title === event.tiddlerTitle && storyRecord.template !== template) {
|
||||
tiddler = this.wiki.getTiddler(storyRecord.title);
|
||||
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.title")) {
|
||||
// Save the draft tiddler as the real tiddler
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: tiddler.fields["draft.title"],"draft.title": undefined, "draft.of": undefined}));
|
||||
// Remove the draft tiddler
|
||||
this.wiki.deleteTiddler(storyRecord.title);
|
||||
// Remove the original tiddler if we're renaming it
|
||||
if(tiddler.fields["draft.of"] !== tiddler.fields["draft.title"]) {
|
||||
this.wiki.deleteTiddler(tiddler.fields["draft.of"]);
|
||||
}
|
||||
// Make the story record point to the newly saved tiddler
|
||||
storyRecord.title = tiddler.fields["draft.title"];
|
||||
storyRecord.template = template;
|
||||
// Check if we're modifying the story tiddler itself
|
||||
if(tiddler.fields["draft.title"] === this.params.story) {
|
||||
storyTiddlerModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!storyTiddlerModified) {
|
||||
this.wiki.addTiddler(new $tw.Tiddler(storyTiddler,{text: JSON.stringify(story)}));
|
||||
}
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
exports.executeMacro = function() {
|
||||
var storyJson = JSON.parse(this.wiki.getTiddlerText(this.params.story)),
|
||||
storyNode = $tw.Tree.Element("div",{},[]);
|
||||
@ -146,6 +164,12 @@ exports.postRenderInDom = function() {
|
||||
if(StoryView) {
|
||||
this.storyview = new StoryView(this);
|
||||
};
|
||||
if(!this.storyview) {
|
||||
StoryView = this.wiki.macros.story.viewers["scroller"];
|
||||
if(StoryView) {
|
||||
this.storyview = new StoryView(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.refreshInDom = function(changes) {
|
||||
@ -183,8 +207,9 @@ exports.refreshInDom = function(changes) {
|
||||
m.execute(this.parents,this.tiddlerTitle);
|
||||
m.renderInDom(this.children[0].domNode,this.children[0].domNode.childNodes[t]);
|
||||
this.children[0].children.splice(t,0,m);
|
||||
if(this.storyview && this.storyview.tiddlerAdded) {
|
||||
this.storyview.tiddlerAdded(this.children[0].children[t]);
|
||||
// Invoke the storyview to animate the navigation
|
||||
if(this.storyview && this.storyview.navigate) {
|
||||
this.storyview.navigate(this.children[0].children[t],true,this.lastNavigationEvent);
|
||||
}
|
||||
} else {
|
||||
// Delete any nodes preceding the one we want
|
||||
@ -210,10 +235,13 @@ exports.refreshInDom = function(changes) {
|
||||
this.children[0].children.splice(story.tiddlers.length,this.children[0].children.length-story.tiddlers.length);
|
||||
}
|
||||
} else {
|
||||
// If our dependencies didn't change, just refresh the children
|
||||
for(t=0; t<this.children.length; t++) {
|
||||
this.children[t].refreshInDom(changes);
|
||||
}
|
||||
}
|
||||
// Clear the details of the last navigation
|
||||
this.lastNavigationEvent = undefined;
|
||||
};
|
||||
|
||||
})();
|
||||
|
74
core/modules/macros/story/views/scroller.js
Normal file
74
core/modules/macros/story/views/scroller.js
Normal file
@ -0,0 +1,74 @@
|
||||
/*\
|
||||
title: $:/core/modules/macros/story/views/scroller.js
|
||||
type: application/javascript
|
||||
module-type: storyview
|
||||
|
||||
A storyview that shows a sequence of tiddlers and navigates by scrolling
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
function slowInSlowOut(t) {
|
||||
return (1 - ((Math.cos(t * Math.PI) + 1) / 2));
|
||||
}
|
||||
|
||||
function animate(animList,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);
|
||||
for(var a=0; a<animList.length; a++) {
|
||||
var anim = animList[a];
|
||||
document.body[anim.property] = anim.from + (anim.to - anim.from) * t;
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
/*
|
||||
Check if the top left corner of a given element is currently visible, given the scroll position
|
||||
*/
|
||||
function isVisible(element) {
|
||||
var x = element.offsetLeft, y = element.offsetTop;
|
||||
return (x >= document.body.scrollLeft) &&
|
||||
(x < (document.body.scrollLeft + window.innerHeight)) &&
|
||||
(y >= document.body.scrollTop) &&
|
||||
(y < (document.body.scrollTop + window.innerHeight));
|
||||
}
|
||||
|
||||
/*
|
||||
Smoothly scroll an element back into view if needed
|
||||
*/
|
||||
function scrollIntoView(element) {
|
||||
if(!isVisible(element)) {
|
||||
animate([
|
||||
{property: "scrollLeft", from: document.body.scrollLeft, to: element.offsetLeft},
|
||||
{property: "scrollTop", from: document.body.scrollTop, to: element.offsetTop}
|
||||
],$tw.config.preferences.animationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
function Scroller(story) {
|
||||
this.story = story;
|
||||
}
|
||||
|
||||
/*
|
||||
Visualise navigation to the specified tiddler macro, optionally specifying a source node for the visualisation
|
||||
targetTiddlerNode: tree node of the tiddler macro we're navigating to
|
||||
isNew: true if the node we're navigating to has just been added to the DOM
|
||||
sourceNode: optional tree node that initiated the navigation
|
||||
*/
|
||||
Scroller.prototype.navigate = function(targetTiddlerNode,isNew,sourceEvent) {
|
||||
scrollIntoView(targetTiddlerNode.domNode);
|
||||
};
|
||||
|
||||
exports.scroller = Scroller;
|
||||
|
||||
})();
|
Loading…
Reference in New Issue
Block a user