mirror of https://gitlab.com/octtspacc/OcttKB
247 lines
7.6 KiB
JavaScript
247 lines
7.6 KiB
JavaScript
|
/*\
|
|||
|
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 tiddler’s 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;
|
|||
|
|
|||
|
})();
|