mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-17 23:34:50 +00:00
Refactored slider macro to lazily render it's content
This commit is contained in:
parent
60670509e0
commit
4649a0bd88
@ -5,6 +5,8 @@ title: js/macros/slider.js
|
|||||||
The slider macro is used to selectively reveal a chunk of text. By default, it renders as a button that may be clicked or touched to reveal the enclosed text.
|
The slider macro is used to selectively reveal a chunk of text. By default, it renders as a button that may be clicked or touched to reveal the enclosed text.
|
||||||
|
|
||||||
The enclosed text can be a string of WikiText or be taken from a target tiddler.
|
The enclosed text can be a string of WikiText or be taken from a target tiddler.
|
||||||
|
|
||||||
|
The current state of the slider can be stored as the string "open" or "closed" in a specified tiddler. If the value of that tiddler changes then the slider is automatically updated.
|
||||||
!!Parameters
|
!!Parameters
|
||||||
|`state` //(defaults to 1st parameter)// |The title of the tiddler to contain the current state of the slider |
|
|`state` //(defaults to 1st parameter)// |The title of the tiddler to contain the current state of the slider |
|
||||||
|`default` |The initial state of the slider, either `open` or `closed` |
|
|`default` |The initial state of the slider, either `open` or `closed` |
|
||||||
@ -30,6 +32,44 @@ var Renderer = require("../Renderer.js").Renderer,
|
|||||||
Tiddler = require("../Tiddler.js").Tiddler,
|
Tiddler = require("../Tiddler.js").Tiddler,
|
||||||
utils = require("../Utils.js");
|
utils = require("../Utils.js");
|
||||||
|
|
||||||
|
|
||||||
|
function getOpenState() {
|
||||||
|
if(this.params.hasOwnProperty("state")) {
|
||||||
|
var stateTiddler = this.store.getTiddler(this.params.state);
|
||||||
|
if(stateTiddler) {
|
||||||
|
return stateTiddler.text.trim() === "open";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(this.params.hasOwnProperty("default")) {
|
||||||
|
return this.params["default"] === "open";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
function saveOpenState() {
|
||||||
|
if(this.params.hasOwnProperty("state")) {
|
||||||
|
var stateTiddler = this.store.getTiddler(this.params.state) ||
|
||||||
|
new Tiddler({title: this.params.state, text: ""});
|
||||||
|
this.store.addTiddler(new Tiddler(stateTiddler,{text: this.isOpen ? "open" : "closed"}));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSliderContent() {
|
||||||
|
if(this.params.hasOwnProperty("content")) {
|
||||||
|
return this.store.parseText("text/x-tiddlywiki",this.params.content).nodes;
|
||||||
|
} else if(this.params.hasOwnProperty("target")) {
|
||||||
|
return [Renderer.MacroNode(
|
||||||
|
"tiddler",
|
||||||
|
{target: this.params.target},
|
||||||
|
null,
|
||||||
|
this.store)];
|
||||||
|
} else {
|
||||||
|
return [Renderer.ErrorNode("No content specified for slider")];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "slider",
|
name: "slider",
|
||||||
types: ["text/html","text/plain"],
|
types: ["text/html","text/plain"],
|
||||||
@ -43,12 +83,11 @@ exports.macro = {
|
|||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
click: function(event) {
|
click: function(event) {
|
||||||
if(event.target === event.currentTarget.firstChild.firstChild) {
|
if(event.target === this.domNode.firstChild.firstChild) {
|
||||||
var el = event.currentTarget.firstChild.firstChild.nextSibling,
|
this.isOpen = !this.isOpen;
|
||||||
stateTiddler = this.params.state ? this.store.getTiddler(this.params.state) : null;
|
if(!saveOpenState.call(this)) {
|
||||||
stateTiddler = stateTiddler || new Tiddler({title: this.params.state, text: ""});
|
exports.macro.refreshInDom.call(this,{});
|
||||||
var isOpen = stateTiddler.text.trim() === "open";
|
}
|
||||||
this.store.addTiddler(new Tiddler(stateTiddler,{text: isOpen ? "closed" : "open"}));
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -57,37 +96,40 @@ exports.macro = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
execute: function() {
|
execute: function() {
|
||||||
var isOpen = this.params.state ? this.store.getTiddlerText(this.params.state,"").trim() === "open" : true,
|
this.isOpen = getOpenState.call(this);
|
||||||
target = this.params.target,
|
var sliderContent = [];
|
||||||
sliderContent;
|
if(this.isOpen) {
|
||||||
if(this.params.hasOwnProperty("content")) {
|
sliderContent = getSliderContent.call(this);
|
||||||
sliderContent = this.store.parseText("text/x-tiddlywiki",this.params.content).nodes;
|
|
||||||
} else {
|
|
||||||
sliderContent = [Renderer.MacroNode(
|
|
||||||
"tiddler",
|
|
||||||
{target: target},
|
|
||||||
null,
|
|
||||||
this.store)];
|
|
||||||
}
|
}
|
||||||
var content = Renderer.SliderNode(this.params.state,
|
var content = Renderer.SliderNode(this.params.state,
|
||||||
this.params.label ? this.params.label : target,
|
this.params.label ? this.params.label : this.params.target,
|
||||||
this.params.tooltip,
|
this.params.tooltip,
|
||||||
isOpen,
|
this.isOpen,
|
||||||
sliderContent);
|
sliderContent);
|
||||||
content.execute(this.parents,this.store.getTiddler(this.tiddlerText));
|
content.execute(this.parents,this.store.getTiddler(this.tiddlerTitle));
|
||||||
return [content];
|
return [content];
|
||||||
},
|
},
|
||||||
refreshInDom: function(changes) {
|
refreshInDom: function(changes) {
|
||||||
if(this.params.target && changes.hasOwnProperty(this.params.target)) {
|
var needContentRefresh = true; // Avoid refreshing the content nodes if we don't need to
|
||||||
// If the target has changed, re-render the macro
|
// If the state tiddler has changed then reset the open state
|
||||||
} else {
|
if(this.params.hasOwnProperty("state") && changes.hasOwnProperty(this.params.state)) {
|
||||||
if (this.params.state && changes.hasOwnProperty(this.params.state)) {
|
this.isOpen = getOpenState.call(this);
|
||||||
// If it was just the state tiddler that's changed, set the display appropriately
|
}
|
||||||
var el = this.domNode.firstChild.firstChild.nextSibling,
|
// Render the content if the slider is open and we don't have any content yet
|
||||||
isOpen = this.store.getTiddlerText(this.params.state,"").trim() === "open";
|
if(this.isOpen && this.content[0].children[1].children.length === 0) {
|
||||||
el.style.display = isOpen ? "block" : "none";
|
// Get the slider content and execute it
|
||||||
}
|
this.content[0].children[1].children = getSliderContent.call(this);
|
||||||
// Refresh any children
|
this.content[0].children[1].execute(this.parents,this.store.getTiddler(this.tiddlerTitle));
|
||||||
|
// Replace the existing slider body DOM node
|
||||||
|
this.domNode.firstChild.removeChild(this.domNode.firstChild.firstChild.nextSibling);
|
||||||
|
this.content[0].children[1].renderInDom(this.domNode.firstChild,this.domNode.firstChild.firstChild.nextSibling);
|
||||||
|
needContentRefresh = false; // Don't refresh the children if we've just created them
|
||||||
|
}
|
||||||
|
// Set the visibility of the slider content
|
||||||
|
var el = this.domNode.firstChild.firstChild.nextSibling;
|
||||||
|
el.style.display = this.isOpen ? "block" : "none";
|
||||||
|
// Refresh any children
|
||||||
|
if(needContentRefresh) {
|
||||||
for(var t=0; t<this.content.length; t++) {
|
for(var t=0; t<this.content.length; t++) {
|
||||||
this.content[t].refreshInDom(changes);
|
this.content[t].refreshInDom(changes);
|
||||||
}
|
}
|
||||||
|
@ -10,3 +10,6 @@ And here's another slider that contains a video, with the state stored in VideoS
|
|||||||
|
|
||||||
And here's a MiniSlider that works with text, rather than a separate tiddler.
|
And here's a MiniSlider that works with text, rather than a separate tiddler.
|
||||||
<<slider state:MiniSlider label:"Click me!" content:"This is the //content// of the slider. The state is stored in MiniSlider">>
|
<<slider state:MiniSlider label:"Click me!" content:"This is the //content// of the slider. The state is stored in MiniSlider">>
|
||||||
|
|
||||||
|
And here's a slider that doesn't use a state tiddler:
|
||||||
|
<<slider label:"Click me!" content:"This is the //content// of the slider. The state is not retained.">>
|
||||||
|
Loading…
Reference in New Issue
Block a user