OcttKB/Wiki/plugins/details/$__plugins_telmiger_details...

247 lines
7.6 KiB
JavaScript
Raw Normal View History

2023-02-28 12:07:24 +01:00
/*\
title: $:/plugins/telmiger/details/details.js
type: application/javascript
module-type: widget
Details widget v 0.8
Will output an HTML 5 <details> section including a <summary>
```
<details>
<summary>This sums it up</summary>
All the details follow here.
</details>
```
|Parameter |Description |h
|summary |Optional text to display as summary. Wins over field (see below). |
|open |Optional initial state, set to "open" to show details on load. Defaults to "". |
|state |An optional TextReference containing the state. Wins over open. |
|field |Optionally, the summary is taken from the field with this name in a given tiddler. Defaults to "title". |
|tiddler |Optional title of a tiddler to watch, connected to field. Defaults to current tiddler. |
|class |Optional CSS classes to be assigned to the details tag. |
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var DetailsWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
DetailsWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
DetailsWidget.prototype.render = function(parent,nextSibling) {
// Save the parent dom node
this.parentDomNode = parent;
// Compute attributes
this.computeAttributes();
// Execute logic
this.execute();
// Create elements
this.detailsDomNode = this.document.createElement("details");
if(this.detailsClass !== "") {
// this.detailsClass += " ";
// this.detailsClass += "tc-details";
this.detailsDomNode.setAttribute("class",this.detailsClass);
}
if(this.detailsOpen == "open") {
this.detailsDomNode.setAttribute("open","open");
}
if(this.detailsSummary !== "") {
this.summaryDomNode = this.document.createElement("summary");
// this.summaryDomNode.setAttribute("class","tc-summary");
this.detailsDomNode.appendChild(this.summaryDomNode);
this.summaryDomNode.appendChild(this.document.createTextNode(this.detailsSummary));
}
// register an event listener
/* Maybe this can be reactivated later, see below.
if(this.detailsStateTitle) {
$tw.utils.addEventListeners(this.detailsDomNode,[
{name: "toggle", handlerObject: this, handlerMethod: "handleToggleEvent"},
]);
}
*/
// As iOS mobile browsers lack support of toggle events on details
// we emulate the toggle event using click
if(this.detailsStateTitle && this.summaryDomNode) {
$tw.utils.addEventListeners(this.summaryDomNode,[
{name: "click", handlerObject: this, handlerMethod: "handleToggleEvent"},
]);
} else {
if(this.detailsStateTitle) {
$tw.utils.addEventListeners(this.detailsDomNode,[
{name: "click", handlerObject: this, handlerMethod: "handleToggleEvent"},
]);
}
}
// Insert the details into the DOM and render any children
this.parentDomNode.insertBefore(this.detailsDomNode,nextSibling);
this.renderChildren(this.detailsDomNode,null);
this.domNodes.push(this.detailsDomNode);
};
/*
Retrieve the value of the summary
*/
DetailsWidget.prototype.getSummary = function() {
var summary = "";
if(this.summaryTitle === "Tiddler not found" && this.summaryField === "") {
// nothing defined: leave empty
summary = "";
} else {
// tiddler defined? use defined field or title
if(this.myTiddler) {
if(this.summaryField === "title" || this.summaryField === "") {
summary = this.summaryTitle;
} else {
if(this.summaryField === "text") {
// getTiddlerText() triggers lazy loading of skinny tiddlers
summary = this.wiki.getTiddlerText(this.summaryTitle);
} else {
summary = this.myTiddler.fields[this.summaryField];
}
}
} else {
if(this.summaryField !== "" && this.summaryField !== "text") {
// try defined field in current tiddler
var tiddler = this.wiki.getTiddler(this.getVariable("currentTiddler"));
summary = tiddler.fields[this.summaryField];
} else {
summary = "";
}
}
}
return summary;
};
/*
Retrieve the value of the state text reference
*/
DetailsWidget.prototype.getStateFromReference = function() {
var state = this.detailsStateTitle ? this.wiki.getTextReference(this.detailsStateTitle,"",this.getVariable("currentTiddler")) : "";
return state;
};
/*
Check all open signals, state fields/tiddlers get priority
*/
DetailsWidget.prototype.getOpenState = function() {
var result = "";
if((this.detailsOpenDefault !== "" && this.detailsOpenDefault !== "no")
|| this.detailsState === "open") {
result = "open";
}
if(this.detailsStateTitle !=="" && this.detailsState !== "open") {
result = "";
}
return result;
};
/*
Update the state text reference after click event
*/
DetailsWidget.prototype.updateState = function(openState) {
var fieldValue = "false";
var currentTiddler = this.getVariable("currentTiddler");
// get the title for the (existing/new) tiddler
var tr = $tw.utils.parseTextReference(this.detailsStateTitle);
var tidTitle = tr.title || currentTiddler;
// is it an existing state tiddler?
var isStateTiddler = (tr.title === this.detailsStateTitle);
var hasStateTiddler = this.wiki.tiddlerExists(tr.title);
var currentStateTiddler = (tr.title === currentTiddler);
if(isStateTiddler || hasStateTiddler || (currentStateTiddler && tr.field !== "text")) {
// Set the state field (but never overwrite the current tiddlers text field
this.wiki.setText(tidTitle,tr.field,tr.index,openState);
} else {
if(!hasStateTiddler && tidTitle !== currentTiddler) {
this.createTiddler(tidTitle);
this.wiki.setText(tidTitle,tr.field,tr.index,openState);
} else {
console.log ("Something went wrong in updateState");
}
}
};
/*
Create a tiddler with a title only
*/
DetailsWidget.prototype.createTiddler = function(tidTitle) {
this.wiki.addTiddler(new $tw.Tiddler(
this.wiki.getCreationFields(),
this.wiki.getModificationFields(),
{
title: tidTitle,
tags: []
}
));
};
/*
Set openState according to click
*/
DetailsWidget.prototype.handleToggleEvent = function(event) {
// check if an open attribute is present
var newState = this.detailsDomNode.open ? "" : "open";
// update only, if the node has a new state
if(newState !== this.detailsState) {
this.updateState(newState);
}
};
/*
Compute the internal state of the widget
*/
DetailsWidget.prototype.execute = function() {
// Get the parameters from the attributes
var tryTiddler = this.getAttribute("tiddler");
this.myTiddler = this.wiki.getTiddler(tryTiddler);
this.summaryTitle = this.myTiddler ? tryTiddler : "Tiddler not found";
this.summaryField = this.getAttribute("field","");
this.detailsSummary = this.getAttribute("summary") || this.getSummary();
this.detailsStateTitle = this.getAttribute("state","");
this.detailsState = this.getStateFromReference();
this.detailsOpenDefault = this.getAttribute("open","");
this.detailsOpen = this.getOpenState();
this.detailsClass = this.getAttribute("class","");
// Construct the child widgets
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
DetailsWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.summary || changedAttributes.state || changedAttributes.open || changedAttributes["class"]) {
this.refreshSelf();
return true;
} else {
var refreshed = false;
var testState = this.getStateFromReference();
if(testState !== this.detailsState) {
// state change
this.refreshSelf();
refreshed = true;
}
return this.refreshChildren(changedTiddlers) || refreshed;
}
};
exports.details = DetailsWidget;
})();