From 987890c085e4a4fe16ef5027579a09dad589b2fd Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Sun, 13 Oct 2013 21:31:00 +0100 Subject: [PATCH] Add button widget --- core/modules/new_widgets/button.js | 149 ++++++++++++++++++++++++ core/modules/new_widgets/link.js | 8 +- core/modules/new_widgets/navigator.js | 12 ++ core/modules/new_widgets/tempwidgets.js | 1 - core/modules/new_widgets/tiddler.js | 4 +- core/ui/PageTemplate.tid | 2 +- core/ui/SideBar.tid | 2 +- core/ui/ViewTemplate.tid | 2 +- themes/tiddlywiki/snowwhite/base.tid | 2 +- 9 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 core/modules/new_widgets/button.js 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
-<$list filter="[list[$:/StoryList]]" history="$:/HistoryList" template="$:/core/ui/ViewTemplate" editTemplate="$:/core/ui/EditTemplate" listview={{$:/view}} itemClass="tw-tiddler-frame"/> +<$list filter="[list[$:/StoryList]]" history="$:/HistoryList" template="$:/core/ui/ViewTemplate" editTemplate="$:/core/ui/EditTemplate" listview={{$:/view}} />
diff --git a/core/ui/SideBar.tid b/core/ui/SideBar.tid index bde6fd168..edfed5b37 100644 --- a/core/ui/SideBar.tid +++ b/core/ui/SideBar.tid @@ -31,7 +31,7 @@ title: $:/core/ui/SideBar
<$reveal type="match" state="$:/state/sideBarTabSet" text="openTab" qualifyTiddlerTitles="yes"> <$list filter="[list[$:/StoryList]]" history="$:/HistoryList" listview="pop" itemClass="tw-menu-list-item tw-open-tiddler-list"> -<$button message="tw-close-tiddler" class="btn-invisible btn-mini">× <$view field="title" format="link"/> +<$button message="tw-close-tiddler" class="btn-invisible btn-mini">× <$link to={{!!title}}><$view field="title"/> <$button message="tw-close-all-tiddlers" class="btn-invisible btn-mini">close all diff --git a/core/ui/ViewTemplate.tid b/core/ui/ViewTemplate.tid index c841b2008..68afa61b9 100644 --- a/core/ui/ViewTemplate.tid +++ b/core/ui/ViewTemplate.tid @@ -1,5 +1,5 @@ title: $:/core/ui/ViewTemplate modifier: JeremyRuston -
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/ViewTemplate]] [!is[shadow]!has[draft.of]tag[$:/tags/ViewTemplate]]" hackTemplate=true/> +
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/ViewTemplate]] [!is[shadow]!has[draft.of]tag[$:/tags/ViewTemplate]]" hackTemplate=true/>
diff --git a/themes/tiddlywiki/snowwhite/base.tid b/themes/tiddlywiki/snowwhite/base.tid index 2623df74a..00e9c94df 100644 --- a/themes/tiddlywiki/snowwhite/base.tid +++ b/themes/tiddlywiki/snowwhite/base.tid @@ -490,7 +490,7 @@ a.tw-tiddlylink-external { float: right; } -.tw-tiddler-controls .tw-button { +.tw-tiddler-controls button { margin: 0 0 0 5px; vertical-align: baseline; }