diff --git a/core/modules/new_widgets/button.js b/core/modules/new_widgets/button.js
new file mode 100644
index 000000000..ab8988632
--- /dev/null
+++ b/core/modules/new_widgets/button.js
@@ -0,0 +1,149 @@
+/*\
+title: $:/core/modules/new_widgets/button.js
+type: application/javascript
+module-type: new_widget
+
+Button widget
+
+\*/
+(function(){
+
+/*jslint node: true, browser: true */
+/*global $tw: false */
+"use strict";
+
+var Widget = require("$:/core/modules/new_widgets/widget.js").widget;
+
+var ButtonWidget = function(parseTreeNode,options) {
+ this.initialise(parseTreeNode,options);
+};
+
+/*
+Inherit from the base widget class
+*/
+ButtonWidget.prototype = new Widget();
+
+/*
+Render this widget into the DOM
+*/
+ButtonWidget.prototype.render = function(parent,nextSibling) {
+ var self = this;
+ // Remember parent
+ this.parentDomNode = parent;
+ // Compute attributes and execute state
+ this.computeAttributes();
+ this.execute();
+ // Create element
+ var domNode = this.document.createElement("button");
+ // Assign classes
+ var classes = this["class"].split(" ") || [];
+ if(this.set && this.setTo && this.selectedClass) {
+ if(this.isSelected()) {
+ classes.push(this.selectedClass.split(" "));
+ }
+ }
+ domNode.className = classes.join(" ");
+ // Add a click event handler
+ domNode.addEventListener("click",function (event) {
+ var handled = false;
+ if(self.message) {
+ self.dispatchMessage(event);
+ handled = true;
+ }
+ if(self.popup) {
+ self.triggerPopup(event);
+ handled = true;
+ }
+ if(self.set) {
+ self.setTiddler();
+ handled = true;
+ }
+ if(handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ return handled;
+ },false);
+ // Insert element
+ parent.insertBefore(domNode,nextSibling);
+ this.renderChildren(domNode,null);
+ this.domNodes.push(domNode);
+};
+
+ButtonWidget.prototype.isSelected = function() {
+ var title = this.set;
+ if(this.qualifyTiddlerTitles) {
+ title = title + "-" + this.getStateQualifier();
+ }
+ var tiddler = this.wiki.getTiddler(title);
+ return tiddler ? tiddler.fields.text === this.setTo : false;
+};
+
+ButtonWidget.prototype.dispatchMessage = function(event) {
+ this.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable("tiddlerTitle")});
+};
+
+ButtonWidget.prototype.triggerPopup = function(event) {
+ var title = this.popup;
+ if(this.qualifyTiddlerTitles) {
+ title = title + "-" + this.getStateQualifier();
+ }
+ $tw.popup.triggerPopup({
+ domNode: this.domNodes[0],
+ title: title,
+ wiki: this.wiki
+ });
+};
+
+ButtonWidget.prototype.setTiddler = function() {
+ var title = this.set;
+ if(this.qualifyTiddlerTitles) {
+ title = title + "-" + this.getStateQualifier();
+ }
+ var tiddler = this.wiki.getTiddler(title);
+ this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: title, text: this.setTo}));
+};
+
+/*
+Compute the internal state of the widget
+*/
+ButtonWidget.prototype.execute = function() {
+ // Get attributes
+ this.message = this.getAttribute("message");
+ this.param = this.getAttribute("param");
+ this.set = this.getAttribute("set");
+ this.setTo = this.getAttribute("setTo");
+ this.popup = this.getAttribute("popup");
+ this.hover = this.getAttribute("hover");
+ this.qualifyTiddlerTitles = this.getAttribute("qualifyTiddlerTitles");
+ this["class"] = this.getAttribute("class","");
+ this.selectedClass = this.getAttribute("selectedClass");
+ // Make child widgets
+ this.makeChildWidgets();
+};
+
+/*
+Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
+*/
+ButtonWidget.prototype.refresh = function(changedTiddlers) {
+ var changedAttributes = this.computeAttributes();
+ if(changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.qualifyTiddlerTitles || changedAttributes["class"] || changedAttributes.selectedClass) {
+ this.refreshSelf();
+ return true;
+ }
+ return this.refreshChildren(changedTiddlers);
+};
+
+/*
+Remove any DOM nodes created by this widget or its children
+*/
+ButtonWidget.prototype.removeChildDomNodes = function() {
+ $tw.utils.each(this.domNodes,function(domNode) {
+ domNode.parentNode.removeChild(domNode);
+ });
+ this.domNodes = [];
+};
+
+exports.button = ButtonWidget;
+
+})();
diff --git a/core/modules/new_widgets/link.js b/core/modules/new_widgets/link.js
index 6ad90887a..7c74d3c5d 100755
--- a/core/modules/new_widgets/link.js
+++ b/core/modules/new_widgets/link.js
@@ -58,13 +58,7 @@ LinkWidget.prototype.render = function(parent,nextSibling) {
type: "tw-navigate",
navigateTo: self.to,
navigateFromNode: self,
- navigateFromClientRect: {
- top: bounds.top,
- left: bounds.left,
- width: bounds.width,
- right: bounds.right,
- bottom: bounds.bottom,
- height: bounds.height
+ navigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height
}
});
event.preventDefault();
diff --git a/core/modules/new_widgets/navigator.js b/core/modules/new_widgets/navigator.js
index cc7122c5e..448ce29a2 100755
--- a/core/modules/new_widgets/navigator.js
+++ b/core/modules/new_widgets/navigator.js
@@ -115,6 +115,18 @@ NavigatorWidget.prototype.handleNavigateEvent = function(event) {
return false;
};
+// Close a specified tiddler
+NavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {
+ this.getStoryList();
+ // Look for tiddlers with this title to close
+ var slot = this.findTitleInStory(event.tiddlerTitle,-1);
+ if(slot !== -1) {
+ this.storyList.splice(slot,1);
+ this.saveStoryList();
+ }
+ return false;
+};
+
exports.navigator = NavigatorWidget;
})();
diff --git a/core/modules/new_widgets/tempwidgets.js b/core/modules/new_widgets/tempwidgets.js
index c3413bfaa..c5bd3ab2f 100755
--- a/core/modules/new_widgets/tempwidgets.js
+++ b/core/modules/new_widgets/tempwidgets.js
@@ -14,7 +14,6 @@ Temporary shim widgets
var Widget = require("$:/core/modules/new_widgets/widget.js").widget;
-exports.button = Widget;
exports.linkcatcher = Widget;
exports.setstyle = Widget;
exports["import"] = Widget;
diff --git a/core/modules/new_widgets/tiddler.js b/core/modules/new_widgets/tiddler.js
index a892ad87b..3aacef3e0 100755
--- a/core/modules/new_widgets/tiddler.js
+++ b/core/modules/new_widgets/tiddler.js
@@ -42,8 +42,9 @@ Compute the internal state of the widget
TiddlerWidget.prototype.execute = function() {
// Get our parameters
this.tiddlerTitle = this.getAttribute("title","");
- // Set context variable
+ // Set context variables
this.setVariable("tiddlerTitle",this.tiddlerTitle);
+ this.setVariable("tiddlerMissing",this.wiki.tiddlerExists(this.tiddlerTitle) ? "tw-tiddler-exists" : "tw-tiddler-missing");
// Construct the child widgets
this.makeChildWidgets();
};
@@ -65,7 +66,6 @@ TiddlerWidget.prototype.refresh = function(changedTiddlers) {
Handle a tw-navigate event
*/
TiddlerWidget.prototype.handleNavigateEvent = function(event) {
-console.log("Setting navigateFromTitle to",this.tiddlerTitle)
event.navigateFromTitle = this.tiddlerTitle;
return true;
};
diff --git a/core/ui/PageTemplate.tid b/core/ui/PageTemplate.tid
index 10a458884..c2c37dce7 100644
--- a/core/ui/PageTemplate.tid
+++ b/core/ui/PageTemplate.tid
@@ -26,7 +26,7 @@ title: $:/core/ui/PageTemplate