<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see [[AdvancedOptions]]
<<importTiddlers>>
<<tiddler TaskManagerPlugin##About>>
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Add checkboxes to your tiddler content|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content.  Checkbox states are preserved by:
* by setting/removing tags on specified tiddlers,
* or, by setting custom field values on specified tiddlers,
* or, by saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler content (deprecated)
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data.  In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Documentation
>see [[CheckboxPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global "window.place" to current checkbox element when processing checkbox clicks.  This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)".  Also, wrap handlers in "function()" so "return" can be used within handler code.
|please see [[CheckboxPluginInfo]] for additional revision details|
2005.12.07 [0.9.0] initial BETA release
<<<
!!!!!Code
***/
//{{{
version.extensions.CheckboxPlugin = {major: 2, minor: 4, revision:0 , date: new Date(2008,1,5)};
//}}}
//{{{
config.checkbox = { refresh: { tagged:true, tagging:true, container:true } };
config.formatters.push( {
	name: "checkbox",
	match: "\\[[xX_ ][\\]\\=\\(\\{]",
	lookahead: "\\[([xX_ ])(=[^\\s\\(\\]{]+)?(\\([^\\)]*\\))?({[^}]*})?({[^}]*})?({[^}]*})?\\]",
	handler: function(w) {
		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
		lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			// get params
			var checked=(lookaheadMatch[1].toUpperCase()=="X");
			var id=lookaheadMatch[2];
			var target=lookaheadMatch[3];
			if (target) target=target.substr(1,target.length-2).trim(); // trim off parentheses
			var fn_init=lookaheadMatch[4];
			var fn_clickBefore=lookaheadMatch[5];
			var fn_clickAfter=lookaheadMatch[6];
			var tid=story.findContainingTiddler(w.output);  if (tid) tid=tid.getAttribute("tiddler");
			var srctid=w.tiddler?w.tiddler.title:null;
			config.macros.checkbox.create(w.output,tid,srctid,w.matchStart+1,checked,id,target,config.checkbox.refresh,fn_init,fn_clickBefore,fn_clickAfter);
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
		}
	}
} );
config.macros.checkbox = {
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!(tiddler instanceof Tiddler)) { // if no tiddler passed in try to find one
			var here=story.findContainingTiddler(place);
			if (here) tiddler=store.getTiddler(here.getAttribute("tiddler"))
		}
		var srcpos=0; // "inline X" not applicable to macro syntax
		var target=params.shift(); if (!target) target="";
		var defaultState=params[0]=="checked"; if (defaultState) params.shift();
		var id=params.shift(); if (id && !id.length) id=null;
		var fn_init=params.shift(); if (fn_init && !fn_init.length) fn_init=null;
		var fn_clickBefore=params.shift();
		if (fn_clickBefore && !fn_clickBefore.length) fn_clickBefore=null;
		var fn_clickAfter=params.shift();
		if (fn_clickAfter && !fn_clickAfter.length) fn_clickAfter=null;
		var refresh={ tagged:true, tagging:true, container:false };
		this.create(place,tiddler.title,tiddler.title,0,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter);
	},
	create: function(place,tid,srctid,srcpos,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter) {
		// create checkbox element
		var c = document.createElement("input");
		c.setAttribute("type","checkbox");
		c.onclick=this.onClickCheckbox;
		c.srctid=srctid; // remember source tiddler
		c.srcpos=srcpos; // remember location of "X"
		c.container=tid; // containing tiddler (may be null if not in a tiddler)
		c.tiddler=tid; // default target tiddler 
		c.refresh = {};
		c.refresh.container = refresh.container;
		c.refresh.tagged = refresh.tagged;
		c.refresh.tagging = refresh.tagging;
		place.appendChild(c);
		// set default state
		c.checked=defaultState;
		// track state in config.options.ID
		if (id) {
			c.id=id.substr(1); // trim off leading "="
			if (config.options[c.id]!=undefined)
				c.checked=config.options[c.id];
			else
				config.options[c.id]=c.checked;
		}
		// track state in (tiddlername|tagname) or (fieldname@tiddlername)
		if (target) {
			var pos=target.indexOf("@");
			if (pos!=-1) {
				c.field=pos?target.substr(0,pos):"checked"; // get fieldname (or use default "checked")
				c.tiddler=target.substr(pos+1); // get specified tiddler name (if any)
				if (!c.tiddler || !c.tiddler.length) c.tiddler=tid; // if tiddler not specified, default == container
				if (store.getValue(c.tiddler,c.field)!=undefined)
					c.checked=(store.getValue(c.tiddler,c.field)=="true"); // set checkbox from saved state
			} else {
				var pos=target.indexOf("|"); if (pos==-1) var pos=target.indexOf(":");
				c.tag=target;
				if (pos==0) c.tag=target.substr(1); // trim leading "|" or ":"
				if (pos>0) { c.tiddler=target.substr(0,pos); c.tag=target.substr(pos+1); }
				if (!c.tag.length) c.tag="checked";
				var t=store.getTiddler(c.tiddler);
				if (t && t.tags)
					c.checked=t.isTagged(c.tag); // set checkbox from saved state
			}
		}
		// trim off surrounding { and } delimiters from init/click handlers
		if (fn_init) c.fn_init="(function(){"+fn_init.trim().substr(1,fn_init.length-2)+"})()";
		if (fn_clickBefore) c.fn_clickBefore="(function(){"+fn_clickBefore.trim().substr(1,fn_clickBefore.length-2)+"})()";
		if (fn_clickAfter) c.fn_clickAfter="(function(){"+fn_clickAfter.trim().substr(1,fn_clickAfter.length-2)+"})()";
		c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie
	},
	onClickCheckbox: function(event) {
		window.place=this;
		if (this.init && this.fn_init) // custom function hook to set initial state (run only once)
			{ try { eval(this.fn_init); } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }
		if (!this.init && this.fn_clickBefore) // custom function hook to override changes in checkbox state
			{ try { eval(this.fn_clickBefore) } catch(e) { displayMessage("Checkbox onClickBefore error: "+e.toString()); } }
		if (this.id)
			// save state in config AND cookie (only when ID starts with 'chk')
			{ config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }
		if (this.srctid && this.srcpos>0 && (!this.id || this.id.substr(0,3)!="chk") && !this.tag && !this.field) {
			// save state in tiddler content only if not using cookie, tag or field tracking
			var t=store.getTiddler(this.srctid); // put X in original source tiddler (if any)
			if (t && this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed
				t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);
				if (!story.isDirty(t.title)) story.refreshTiddler(t.title,null,true);
				store.setDirty(true);
			}
		}
		if (this.field) {
			if (this.checked && !store.tiddlerExists(this.tiddler))
				store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
			// set the field value in the target tiddler
			store.setValue(this.tiddler,this.field,this.checked?"true":"false");
			// DEBUG: displayMessage(this.field+"@"+this.tiddler+" is "+this.checked);
		}
		if (this.tag) {
			if (this.checked && !store.tiddlerExists(this.tiddler))
				store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
			var t=store.getTiddler(this.tiddler);
			if (t) {
				var tagged=(t.tags && t.tags.indexOf(this.tag)!=-1);
				if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }
				if (!this.checked && tagged) { t.tags.splice(t.tags.indexOf(this.tag),1); store.setDirty(true); }
			}
			// if tag state has been changed, update display of corresponding tiddlers (unless they are in edit mode...)
			if (this.checked!=tagged) {
				if (this.refresh.tagged) {
					if (!story.isDirty(this.tiddler)) // the TAGGED tiddler in view mode
						story.refreshTiddler(this.tiddler,null,true); 
					else // the TAGGED tiddler in edit mode (with tags field)
						config.macros.checkbox.refreshEditorTagField(this.tiddler,this.tag,this.checked);
				}
				if (this.refresh.tagging)
					if (!story.isDirty(this.tag)) story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler
			}
		}
		if (!this.init && this.fn_clickAfter) // custom function hook to react to changes in checkbox state
			{ try { eval(this.fn_clickAfter) } catch(e) { displayMessage("Checkbox onClickAfter error: "+e.toString()); } }
		// refresh containing tiddler (but not during initial rendering, or we get an infinite loop!) (and not when editing container)
		if (!this.init && this.refresh.container && this.container!=this.tiddler)
			if (!story.isDirty(this.container)) story.refreshTiddler(this.container,null,true); // the tiddler CONTAINING the checkbox
		return true;
	},
	refreshEditorTagField: function(title,tag,set) {
		var tagfield=story.getTiddlerField(title,"tags");
		if (!tagfield||tagfield.getAttribute("edit")!="tags") return; // if no tags field in editor (i.e., custom template)
		var tags=tagfield.value.readBracketedList();
		if (tags.contains(tag)==set) return; // if no change needed
		if (set) tags.push(tag); // add tag
		else tags.splice(tags.indexOf(tag),1); // remove tag
		for (var t=0;t<tags.length;t++) tags[t]=String.encodeTiddlyLink(tags[t]);
		tagfield.value=tags.join(" "); // reassemble tag string (with brackets as needed)
		return;
	}
}
//}}}
Task: Clean up + ELS Ideas
Reminder: <<newReminder>>
!!!Items
#
#
!!!Notes
> 1) I have firebug, but have no idea how to use it or what to look for,
> did you see the error while running the macro?

First step: when an error in code occurs, the little green bug (lower
right corner of browser status bar) changes to a red bug.  Click on
that to see the error message (if any)

I've never actually read any documentation for FireBug... but I'm sure
there is some.

> 2) What would be a good reference for proper K&R identation?

http://en.wikipedia.org/wiki/Indent_style

I tend to use either K&R or 1TBS style, along with my own 'line
saving' variations where I will sometimes put multiple statements on a
single line if they are all part of a single 'phrase', e.g., these
statements:
   for (var i=0; i<list.length; i++) if (...list[i]...) results.push
(list[i]);
effectively say: "select items from list and copy to results".

-e 
> 3) How can I invoke a refresh of the tiddler containing the macro
> properly at the end of the plugin?

In general, the line of code that was getting the error *is* the
correct way to refresh the "current" tiddler.  However, this code
depends upon access to an appropriate "DOM element context variable",
either 'place' (provided to the macro handler by the TW core) or
'this' (provided by the browser to the onclick event handler).

Unfortunately, your code is wrapped in an anonymous function which
prevents access to either of those variables and, due to the current
indentation (or lack thereof), it's difficult to see exactly what to
re-write.  Still, I think it's possible to simplify and clean up the
code so that the right variable(s) are available at the right time,
and then you will be able to restore the call to refreshTiddler(...)

> 4) Finally can I disable / enable the autosave as part of the plugin?

As part of your onclick handler, you can clear the autosave flag
before you modify the tiddlers and then restore the flag and invoke
autoSaveChanges() afterwards, like this:

   config.options.chkAutosave=false;
   ... insert code here ...
   config.options.chkAutosave=true;
   autoSaveChanges();

-e 
!!!Due
<<deleteCompleted daysOld:0 title:'Delete All Completed Items'>>
Task: Convert --[[fETTasks]]-- & [[ProjectTemplate]] to pure JS
Reminder: <<newReminder>>
!!!Items
#
#
!!!Notes
[X]Need to Convert [[fETTasks]] (and Rename to [[TaskTabs]])
[_]Need to Convert [[ProjectTemplate]]
!!!Due
<<reminder year:2009 month:5 day:1 title:"Post Questions / Example in TW Group" >>
Task: Delete Project Button Including Containing Tasks
Reminder: <<newReminder>>
!!!Items
#
#
!!!Notes
Trying to use DeleteAllTaggedPlugin for this, currently deletes all items of tag, but not actual tag tiddler. Variant?
!!!Due
[[Download Javascript Task Manager|http://www.strm.us/tw/examples_twgg/download.php?file=ijstaskmanager.html]]

[[Download fET Task Manager|http://www.strm.us/tw/examples_twgg/download.php?file=fettaskmanager.html]]
Task: Add Shadow or create function for TaskTabs & ProjectTemplate
Reminder: <<newReminder>>
!!!Items
#
#
!!!Notes
Started TaskManagerPlugin having problems with config.shadowTiddlers & fET (converting fET into Pure JS for v2)

!!!Due
<<reminder year:2009 month:5 day:15 title:"Post Questions / Example in TW Dev Group" >>
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.4|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 3, date: new Date(2008,6,11)};

config.formatters.push( {
	name: "inlineJavascript",
	match: "\\<script",
	lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",

	handler: function(w) {
		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
		lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var src=lookaheadMatch[1];
			var label=lookaheadMatch[2];
			var tip=lookaheadMatch[3];
			var key=lookaheadMatch[4];
			var show=lookaheadMatch[5];
			var code=lookaheadMatch[6];
			if (src) { // load a script library
				// make script tag, set src, add to body to execute, then remove for cleanup
				var script = document.createElement("script"); script.src = src;
				document.body.appendChild(script); document.body.removeChild(script);
			}
			if (code) { // there is script code
				if (show) // show inline script code in tiddler output
					wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
				if (label) { // create a link to an 'onclick' script
					// add a link, define click handler, save code in link (pass 'place'), set link attributes
					var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
					var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
					link.code="function _out(place){"+fixup+"\n};_out(this);"
					link.tiddler=w.tiddler;
					link.onclick=function(){
						this.bufferedHTML="";
						try{ var r=eval(this.code);
							if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
								var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
							if(this.bufferedHTML.length)
								s.innerHTML=this.bufferedHTML;
							if((typeof(r)==="string")&&r.length) {
								wikify(r,s,null,this.tiddler);
								return false;
							} else return r!==undefined?r:false;
						} catch(e){alert(e.description||e.toString());return false;}
					};
					link.setAttribute("title",tip||"");
					var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
					URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
					URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
					link.setAttribute("href",URIcode);
					link.style.cursor="pointer";
					if (key) link.accessKey=key.substr(0,1); // single character only
				}
				else { // run inline script code
					var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
					var c="function _out(place){"+fixup+"\n};_out(w.output);";
					try	 { var out=eval(c); }
					catch(e) { out=e.description?e.description:e.toString(); }
					if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
				}
			}
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
		}
	}
} )
//}}}

// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
	if(limit > 0) text = text.substr(0,limit);
	var wikifier = new Wikifier(text,formatter,null,tiddler);
	return wikifier.wikifyPlain();
}
//}}}

// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
[[About this Project|About]]
[[Task Manager]]
<script>
 if(config.macros.reminders){
	return ("[[Reminders]]"+"\n")}
</script><script>
if (config.commands.deleteTiddler.sendToTrash){
	return("<<emptyTrash>>")
} else {
	return ("[[Completed]]")
}
</script>
<hr>
{{small{<script>
javascript:(function(){document.write('\nLast modified: '+document.lastModified);})()
</script>}}}
<hr>
Archive:
[[Task Manager v1.0.4|fETTaskManager.html]]
/***
|Name|MatchTagsPlugin|
|Source|http://www.TiddlyTools.com/#MatchTagsPlugin|
|Documentation|http://www.TiddlyTools.com/#MatchTagsPluginInfo|
|Version|2.0.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|'tag matching' with full boolean expressions (AND, OR, NOT, and nested parentheses)|
!!!!!Documentation
> see [[MatchTagsPluginInfo]]
!!!!!Revisions
<<<
2008.09.04 [2.0.0] added "report" and "panel" options to generate formatted results and store in a tiddler.  Also, added config.macros.matchTags.formatList(place,fmt,sep) API to return formatted output for use with other plugins/scripts
| please see [[MatchTagsPluginInfo]] for additional revision details |
2008.02.28 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.MatchTagsPlugin= {major: 2, minor: 0, revision: 0, date: new Date(2008,9,4)};

// store.getMatchingTiddlers() processes boolean expressions for tag matching
//    sortfield (optional) sets sort order for tiddlers - default=title
//    tiddlers (optional) use alternative set of tiddlers (instead of current store)
TiddlyWiki.prototype.getMatchingTiddlers = function(tagexpr,sortfield,tiddlers) {

	var debug=config.options.chkDebug; // abbreviation
	var cmm=config.macros.matchTags; // abbreviation
	var r=[]; // results are an array of tiddlers
	var tids=tiddlers||store.getTiddlers(sortfield||"title");
	if (tiddlers && sortfield) store.sortTiddlers(tids,sortfield);
	if (debug) displayMessage(cmm.msg1.format([tids.length]));

	// try simple lookup to quickly find single tags or tags that
	// contain boolean operators as literals, e.g. "foo and bar"
	for (var t=0; t<tids.length; t++)
		if (tids[t].isTagged(tagexpr)) r.pushUnique(tids[t]);
	if (r.length) {
		if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
		return r;
	}
	
	// convert expression into javascript code with regexp tests,
	// so that "tag1 AND ( tag2 OR NOT tag3 )" becomes
	// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag3\~/.test(...) )"

	// normalize whitespace, tokenize operators, delimit with "~"
	var c=tagexpr.trim(); // remove leading/trailing spaces
	c = c.replace(/\s+/ig," "); // reduce multiple spaces to single spaces
	c = c.replace(/\(\s?/ig,"~(~"); // open parens
	c = c.replace(/\s?\)/ig,"~)~"); // close parens
	c = c.replace(/(\s|~)?&&(\s|~)?/ig,"~&&~"); // &&
	c = c.replace(/(\s|~)AND(\s|~)/ig,"~&&~"); // AND
	c = c.replace(/(\s|~)?\|\|(\s|~)?/ig,"~||~"); // ||
	c = c.replace(/(\s|~)OR(\s|~)/ig,"~||~"); // OR
	c = c.replace(/(\s|~)?!(\s|~)?/ig,"~!~"); // !
	c = c.replace(/(^|~|\s)NOT(\s|~)/ig,"~!~"); // NOT
	c = c.replace(/(^|~|\s)NOT~\(/ig,"~!~("); // NOT(
	// change tag terms to regexp tests
	var terms=c.split("~"); for (var i=0; i<terms.length; i++) { var t=terms[i];
		if (/(&&)|(\|\|)|[!\(\)]/.test(t) || t=="") continue; // skip operators/parens/spaces
		if (t==config.macros.matchTags.untaggedKeyword)
			terms[i]="tiddlertags=='~~'"; // 'untagged' tiddlers
		else
			terms[i]="/\\~"+t+"\\~/.test(tiddlertags)";
	}
	c=terms.join(" ");
	if (debug) { displayMessage(cmm.msg2.format([tagexpr])); displayMessage(cmm.msg3.format([c])); }

	// scan tiddlers for matches
	for (var t=0; t<tids.length; t++) {
	 	// assemble tags from tiddler into string "~tag1~tag2~tag3~"
		var tiddlertags = "~"+tids[t].tags.join("~")+"~";
		try { if(eval(c)) r.push(tids[t]); } // test tags
		catch(e) { // error in test
			displayMessage(cmm.msg2.format([tagexpr]));
			displayMessage(cmm.msg3.format([c]));
			displayMessage(e.toString());
			break; // skip remaining tiddlers
		}
	}
	if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
	return r;
}
//}}}
//{{{
config.macros.matchTags = {
	msg1: "scanning %0 input tiddlers",
	msg2: "looking for '%0'",
	msg3: "using expression: '%0'",
	msg4: "found %0 tiddlers matching '%1'",
	noMatch: "no matching tiddlers",
	untaggedKeyword: "-",



	untaggedLabel: "no tags",
	untaggedPrompt: "show tiddlers with no tags",
	defTiddler: "MatchingTiddlers",
	defFormat: "%0",
	defSeparator: "\n",
	reportHeading: "Found %0 tiddlers tagged with: '{{{%1}}}'\n----\n",
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var mode=params[0]?params[0].toLowerCase():'';
		if (mode=="inline")
			params.shift();
		if (mode=="report" || mode=="panel") {
			params.shift();
			var target=params.shift()||this.defTiddler;
		}
		if (mode=="popup") {
			params.shift();
			if (params[0]&&params[0].substr(0,6)=="label:") var label=params.shift().substr(6);
			if (params[0]&&params[0].substr(0,7)=="prompt:") var prompt=params.shift().substr(7);
		} else {
			var fmt=(params.shift()||this.defFormat).unescapeLineBreaks();
			var sep=(params.shift()||this.defSeparator).unescapeLineBreaks();
		}
		var sortBy="+title";
		if (params[0]&&params[0].substr(0,5)=="sort:") sortBy=params.shift().substr(5);
		var expr = params.join(" ");
		if (mode!="panel" && (!expr||!expr.trim().length)) return;
		if (expr==this.untaggedKeyword)
			{ var label=this.untaggedLabel; var prompt=this.untaggedPrompt };
		switch (mode) {
			case "popup": this.createPopup(place,label,expr,prompt,sortBy); break;
			case "panel": this.createPanel(place,expr,fmt,sep,sortBy,target); break;
			case "report": this.createReport(target,expr,fmt,sep,sortBy); break;
			case "inline": default: this.createInline(place,expr,fmt,sep,sortBy); break;
		}
	},
	formatList: function(tids,fmt,sep) {
		var out=[];
		for (var t=0; t<tids.length; t++) {
			var title="[["+tids[t].title+"]]";
			var who=tids[t].modifier;
			var when=tids[t].modified.toLocaleString();
			var text=tids[t].text;
			var first=tids[t].text.split("\n")[0];
			var desc=store.getTiddlerSlice(tids[t].title,"description");
			desc=desc||store.getTiddlerSlice(tids[t].title,"Description");
			desc=desc||store.getTiddlerText(tids[t].title+"##description");
			desc=desc||store.getTiddlerText(tids[t].title+"##Description");
			out.push(fmt.format([title,who,when,text,first,desc]));
		}
		return out.join(sep);
	},
	createInline: function(place,expr,fmt,sep,sortBy) {
		wikify(this.formatList(store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy),fmt,sep),place);
	},
	createPopup: function(place,label,expr,prompt,sortBy) {
		var btn=createTiddlyButton(place,
			(label||expr).format([expr]),
			(prompt||config.views.wikified.tag.tooltip).format([expr]),
			function(ev){ return config.macros.matchTags.showPopup(this,ev||window.event); });
		btn.setAttribute("sortBy",sortBy);
		btn.setAttribute("expr",expr);
	},
	showPopup: function(here,ev) {
		var p=Popup.create(here); if (!p) return false;
		var tids=store.getMatchingTiddlers(here.getAttribute("expr"));
		store.sortTiddlers(tids,here.getAttribute("sortBy"));
		var list=[]; for (var t=0; t<tids.length; t++) list.push(tids[t].title);
		if (!list.length) createTiddlyText(p,this.noMatch);
		else {
			var b=createTiddlyButton(createTiddlyElement(p,"li"),
				config.views.wikified.tag.openAllText,
				config.views.wikified.tag.openAllTooltip,
				function() {
					var list=this.getAttribute("list").readBracketedList();
					story.displayTiddlers(null,tids);
				});
			b.setAttribute("list","[["+list.join("]] [[")+"]]");
			createTiddlyElement(p,"hr");
		}
		var out=this.formatList(tids," &nbsp;%0&nbsp; ","\n"); wikify(out,p);
		Popup.show(p,false);
		ev.cancelBubble=true;
		if(ev.stopPropagation) ev.stopPropagation();
		return false;
	},
	createReport: function(target,expr,fmt,sep,sortBy) {
		var tids=store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy);
		if (!tids.length) { displayMessage('no matches for: '+expr); return false; }
		var msg=config.messages.overwriteWarning.format([target]);
		if (store.tiddlerExists(target) && !confirm(msg)) return false;
		var out=this.reportHeading.format([tids.length,expr])
		out+=this.formatList(tids,fmt,sep);
		store.saveTiddler(target,target,out,config.options.txtUserName,new Date(),[],{});
		story.closeTiddler(target); story.displayTiddler(null,target);
	},
	createPanel: function(place,expr,fmt,sep,sortBy,tid) {
		var html="<form style='display:inline'><!-- \
			--><input type='text'    name='expr' style='width:55%' title='tag expression'><!-- \
			--><input type='text'    name='fmt'  style='width:10%' title='list item format'><!-- \
			--><input type='text'    name='sep'  style='width:5%'  title='list item separator'><!-- \
			--><input type='text'    name='tid'  style='width:20%' title='target tiddler title'><!-- \
			--><input type='button'  name='go'   style='width:8%'  value='go' onclick=\" \
				var expr=this.form.expr.value; \
				if (!expr.length) { alert('Enter a boolean tag expression'); return false; } \
				var fmt=this.form.fmt.value; \
				if (!fmt.length) { alert('Enter the list item output format'); return false; } \
				var sep=this.form.sep.value.unescapeLineBreaks(); \
				var tid=this.form.tid.value; \
				if (!tid.length) { alert('Enter a target tiddler title'); return false; } \
				config.macros.matchTags.createReport(tid,expr,fmt,sep,'title'); \
				return false;\"> \
			</form>";
		var s=createTiddlyElement(place,"span"); s.innerHTML=html;
		var f=s.getElementsByTagName("form")[0];
		f.expr.value=expr; f.fmt.value=fmt; f.sep.value=sep.escapeLineBreaks(); f.tid.value=tid;
	}
};
//}}}
//{{{
// SHADOW TIDDLER for displaying default panel input form
config.shadowTiddlers.MatchTags="{{smallform{<<matchTags panel>>}}}";
//}}}
//{{{
// TWEAK core filterTiddlers() for enhanced boolean matching in [tag[...]] syntax:
// use getMatchingTiddlers instead getTaggedTiddlers
var fn=TiddlyWiki.prototype.filterTiddlers;
fn=fn.toString().replace(/getTaggedTiddlers/g,"getMatchingTiddlers");
eval("TiddlyWiki.prototype.filterTiddlers="+fn);
//}}}
//{{{
// REDEFINE core handler for enhanced boolean matching in tag:"..." paramifier
// use filterTiddlers() instead of getTaggedTiddlers() to get list of tiddlers.
config.paramifiers.tag = {
	onstart: function(v) {
		var tagged = store.filterTiddlers("[tag["+v+"]]");
		story.displayTiddlers(null,tagged,null,false,null);
	}
};
//}}}
Task: Possibly rewrite plugins to accommodate Refresh after Delete
Reminder: <<newReminder>>
!!!Items
#[[deleteCompletedPlugin]]
#[[deleteAllTaggedPlugin]]
!!!Notes

-e

    3) How can I invoke a refresh of the tiddler containing the macro
    properly at the end of the plugin?


In general, the line of code that was getting the error *is* the
correct way to refresh the "current" tiddler. However, this code
depends upon access to an appropriate "DOM element context variable",
either 'place' (provided to the macro handler by the TW core) or
'this' (provided by the browser to the onclick event handler).

Unfortunately, your code is wrapped in an anonymous function which
prevents access to either of those variables and, due to the current
indentation (or lack thereof), it's difficult to see exactly what to
re-write. Still, I think it's possible to simplify and clean up the
code so that the right variable(s) are available at the right time,
and then you will be able to restore the call to refreshTiddler(...)
!!!Due
Task: Fix new project Button
Reminder: <<newReminder>>
!!!Items
#
#
!!!Notes
Existing New Project button gives (2) prompts - consolidate to one prompt
(both prompts need to have same info in current fET state)
{{{
<<clickify newTiddler
 label:'New Project'
 title:{{prompt('Enter a new project title (Tab Name)','New Project Task')}}
 tag:'fETTasks'
         text:{{
             store.getTiddlerText("ProjectTemplate", "").
  replace(/Project1/g, prompt("Enter Project Tag (No Spaces or special characters)"))
         }}
>>
}}}
!!!Due
<<reminder year:2009 month:2 day:25 title:"please enter a title" >>
Task: Fix Plugins to use K&R Indent styling
Reminder: <<newReminder>>
!!!Items
#[[deleteCompletedPlugin]]
#[[deleteAllTaggedPlugin]]
!!!Notes
K&R style

The K&R style, so-called because it was used in Kernighan and Ritchie's book The C Programming Language, is commonly used in C. It is less common for C++, C#, and others. It keeps the first opening brace on the same line as the control statement, indents the statements within the braces, and puts the closing brace on the same indentation level as the control statement (on a line of its own). Functions, however, are braced distinctly from statements; an opening function brace is placed on the line following the declaration, at the same indentation level as the declaration. This is because in the original C language, argument types needed to be declared on the subsequent line, whereas when no arguments were necessary, the opening brace would not appear in the same line with the function declaration. The opening brace for function declarations is an exception on the basic rule.
{{{
int main(int argc, char *argv[])
{
    ...
    while (x == y) {
        something();
        somethingelse();
        if (some_error)
            do_correct();
        else
            continue_as_usual();
    }
    finalthing();
    ...
}
}}}

Variant: 1TBS

Advocates of this style sometimes refer to it as "The One True Brace Style" (abbreviated as 1TBS or OTBS) because of the precedent set by C (although advocates of other styles have been known to use similarly strong language). The source code of the Unix kernel and Linux kernel is written in this style.

In this style, the constructs that allow insertions of new code lines are on separate lines, and constructs that prohibit insertions are on a single line. This principle is amplified by bracing every if, else, while, etc.—even single-line conditionals—so that insertion of a new line of code anywhere is always "safe".

Advantages of this style are that the beginning brace does not require an extra line by itself; and the ending brace lines up with the statement it conceptually belongs to. One disadvantage of this style is that the ending brace of a block takes up an entire line by itself, which can be partially resolved in if/else blocks and do/while blocks:

{{{
//...
    if (x < 0) {
        printf("Negative");
        negative(x);
    } else {
        printf("Positive");
        positive(x);
    }
}}}
While this style may make it difficult to scan any source code for the opening brace of a block, it is not usually the opening brace itself that is interesting, but rather the controlling statement that introduced the block. It is easy to find the beginning of the block by locating the first line above the closing brace which is indented to the same level.

While Java is often written in Allman or other styles, a significant body of Java code uses a minor variant of the K&R style in which the opening brace is on the same line as the class or method declaration, largely because Sun's original style guides [1][2][3] used this K&R variant, and as a result most of the standard source code for the Java API is written in this style. It is also a popular indent style for ActionScript, JavaScript, along with the Allman style.

It should be noted that The C Programming Language does not explicitly specify this style, though it is followed consistently throughout the book. Of note from the book:

    The position of braces is less important, although people hold passionate beliefs. We have chosen one of several popular styles. Pick a style that suits you, then use it consistently.

!!!Due
<<tabs txtProject1
'Urgent Project1' 'Urgent Project1 Tab' Project1##Urgent
'Pending Project1' 'Pending Project1 Tab' Project1##Pending
'Completed Project1' 'Completed Project1 Tab' Project1##Completed
>>
{{button{<script label="New Task">
 var newTiddler = new Tiddler();
 newTiddler.title = prompt('Enter a new task title','New Project Task');
 newTiddler.tags[0] = "Project1";
 newTiddler.tags[1] = "Task";
 newTiddler.tags[2] = "excludeLists";
 newTiddler.modifier = config.options.txtUserName;
 if(config.macros.reminders){
 newTiddler.text = "Task:\nReminder: <<newReminder>>\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";
 } else {newTiddler.text = "Task:\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";}
 store.addTiddler(newTiddler);
 story.displayTiddler(null,newTiddler.title,DEFAULT_EDIT_TEMPLATE);
 story.focusTiddler(newTiddler.title,"title");
</script>}}} <<deleteAllTagged "Delete this Project" delete>>
@@display:none;"
!!!Urgent
~~Urgent Items~~
<script>
//	var tag=store.getMatchingTiddlers("Project1 && Urgent && ! Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("Project1 && Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Pending
~~Pending Items~~
<script>
//	var tag=store.getMatchingTiddlers("Project1 && ! Urgent && ! Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("Project1 && ! Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Completed
~~Completed Items~~
<script>
//	var tag=store.getMatchingTiddlers("Project1 && Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("Project1 && Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
@@
/***
|''Name:''|ReminderPlugin|
|''Version:''|2.3.10 (Jun 28, 2007)|
|''Source:''|http://remindermacros.tiddlyspot.com|
|''Author:''|Jeremy Sheeley(pop1280 [at] excite [dot] com) Maintainer: simon.baird@gmail.com|
|''Licence:''|[[BSD open source license]]|
|''Macros:''|reminder, showreminders, displayTiddlersWithReminders, newReminder|
|''TiddlyWiki:''|2.0+|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|

!Description
This plugin provides macros for tagging a date with a reminder.  Use the {{{reminder}}} macro to do this.  The {{{showReminders}}} and {{{displayTiddlersWithReminder}}} macros automatically search through all available tiddlers looking for upcoming reminders.

!Installation
* Create a new tiddler in your tiddlywiki titled ReminderPlugin and give it the {{{systemConfig}}} tag.  The tag is important because it tells TW that this is executable code.
* Double click this tiddler, and copy all the text from the tiddler's body.
* Paste the text into the body of the new tiddler in your TW.
* Save and reload your TW.
* You can copy some examples into your TW as well.  See [[ReminderExamples]], [[Holidays]], [[showReminders]] and [[Personal Reminders]]

!Syntax:
|>|See [[ReminderSyntax]] and [[showRemindersSyntax]]|

!Revision history
* v2.3.10 (Jun 28, 2007)
** Removed window.story = window backwards compatibility hacks since they were breaking TW 2.2
* v2.3.9 (Apr 26, 2007)
** allow bracketed list format in tags param lets you use tags with spaces
* v2.3.8 (Mar 9, 2006)
**Bug fix: A global variable had snuck in, which was killing FF 1.5.0.1
**Feature: You can now use TIDDLER and TIDDLERNAME in a regular reminder format
* v2.3.6 (Mar 1, 2006)
**Bug fix: Reminders for today weren't being matched sometimes.
**Feature:  Solidified integration with DatePlugin and CalendarPlugin
**Feature:  Recurring reminders will now return multiple hits in showReminders and the calendar.
**Feature:  Added TIDDLERNAME to the replacements for showReminders format, for plugins that need the title without brackets.
* v2.3.5 (Feb 8, 2006)
**Bug fix: Sped up reminders lots.  Added a caching mechanism for reminders that have already been matched.
* v2.3.4 (Feb 7, 2006)
**Bug fix: Cleaned up code to hopefully prevent the Firefox 1.5.0.1 crash that was causing lots of plugins 
to crash Firefox.  Thanks to http://www.jslint.com
* v2.3.3 (Feb 2, 2006)
**Feature: newReminder now has drop down lists instead of text boxes.
**Bug fix:  A trailing space in a title would trigger an infinite loop.
**Bug fix:  using tag:"birthday !reminder" would filter differently than tag:"!reminder birthday"
* v2.3.2 (Jan 21, 2006)
**Feature: newReminder macro, which will let you easily add a reminder to a tiddler. Thanks to Eric Shulman (http://www.elsdesign.com) for the code to do this.
** Bug fix: offsetday was not working sometimes
** Bug fix: when upgrading to 2.0, I included a bit to exclude tiddlers tagged with excludeSearch.  I've reverted back to searching through all tiddlers
* v2.3.1 (Jan 7, 2006)
**Feature: 2.0 compatibility
**Feature AlanH sent some code to make sure that showReminders prints a message if no reminders are found.
* v2.3.0 (Jan 3, 2006)
** Bug Fix:  Using "Last Sunday (-0)" as a offsetdayofweek wasn't working.
** Bug Fix:  Daylight Savings time broke offset based reminders (for example year:2005 month:8 day:23 recurdays:7 would match Monday instead of Tuesday during DST.

!Code
***/
//{{{

//============================================================================
//============================================================================
//           ReminderPlugin
//============================================================================
//============================================================================

version.extensions.ReminderPlugin = {major: 2, minor: 3, revision: 8, date: new Date(2006,3,9), source: "http://remindermacros.tiddlyspot.com/"};

//============================================================================
// Configuration
// Modify this section to change the defaults for 
// leadtime and display strings
//============================================================================

config.macros.reminders = {};
config.macros["reminder"] = {};
config.macros["newReminder"] = {};
config.macros["showReminders"] = {};
config.macros["displayTiddlersWithReminders"] = {};

config.macros.reminders["defaultLeadTime"] = [0,6000];
config.macros.reminders["defaultReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY";
config.macros.reminders["defaultShowReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY -- TIDDLER";
config.macros.reminders["defaultAnniversaryMessage"] = "(DIFF)";
config.macros.reminders["untitledReminder"] = "Untitled Reminder";
config.macros.reminders["noReminderFound"] = "Couldn't find a match for TITLE in the next LEADTIMEUPPER days."
config.macros.reminders["todayString"] = "Today";
config.macros.reminders["tomorrowString"] = "Tomorrow";
config.macros.reminders["ndaysString"] = "DIFF days";
config.macros.reminders["emtpyShowRemindersString"] = "There are no upcoming events";


//============================================================================
//  Code
// You should not need to edit anything 
// below this.  Make sure to edit this tiddler and copy 
// the code from the text box, to make sure that 
// tiddler rendering doesn't interfere with the copy 
// and paste.
//============================================================================

//this object will hold the cache of reminders, so that we don't
//recompute the same reminder over again.
var reminderCache = {};

config.macros.showReminders.handler = function showReminders(place,macroName,params)
{
   var now = new Date().getMidnight();
   var paramHash = {};
   var leadtime = [0,14];
   paramHash = getParamsForReminder(params);
   var bProvidedDate = (paramHash["year"] != null) || 
			(paramHash["month"] != null) || 
			(paramHash["day"] != null) || 
			(paramHash["dayofweek"] != null);
   if (paramHash["leadtime"] != null)
   {
      leadtime = paramHash["leadtime"];
      if (bProvidedDate)
      {
         //If they've entered a day, we need to make 
         //sure to find it.  We'll reset the 
         //leadtime a few lines down.
         paramHash["leadtime"] = [-10000, 10000];
      }
   }
   var matchedDate = now;
   if (bProvidedDate)
   {
      var leadTimeLowerBound = new Date().getMidnight().addDays(paramHash["leadtime"][0]);
      var leadTimeUpperBound = new Date().getMidnight().addDays(paramHash["leadtime"][1]);
      matchedDate = findDateForReminder(paramHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound); 
   }

   var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);
   var elem = createTiddlyElement(place,"span",null,null, null);
   var mess = "";
   if (arr.length == 0)
   {
      mess += config.macros.reminders.emtpyShowRemindersString; 
   }
   for (var j = 0; j < arr.length; j++)
   {
      if (paramHash["format"] != null)
      {
         arr[j]["params"]["format"] = paramHash["format"];
      }
      else
      {
         arr[j]["params"]["format"] = config.macros.reminders["defaultShowReminderMessage"];
      }
      mess += getReminderMessageForDisplay(arr[j]["diff"], arr[j]["params"], arr[j]["matchedDate"], arr[j]["tiddler"]);
      mess += "\n";
   }
   wikify(mess, elem, null, null);
};


config.macros.displayTiddlersWithReminders.handler = function displayTiddlersWithReminders(place,macroName,params)
{
   var now = new Date().getMidnight();
   var paramHash = {};
   var leadtime = [0,14];
   paramHash = getParamsForReminder(params);
   var bProvidedDate = (paramHash["year"] != null) || 
			(paramHash["month"] != null) || 
			(paramHash["day"] != null) || 
			(paramHash["dayofweek"] != null);
   if (paramHash["leadtime"] != null)
   {
      leadtime = paramHash["leadtime"];
      if (bProvidedDate)
      {
         //If they've entered a day, we need to make 
         //sure to find it.  We'll reset the leadtime 
         //a few lines down.
         paramHash["leadtime"] = [-10000,10000];
      }
   }
   var matchedDate = now;
   if (bProvidedDate)
   {
      var leadTimeLowerBound = new Date().getMidnight().addDays(paramHash["leadtime"][0]);
      var leadTimeUpperBound = new Date().getMidnight().addDays(paramHash["leadtime"][1]);
      matchedDate = findDateForReminder(paramHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound); 
   }
   var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);
   for (var j = 0; j < arr.length; j++)
   {
      displayTiddler(null, arr[j]["tiddler"], 0, null, false, false, false);
   }
};

config.macros.reminder.handler = function reminder(place,macroName,params)
{
   var dateHash = getParamsForReminder(params);
   if (dateHash["hidden"] != null)
   {
      return;
   }
   var leadTime = dateHash["leadtime"];
   if (leadTime == null)
   {
      leadTime = config.macros.reminders["defaultLeadTime"]; 
   }
   var leadTimeLowerBound = new Date().getMidnight().addDays(leadTime[0]);
   var leadTimeUpperBound = new Date().getMidnight().addDays(leadTime[1]);
   var matchedDate = findDateForReminder(dateHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound);
   if (!store.getTiddler) 
   {
      store.getTiddler=function(title) {return this.tiddlers[title];};
   }
   var title = window.story.findContainingTiddler(place).id.substr(7);
   if (matchedDate != null)
   {
      var diff = matchedDate.getDifferenceInDays(new Date().getMidnight());
      var elem = createTiddlyElement(place,"span",null,null, null);
      var mess = getReminderMessageForDisplay(diff, dateHash, matchedDate, title);
      wikify(mess, elem, null, null);
   }
   else
   {
      createTiddlyElement(place,"span",null,null, config.macros.reminders["noReminderFound"].replace("TITLE", dateHash["title"]).replace("LEADTIMEUPPER", leadTime[1]).replace("LEADTIMELOWER", leadTime[0]).replace("TIDDLERNAME", title).replace("TIDDLER", "[[" + title + "]]") );
   }
};

config.macros.newReminder.handler = function newReminder(place,macroName,params)
{
  var today=new Date().getMidnight();
  var formstring = '<html><form>Year: <select name="year"><option value="">Every year</option>';
  for (var i = 0; i < 5; i++)
  {
    formstring += '<option' + ((i == 0) ? ' selected' : '') + ' value="' + (today.getFullYear() +i) + '">' + (today.getFullYear() + i) + '</option>';
  }
  formstring += '</select>&nbsp;&nbsp;Month:<select name="month"><option value="">Every month</option>';
  for (i = 0; i < 12; i++)
  {
    formstring += '<option' + ((i == today.getMonth()) ? ' selected' : '') + ' value="' + (i+1) + '">' + config.messages.dates.months[i] + '</option>';
  }
  formstring += '</select>&nbsp;&nbsp;Day:<select name="day"><option value="">Every day</option>';
  for (i = 1; i < 32; i++)
  {
    formstring += '<option' + ((i == (today.getDate() )) ? ' selected' : '') + ' value="' + i + '">' + i + '</option>';
  }

formstring += '</select>&nbsp;&nbsp;Reminder Title:<input type="text" size="40" name="title" value="please enter a title" onfocus="this.select();"><input type="button" value="ok" onclick="addReminderToTiddler(this.form)"></form></html>';

  var panel = config.macros.slider.createSlider(place,null,"New Reminder","Open a form to add a new reminder to this tiddler");
  wikify(formstring ,panel,null,store.getTiddler(params[1]));
};

// onclick: process input and insert reminder at 'marker'
window.addReminderToTiddler = function(form) {
   if (!store.getTiddler) 
   {
      store.getTiddler=function(title) {return this.tiddlers[title];};
   }
   var title = window.story.findContainingTiddler(form).id.substr(7);
   var tiddler=store.getTiddler(title);
  var txt='\n<<reminder ';
  if (form.year.value != "")
    txt += 'year:'+form.year.value + ' ';
  if (form.month.value != "")
    txt += 'month:'+form.month.value + ' ';
  if (form.day.value != "")
    txt += 'day:'+form.day.value + ' ';
  txt += 'title:"'+form.title.value+'" ';
  txt +='>>';
   tiddler.set(null,tiddler.text + txt);
   window.story.refreshTiddler(title,1,true);
   store.setDirty(true);
};

function hasTag(tiddlerTags, tagFilters)
{
  //Make sure we respond well to empty tiddlerTaglists or tagFilterlists
  if (tagFilters.length==0 || tiddlerTags.length==0)
  {
    return true;
  }

  var bHasTag = false;
  
  /*bNoPos says: "'till now there has been no check using a positive filter"
     Imagine a filterlist consisting of 1 negative filter:
         If the filter isn't matched, we want hasTag to be true.
         Yet bHasTag is still false ('cause only positive filters cause bHasTag to change)
         
     If no positive filters are present bNoPos is true, and no negative filters are matched so we have not returned false
         Thus: hasTag returns true.
      
      If at any time a positive filter is encountered, we want at least one of the tags to match it, so we turn bNoPos to false, which
      means bHasTag must be true for hasTag to return true*/
  var bNoPos=true;
  
for (var t3 = 0; t3 < tagFilters.length; t3++)
  {
      for(var t2=0; t2<tiddlerTags.length; t2++)
      {
           if (tagFilters[t3].length > 1 && tagFilters[t3].charAt(0) == '!') 
           {
              if (tiddlerTags[t2] == tagFilters[t3].substring(1))
              {
                 //If at any time a negative filter is matched, we return false
                  return false;
              }
           }
           else 
           {
              if (bNoPos)
              {
                 //We encountered the first positive filter
                 bNoPos=false;
              }
              if (tiddlerTags[t2] == tagFilters[t3])
              {
                  //A positive filter is matched. As long as no negative filter is matched, hasTag will return true
                  bHasTag=true;
              }
           }
        }
    }
    return (bNoPos || bHasTag);
};

//This function searches all tiddlers for the reminder  //macro.  It is intended that other plugins (like //calendar) will use this function to query for 
//upcoming reminders.
//The arguments to this function filter out reminders //based on when they will fire.
//
//ARGUMENTS:
//baseDate is the date that is used as "now".  
//leadtime is a two element int array, with leadtime[0] 
//         as the lower bound and leadtime[1] as the
//         upper bound.  A reasonable default is [0,14]
//tags is a space-separated list of tags to use to filter 
//         tiddlers.  If a tag name begins with an !, then 
//         only tiddlers which do not have that tag will 
//         be considered.  For example "examples holidays"  
//         will search for reminders in any tiddlers that  
//         are tagged with examples or holidays and 
//         "!examples !holidays" will search for reminders 
//         in any tiddlers that are not tagged with 
//         examples or holidays.  Pass in null to search 
//         all tiddlers.
//limit.  If limit is null, individual reminders can 
//        override the leadtime specified earlier.  
//        Pass in 1 in order to override that behavior.

window.findTiddlersWithReminders = function findTiddlersWithReminders(baseDate, leadtime, tags, limit)
{
//function(searchRegExp,sortField,excludeTag)
//   var macroPattern = "<<([^>\\]+)(?:\\*)([^>]*)>>";
   var macroPattern = "<<(reminder)(.*)>>";
   var macroRegExp = new RegExp(macroPattern,"mg");
   var matches = store.search(macroRegExp,"title","");
   var arr = [];
   var tagsArray = null;
   if (tags != null)
   {
      // tagsArray = tags.split(" ");
      tagsArray = tags.readBracketedList(); // allows tags with spaces. thanks Robin Summerhill, 4-Oct-06.
   }
   for(var t=matches.length-1; t>=0; t--)
   {
      if (tagsArray != null)
      {
         //If they specified tags to filter on, and this tiddler doesn't 
	 //match, skip it entirely.
         if ( ! hasTag(matches[t].tags, tagsArray))
         {
            continue;
         }
      }

      var targetText = matches[t].text;
      do {
         // Get the next formatting match
         var formatMatch = macroRegExp.exec(targetText);
         if(formatMatch && formatMatch[1] != null && formatMatch[1].toLowerCase() == "reminder")
         {
            //Find the matching date.
            
            var params = formatMatch[2] != null ? formatMatch[2].readMacroParams() : {};
            var dateHash = getParamsForReminder(params);
            if (limit != null || dateHash["leadtime"] == null)
            {
               if (leadtime == null)
                   dateHash["leadtime"] = leadtime;
               else
               {
                  dateHash["leadtime"] = [];
                  dateHash["leadtime"][0] = leadtime[0];
                  dateHash["leadtime"][1] = leadtime[1];
               }
            }
	    if (dateHash["leadtime"] == null)
               dateHash["leadtime"] = config.macros.reminders["defaultLeadTime"]; 
            var leadTimeLowerBound = baseDate.addDays(dateHash["leadtime"][0]);
            var leadTimeUpperBound = baseDate.addDays(dateHash["leadtime"][1]);
            var matchedDate = findDateForReminder(dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound);
            while (matchedDate != null)
            {
               var hash = {};
               hash["diff"] = matchedDate.getDifferenceInDays(baseDate);
               hash["matchedDate"] = new Date(matchedDate.getFullYear(), matchedDate.getMonth(), matchedDate.getDate(), 0, 0);
               hash["params"] = cloneParams(dateHash);
               hash["tiddler"] = matches[t].title;
               hash["tags"] = matches[t].tags;
               arr.pushUnique(hash);
	       if (dateHash["recurdays"] != null || (dateHash["year"] == null))
	       {
	         leadTimeLowerBound = leadTimeLowerBound.addDays(matchedDate.getDifferenceInDays(leadTimeLowerBound)+ 1);
                 matchedDate = findDateForReminder(dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound);
	       }
	       else matchedDate = null;
            }
         }
      }while(formatMatch);
   }
   if(arr.length > 1)  //Sort the array by number of days remaining.
   {
      arr.sort(function (a,b) {if(a["diff"] == b["diff"]) {return(0);} else {return (a["diff"] < b["diff"]) ? -1 : +1; } });
   }
   return arr;
};

//This function takes the reminder macro parameters and
//generates the string that is used for display.
//This function is not intended to be called by 
//other plugins.
 window.getReminderMessageForDisplay= function getReminderMessageForDisplay(diff, params, matchedDate, tiddlerTitle)
{
   var anniversaryString = "";
   var reminderTitle = params["title"];
   if (reminderTitle == null)
   {
      reminderTitle = config.macros.reminders["untitledReminder"];
   }
   if (params["firstyear"] != null)
   {
      anniversaryString = config.macros.reminders["defaultAnniversaryMessage"].replace("DIFF", (matchedDate.getFullYear() - params["firstyear"]));
   }
   var mess = "";
   var diffString = "";
   if (diff == 0)
   {
      diffString = config.macros.reminders["todayString"];
   }
   else if (diff == 1)
   {
      diffString = config.macros.reminders["tomorrowString"];
   }
   else
   {
      diffString = config.macros.reminders["ndaysString"].replace("DIFF", diff);
   }
   var format = config.macros.reminders["defaultReminderMessage"];
   if (params["format"] != null)
   {
      format = params["format"];
   }
   mess = format;
//HACK!  -- Avoid replacing DD in TIDDLER with the date
   mess = mess.replace(/TIDDLER/g, "TIDELER");
   mess = matchedDate.formatStringDateOnly(mess);
   mess = mess.replace(/TIDELER/g, "TIDDLER");
   if (tiddlerTitle != null)
   {
      mess = mess.replace(/TIDDLERNAME/g, tiddlerTitle);
      mess = mess.replace(/TIDDLER/g, "[[" + tiddlerTitle + "]]");
   }
   
   mess = mess.replace("DIFF", diffString).replace("TITLE", reminderTitle).replace("DATE", matchedDate.formatString("DDD MMM DD, YYYY")).replace("ANNIVERSARY", anniversaryString);
   return mess;
};

// Parse out the macro parameters into a hashtable.  This
// handles the arguments for reminder, showReminders and 
// displayTiddlersWithReminders.
window.getParamsForReminder = function getParamsForReminder(params)
{
   var dateHash = {};
   var type = "";
   var num = 0;
   var title = "";
   for(var t=0; t<params.length; t++)
   {
      var split = params[t].split(":");
      type = split[0].toLowerCase();
      var value = split[1];
      for (var i=2; i < split.length; i++)
      {
         value += ":" + split[i];
      }
      if (type == "nolinks" || type == "limit" || type == "hidden")
      {
         num = 1;
      }
      else if (type == "leadtime")
      {
         var leads = value.split("...");
         if (leads.length == 1)
         {
            leads[1]= leads[0];
            leads[0] = 0;
         }
         leads[0] = parseInt(leads[0], 10);
         leads[1] = parseInt(leads[1], 10);
         num = leads;
      }
      else if (type == "offsetdayofweek")
      {
          if (value.substr(0,1) == "-")
          {
             dateHash["negativeOffsetDayOfWeek"] = 1;
	     value = value.substr(1);
          }
          num = parseInt(value, 10);
      }
      else if (type != "title" && type != "tag" && type != "format")
      {
         num = parseInt(value, 10);
      }
      else
      {
         title = value;
         t++;
         while (title.substr(0,1) == '"' && title.substr(title.length - 1,1) != '"' && params[t] != undefined)
         {
            title += " " + params[t++];
         }
         //Trim off the leading and trailing quotes
         if (title.substr(0,1) == "\"" && title.substr(title.length - 1,1)== "\"")
         {
            title = title.substr(1, title.length - 2);
            t--;
         }
         num = title;
      }
      dateHash[type] = num;
   }
   //date is synonymous with day
   if (dateHash["day"] == null)
   {
      dateHash["day"] = dateHash["date"];
   }
   return dateHash;
};

//This function finds the date specified in the reminder 
//parameters.  It will return null if no match can be
//found.  This function is not intended to be used by
//other plugins.
window.findDateForReminder= function findDateForReminder( dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound)
{
   if (baseDate == null)
   {
     baseDate = new Date().getMidnight();
   }
   var hashKey = baseDate.convertToYYYYMMDDHHMM();
   for (var k in dateHash)
   {
      hashKey += "," + k + "|" + dateHash[k];
   }
   hashKey += "," + leadTimeLowerBound.convertToYYYYMMDDHHMM();
   hashKey += "," + leadTimeUpperBound.convertToYYYYMMDDHHMM();
   if (reminderCache[hashKey] == null)
   {
      //If we don't find a match in this run, then we will
      //cache that the reminder can't be matched.
      reminderCache[hashKey] = false;
   }
   else if (reminderCache[hashKey] == false)
   {
      //We've already tried this date and failed
      return null;
   }
   else
   {
      return reminderCache[hashKey];
   }
   
   var bOffsetSpecified = dateHash["offsetyear"] != null || 
				dateHash["offsetmonth"] != null || 
				dateHash["offsetday"] != null || 
				dateHash["offsetdayofweek"] != null || 
				dateHash["recurdays"] != null;
   
   // If we are matching the base date for a dayofweek offset, look for the base date a 
   //little further back.
   var tmp1leadTimeLowerBound = leadTimeLowerBound;  
   if ( dateHash["offsetdayofweek"] != null)
   {
      tmp1leadTimeLowerBound = leadTimeLowerBound.addDays(-6);  
   }
   var matchedDate = baseDate.findMatch(dateHash, tmp1leadTimeLowerBound, leadTimeUpperBound);
   if (matchedDate != null)
   {
      var newMatchedDate = matchedDate;
      if (dateHash["recurdays"] != null)
      {
         while (newMatchedDate.getTime() < leadTimeLowerBound.getTime())
         {
            newMatchedDate = newMatchedDate.addDays(dateHash["recurdays"]);
         }
      }
      else if (dateHash["offsetyear"] != null || 
		dateHash["offsetmonth"] != null || 
		dateHash["offsetday"] != null || 
		dateHash["offsetdayofweek"] != null)
      {
         var tmpdateHash = cloneParams(dateHash);
         tmpdateHash["year"] = dateHash["offsetyear"];
         tmpdateHash["month"] = dateHash["offsetmonth"];
         tmpdateHash["day"] = dateHash["offsetday"];
         tmpdateHash["dayofweek"] = dateHash["offsetdayofweek"];
	 var tmpleadTimeLowerBound = leadTimeLowerBound;
	 var tmpleadTimeUpperBound = leadTimeUpperBound;
	 if (tmpdateHash["offsetdayofweek"] != null)
	 {
	 	if (tmpdateHash["negativeOffsetDayOfWeek"] == 1)
		{
		   tmpleadTimeLowerBound = matchedDate.addDays(-6);
		   tmpleadTimeUpperBound = matchedDate;

		}
		else
		{
		   tmpleadTimeLowerBound = matchedDate;
		   tmpleadTimeUpperBound = matchedDate.addDays(6);
		}

	 }
	 newMatchedDate = matchedDate.findMatch(tmpdateHash, tmpleadTimeLowerBound, tmpleadTimeUpperBound);
         //The offset couldn't be matched.  return null.
         if (newMatchedDate == null)
         {
            return null;
         }
      }
      if (newMatchedDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))
      {
         reminderCache[hashKey] = newMatchedDate;
         return newMatchedDate;
      }
   }
   return null;
};

//This does much the same job as findDateForReminder, but
//this one doesn't deal with offsets or recurring 
//reminders.
Date.prototype.findMatch = function findMatch(dateHash, leadTimeLowerBound, leadTimeUpperBound)
{

   var bSpecifiedYear =     (dateHash["year"] != null);
   var bSpecifiedMonth =     (dateHash["month"] != null);
   var bSpecifiedDay =     (dateHash["day"] != null);
   var bSpecifiedDayOfWeek =     (dateHash["dayofweek"] != null);
   if (bSpecifiedYear && bSpecifiedMonth && bSpecifiedDay)
   {
      return new Date(dateHash["year"], dateHash["month"]-1, dateHash["day"], 0, 0);
   }
   var bMatchedYear = !bSpecifiedYear;
   var bMatchedMonth = !bSpecifiedMonth;
   var bMatchedDay = !bSpecifiedDay;
   var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;
   if (bSpecifiedDay && bSpecifiedMonth && !bSpecifiedYear && !bSpecifiedDayOfWeek)
   {

      //Shortcut -- First try this year.  If it's too small, try next year.
      var tmpMidnight = this.getMidnight();
      var tmpDate = new Date(this.getFullYear(), dateHash["month"]-1, dateHash["day"], 0,0);
      if (tmpDate.getTime() < leadTimeLowerBound.getTime())
      {
         tmpDate = new Date((this.getFullYear() + 1), dateHash["month"]-1, dateHash["day"], 0,0);
      }
      if ( tmpDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))
      {
         return tmpDate;
      }
      else
      {
         return null;
      }
   }

   var newDate = leadTimeLowerBound; 
   while (newDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))
   {
      var tmp = testDate(newDate, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek);
      if (tmp != null)
        return tmp;
      newDate = newDate.addDays(1);
   }
};

function testDate(testMe, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek)
{
   var bMatchedYear = !bSpecifiedYear;
   var bMatchedMonth = !bSpecifiedMonth;
   var bMatchedDay = !bSpecifiedDay;
   var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;
   if (bSpecifiedYear)
   {
      bMatchedYear = (dateHash["year"] == testMe.getFullYear());
   }
   if (bSpecifiedMonth)
   {
      bMatchedMonth = ((dateHash["month"] - 1)  == testMe.getMonth() );
   }
   if (bSpecifiedDay)
   {
      bMatchedDay = (dateHash["day"] == testMe.getDate());
   }
   if (bSpecifiedDayOfWeek)
   {
      bMatchedDayOfWeek = (dateHash["dayofweek"] == testMe.getDay());
   }

   if (bMatchedYear && bMatchedMonth && bMatchedDay && bMatchedDayOfWeek)
   {
      return testMe;
   }
};

//Returns true if the date is in between two given dates
Date.prototype.isBetween = function isBetween(lowerBound, upperBound)
{
  return (this.getTime() >= lowerBound.getTime() && this.getTime() <= upperBound.getTime());
}
//Return a new date, with the time set to midnight (0000)
Date.prototype.getMidnight = function getMidnight()
{
   return new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0);
};
// Add the specified number of days to a date.
Date.prototype.addDays = function addDays(numberOfDays)
{
   return new Date(this.getFullYear(), this.getMonth(), this.getDate() + numberOfDays, 0, 0);
};
//Return the number of days between two dates.
Date.prototype.getDifferenceInDays = function getDifferenceInDays(otherDate)
{
//I have to do it this way, because this way ignores daylight savings
   var tmpDate = this.addDays(0);
   if (this.getTime() > otherDate.getTime())
   {
      var i = 0;
      for (i = 0; tmpDate.getTime() > otherDate.getTime(); i++)
      {
         tmpDate = tmpDate.addDays(-1);
      }
      return i;
   }
   else
   {
      var i = 0;
      for (i = 0; tmpDate.getTime() < otherDate.getTime(); i++)
      {
         tmpDate = tmpDate.addDays(1);
      }
      return i * -1;
   }
   return 0;
};
function cloneParams(what) {
    var tmp = {};
    for (var i in what) {
        tmp[i] = what[i];
    }
    return tmp;
}
// Substitute date components into a string
Date.prototype.formatStringDateOnly = function formatStringDateOnly(template)
{
	template = template.replace("YYYY",this.getFullYear());
	template = template.replace("YY",String.zeroPad(this.getFullYear()-2000,2));
	template = template.replace("MMM",config.messages.dates.months[this.getMonth()]);
	template = template.replace("0MM",String.zeroPad(this.getMonth()+1,2));
	template = template.replace("MM",this.getMonth()+1);
	template = template.replace("DDD",config.messages.dates.days[this.getDay()]);
	template = template.replace("0DD",String.zeroPad(this.getDate(),2));
	template = template.replace("DD",this.getDate());
	return template;
};

//}}}
Task: Implement support for ReminderPlugin
Reminder: <<newReminder>>
!!!Items
#
#
!!!Notes
Build support for Reminder macro into templates and fET (similar to ~TaskOrganizerPlugin)

!!!Due
!!Reminders (45 Day Outlook)
{{centeredTable{
<<showReminders leadtime:45 format:"| DIFF | DATE | ANNIVERSARY | TITLE | TIDDLER |" tag:"!Completed !Trash">>}}}
<<slider Slider001 Reminders-45 "Reminders Archive">>
@@display:none;<<reminder firstyear:2009 month:3 day:1 title:"Task Manager v2.0 Started" >>@@
{{center{
<<showReminders leadtime:-45...-1 tag:"!Completed !Trash">>
}}}
Task: Create, Save, and close tiddler automatically (for New Projects)
Reminder: <<newReminder>>
!!!Items
#
#
Need to add tiddler refresh on execution
!!!Notes
Using InlineJavascriptPlugin, you can create an 'onclick' script, like
this:

<script label="New Project">
   var title='NewTiddler';
   var txt=store.getTiddlerText("ProjectTemplate", "").replace(/Project1/g, prompt("Enter Project Tag (No Spaces or special characters)"));
   var who=config.options.txtUserName;
   var when=new Date();
   var tags='fETTasks';
   var fields={};
   store.saveTiddler(title,title,txt,who,when,tags,fields);
</script>
enjoy,
-e 
MTP Version 03.26.09
{{button{<script label="New Project">
   var title=prompt("Enter Project Tag (No Spaces or special characters)");
   var txt=store.getTiddlerText("ProjectTemplate", "").replace(/Project1/g, title);
   var who=config.options.txtUserName;
   var when=new Date();
   var tags='fETTasks';
   var fields={};
   store.saveTiddler(title,title,txt,who,when,tags,fields);
   story.refreshTiddler(story.findContainingTiddler(place).getAttribute("tiddler"),null,true);
</script>}}}

!!!Due
<<reminder year:2009 month:3 day:5 title:"Bump TW Group Questions" >>
<<reminder year:2009 month:3 day:22 title:"Post in TW Dev group" >>
/***
|''Name''|SimpleSearchPlugin|
|''Description''|displays search results as a simple list of matching tiddlers|
|''Authors''|FND|
|''Version''|0.4.1|
|''Status''|stable|
|''Source''|http://devpad.tiddlyspot.com/#SimpleSearchPlugin|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/plugins/SimpleSearchPlugin.js|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Keywords''|search|
!Revision History
!!v0.2.0 (2008-08-18)
* initial release
!!v0.3.0 (2008-08-19)
* added Open All button (renders Classic Search option obsolete)
* sorting by relevance (title matches before content matches)
!!v0.4.0 (2008-08-26)
* added tag matching
!To Do
* tag matching optional
* animations for container creation and removal
* when clicking on search results, do not scroll to the respective tiddler (optional)
* use template for search results
!Code
***/
//{{{
if(!version.extensions.SimpleSearchPlugin) { //# ensure that the plugin is only installed once
version.extensions.SimpleSearchPlugin = { installed: true };

if(!config.extensions) { config.extensions = {}; }

config.extensions.SimpleSearchPlugin = {
	heading: "Search Results",
	containerId: "searchResults",
	btnCloseLabel: "close",
	btnCloseTooltip: "dismiss search results",
	btnCloseId: "search_close",
	btnOpenLabel: "Open all",
	btnOpenTooltip: "open all search results",
	btnOpenId: "search_open",

	displayResults: function(matches, query) {
		story.refreshAllTiddlers(true); // update highlighting within story tiddlers
		var el = document.getElementById(this.containerId);
		query = '"""' + query + '"""'; // prevent WikiLinks
		if(el) {
			removeChildren(el);
		} else { //# fallback: use displayArea as parent
			var container = document.getElementById("displayArea");
			el = document.createElement("div");
			el.id = this.containerId;
			el = container.insertBefore(el, container.firstChild);
		}
		var msg = "!" + this.heading + "\n";
		if(matches.length > 0) {
			msg += "''" + config.macros.search.successMsg.format([matches.length.toString(), query]) + ":''\n";
			this.results = [];
			for(var i = 0 ; i < matches.length; i++) {
				this.results.push(matches[i].title);
				msg += "* [[" + matches[i].title + "]]\n";
			}
		} else {
			msg += "''" + config.macros.search.failureMsg.format([query]) + "''"; // XXX: do not use bold here!?
		}
		createTiddlyButton(el, this.btnCloseLabel, this.btnCloseTooltip, config.extensions.SimpleSearchPlugin.closeResults, "button", this.btnCloseId);
		wikify(msg, el);
		if(matches.length > 0) { // XXX: redundant!?
			createTiddlyButton(el, this.btnOpenLabel, this.btnOpenTooltip, config.extensions.SimpleSearchPlugin.openAll, "button", this.btnOpenId);
		}
	},

	closeResults: function() {
		var el = document.getElementById(config.extensions.SimpleSearchPlugin.containerId);
		removeNode(el);
		config.extensions.SimpleSearchPlugin.results = null;
		highlightHack = null;
	},

	openAll: function(ev) {
		story.displayTiddlers(null, config.extensions.SimpleSearchPlugin.results);
		return false;
	}
};

config.shadowTiddlers.StyleSheetSimpleSearch = "/*{{{*/\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " {\n" +
	"\toverflow: auto;\n" +
	"\tpadding: 5px 1em 10px;\n" +
	"\tbackground-color: [[ColorPalette::TertiaryPale]];\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " h1 {\n" +
	"\tmargin-top: 0;\n" +
	"\tborder: none;\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " ul {\n" +
	"\tmargin: 0.5em;\n" +
	"\tpadding-left: 1.5em;\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " .button {\n" +
	"\tdisplay: block;\n" +
	"\tborder-color: [[ColorPalette::TertiaryDark]];\n" +
	"\tpadding: 5px;\n" +
	"\tbackground-color: [[ColorPalette::TertiaryLight]];\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " .button:hover {\n" +
	"\tborder-color: [[ColorPalette::SecondaryMid]];\n" +
	"\tbackground-color: [[ColorPalette::SecondaryLight]];\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.btnCloseId + " {\n" +
	"\tfloat: right;\n" +
	"\tmargin: -5px -1em 5px 5px;\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.btnOpenId + " {\n" +
	"\tfloat: left;\n" +
	"\tmargin-top: 5px;\n" +
	"}\n" +
	"/*}}}*/";
store.addNotification("StyleSheetSimpleSearch", refreshStyles);

// override Story.search()
Story.prototype.search = function(text, useCaseSensitive, useRegExp) {
	highlightHack = new RegExp(useRegExp ? text : text.escapeRegExp(), useCaseSensitive ? "mg" : "img");
	var matches = store.search(highlightHack, null, "excludeSearch");
	var q = useRegExp ? "/" : "'";
	config.extensions.SimpleSearchPlugin.displayResults(matches, q + text + q);
};

// override TiddlyWiki.search() to sort by relevance
TiddlyWiki.prototype.search = function(searchRegExp, sortField, excludeTag, match) {
	var candidates = this.reverseLookup("tags", excludeTag, !!match);
	var primary = [];
	var secondary = [];
	var tertiary = [];
	for(var t = 0; t < candidates.length; t++) {
		if(candidates[t].title.search(searchRegExp) != -1) {
			primary.push(candidates[t]);
		} else if(candidates[t].tags.join(" ").search(searchRegExp) != -1) {
			secondary.push(candidates[t]);
		} else if(candidates[t].text.search(searchRegExp) != -1) {
			tertiary.push(candidates[t]);
		}
	}
	var results = primary.concat(secondary).concat(tertiary);
	if(sortField) {
		results.sort(function(a, b) {
			return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);
		});
	}
	return results;
};

} //# end of "install only once"
//}}}
.tagging, .tagged {border: 1px solid #fff;}
.hidden {display:none;}
.tiddler {border: 1px solid #eee; margin-bottom: 1em; padding-bottom: 1em;}
/***
|''Name:''|TableSortingPlugin|
|''Description:''|Dynamically sort tables by clicking on column headers|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#TableSortingPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.02|
|''Date:''|25-01-2008|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|
!!Usage:
* Make sure your table has a header row
** {{{|Name|Phone Number|Address|h}}}<br> Note the /h/ that denote a header row 
* Give the table a class of 'sortable'
** {{{
|sortable|k
|Name|Phone Number|Address|h
}}}<br>Note the /k/ that denotes a class name being assigned to the table.
* To disallow sorting by a column, place {{{<<nosort>>}}} in it's header
* To automatically sort a table by a column, place {{{<<autosort>>}}} in the header for that column
** Or to sort automatically but in reverse order, use {{{<<autosort reverse>>}}}

!!Example:
|sortable|k
|Name |Salary |Extension |Performance |File Size |Start date |h
|ZBloggs, Fred |$12000.00 |1353 |+1.2 |74.2Kb |Aug 19, 2003 21:34:00 |
|ABloggs, Fred |$12000.00 |1353 |1.2 |3350b |09/18/2003 |
|CBloggs, Fred |$12000 |1353 |1.200 |55.2Kb |August 18, 2003 |
|DBloggs, Fred |$12000.00 |1353 |1.2 |2100b |07/18/2003 |
|Bloggs, Fred |$12000.00 |1353 |01.20 |6.156Mb |08/17/2003 05:43 |
|Turvey, Kevin |$191200.00 |2342 |-33 |1b |02/05/1979 |
|Mbogo, Arnold |$32010.12 |2755 |-21.673 |1.2Gb |09/08/1998 |
|Shakespeare, Bill |£122000.00|3211 |6 |33.22Gb |12/11/1961 |
|Shakespeare, Hamlet |£9000 |9005 |-8 |3Gb |01/01/2002 |
|Fitz, Marvin |€3300.30 |5554 |+5 |4Kb |05/22/1995 |

***/
// /%
//!BEGIN-PLUGIN-CODE
config.tableSorting = {
	
	darrow: "\u2193",
	
	uarrow: "\u2191",
	
	getText : function (o) {
		var p = o.cells[SORT_INDEX];
		return p.innerText || p.textContent || '';
	},
	
	sortTable : function (o,rev) {
		SORT_INDEX = o.getAttribute("index");
		var c = config.tableSorting;
		var T = findRelated(o.parentNode,"TABLE");
		if(T.tBodies[0].rows.length<=1) 
			return;
		var itm = "";
		var i = 0;
		while (itm == "" && i < T.tBodies[0].rows.length) {
			itm = c.getText(T.tBodies[0].rows[i]).trim();
			i++;
		}
		if (itm == "") 
			return; 	
		var r = [];
		var S = o.getElementsByTagName("span")[0];		
		c.fn = c.sortAlpha; 
		if(!isNaN(Date.parse(itm)))
			c.fn = c.sortDate; 
		else if(itm.match(/^[$|£|€|\+|\-]{0,1}\d*\.{0,1}\d+$/)) 
			c.fn = c.sortNumber; 
		else if(itm.match(/^\d*\.{0,1}\d+[K|M|G]{0,1}b$/)) 
			c.fn = c.sortFile; 
		for(i=0; i<T.tBodies[0].rows.length; i++) {
			 r[i]=T.tBodies[0].rows[i]; 
		} 
		r.sort(c.reSort);
		if(S.firstChild.nodeValue==c.darrow || rev) {
			r.reverse();
			S.firstChild.nodeValue=c.uarrow;
		} 
		else 
			S.firstChild.nodeValue=c.darrow;
		var thead = T.getElementsByTagName('thead')[0]; 
		var headers = thead.rows[thead.rows.length-1].cells;
		for(var k=0; k<headers.length; k++) {
			if(!hasClass(headers[k],"nosort"))
				addClass(headers[k].getElementsByTagName("span")[0],"hidden");
		}
		removeClass(S,"hidden");
		for(i=0; i<r.length; i++) { 
			T.tBodies[0].appendChild(r[i]);
			c.stripe(r[i],i);
			for(var j=0; j<r[i].cells.length;j++){
				removeClass(r[i].cells[j],"sortedCol");
			}
			addClass(r[i].cells[SORT_INDEX],"sortedCol");
		}
	},
	
	stripe : function (e,i){
		var cl = ["oddRow","evenRow"];
		i&1? cl.reverse() : cl;
		removeClass(e,cl[1]);
		addClass(e,cl[0]);
	},
	
	sortNumber : function(v) {
		var x = parseFloat(this.getText(v).replace(/[^0-9.-]/g,''));
		return isNaN(x)? 0: x;
	},
	
	sortDate : function(v) {
		return Date.parse(this.getText(v));
	},

	sortAlpha : function(v) {
		return this.getText(v).toLowerCase();
	},
	
	sortFile : function(v) { 		
		var j, q = config.messages.sizeTemplates, s = this.getText(v);
		for (var i=0; i<q.length; i++) {
			if ((j = s.toLowerCase().indexOf(q[i].template.replace("%0\u00a0","").toLowerCase())) != -1)
				return q[i].unit * s.substr(0,j);
		}
		return parseFloat(s);
	},
	
	reSort : function(a,b){
		var c = config.tableSorting;
		var aa = c.fn(a);
		var bb = c.fn(b);
		return ((aa==bb)? 0 : ((aa<bb)? -1:1));
	}
};

Story.prototype.tSort_refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function(title,template,force,customFields,defaultText){
	var elem = this.tSort_refreshTiddler.apply(this,arguments);
	if(elem){
		var tables = elem.getElementsByTagName("TABLE");
		var c = config.tableSorting;
		for(var i=0; i<tables.length; i++){
			if(hasClass(tables[i],"sortable")){
				var x = null, rev, table = tables[i], thead = table.getElementsByTagName('thead')[0], headers = thead.rows[thead.rows.length-1].cells;
				for (var j=0; j<headers.length; j++){
					var h = headers[j];
					if (hasClass(h,"nosort"))
						continue;
					h.setAttribute("index",j);
					h.onclick = function(){c.sortTable(this); return false;};
					h.ondblclick = stopEvent;
					if(h.getElementsByTagName("span").length == 0)
						createTiddlyElement(h,"span",null,"hidden",c.uarrow); 
					if(!x && hasClass(h,"autosort")) {
						x = j;
						rev = hasClass(h,"reverse");
					}
				}
				if(x)
					c.sortTable(headers[x],rev);		
			}
		}
	}
	return elem; 
};

setStylesheet("table.sortable span.hidden {visibility:hidden;}\n"+
	"table.sortable thead {cursor:pointer;}\n"+
	"table.sortable .nosort {cursor:default;}\n"+
	"table.sortable td.sortedCol {background:#ffc;}","TableSortingPluginStyles");

function stopEvent(e){
	var ev = e? e : window.event;
	ev.cancelBubble = true;
	if (ev.stopPropagation) ev.stopPropagation();
	return false;	
}	

config.macros.nosort={
	handler : function(place){
		addClass(place,"nosort");
	}	
};

config.macros.autosort={
	handler : function(place,m,p,w,pS){
		addClass(place,"autosort"+" "+pS);		
	}	
};
//!END-PLUGIN-CODE
// %/
<<tiddler TaskTabs>>
<<tabs txtTaskManager
'Urgent TaskManager' 'Urgent TaskManager Tab' TaskManager##Urgent
'Pending TaskManager' 'Pending TaskManager Tab' TaskManager##Pending
'Completed TaskManager' 'Completed TaskManager Tab' TaskManager##Completed
>>
{{button{<script label="New Task">
 var newTiddler = new Tiddler();
 newTiddler.title = prompt('Enter a new task title','New Project Task');
 newTiddler.tags[0] = "TaskManager";
 newTiddler.tags[1] = "Task";
 newTiddler.tags[2] = "excludeLists";
 newTiddler.modifier = config.options.txtUserName;
 if(config.macros.reminders){
 newTiddler.text = "Task:\nReminder: <<newReminder>>\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";
 } else {newTiddler.text = "Task:\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";}
 store.addTiddler(newTiddler);
 story.displayTiddler(null,newTiddler.title,DEFAULT_EDIT_TEMPLATE);
 story.focusTiddler(newTiddler.title,"title");
</script>}}} <<deleteAllTagged "Delete this Project" delete>>

@@display:none;
!!!Urgent
~~Urgent Items~~
<script>
	var tag=store.getMatchingTiddlers("TaskManager && Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Pending
~~Pending Items~~
<script>
	var tag=store.getMatchingTiddlers("TaskManager && ! Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Completed
~~Completed Items~~
<script>
	var tag=store.getMatchingTiddlers("TaskManager && Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
@@
Import everything tagged with TaskManagerPackage to use this in your TiddlyWiki document
I recommend using http://www.TiddlyTools.com/index.html#ImportTiddlersPlugin
/***
|Name|TaskManagerPlugin|
|Documentation|see: [[TaskManagerPackage]]|
|Version|2.1.3|
|Author|Mike Praeuner|
|~CoreVersion|2.5.0|
|Type|plugin|
|Requires|see below|
|Description|**Experimental** [[InlineJavascriptPlugin]] based Task Manager|

!!!About
''Task Manager v<<tiddler "TaskManagerPlugin::Version">>''
Concept:
*Task Organizer similar to TaskOrganizerPlugin
*Based on InlineJavascriptPlugin
*Learning experience for TW and Javascript (+IJS)
*Highly customizable
*Added automation to delete completed items
Plugins Required: (<script>
return store.getMatchingTiddlers("TaskManagerPackage && systemConfig && ! Optional").length.toString();</script>)
<script>
  var out=[];
  var tids=store.getMatchingTiddlers("TaskManagerPackage && systemConfig && ! Optional",'modified').reverse();
  for (var t=0; t<tids.length; t++)
out.push('*[['+tids[t].title+']]');
  return out.join("\n");</script>
Plugins Optional: (<script>
return store.getMatchingTiddlers("TaskManagerPackage && systemConfig && Optional").length.toString();</script>)
<script>
  var out=[];
  var tids=store.getMatchingTiddlers("TaskManagerPackage && systemConfig && Optional",'modified').reverse();
  for (var t=0; t<tids.length; t++)
out.push('*[['+tids[t].title+']]');
  return out.join("\n");</script>
Tiddlers Created by Plugins: (<script>
return store.getMatchingTiddlers("TaskManagerPackage && ! systemConfig").length.toString();</script>)
<script>
  var out=[];
  var tids=store.getMatchingTiddlers("TaskManagerPackage && ! systemConfig",'modified').reverse();
  for (var t=0; t<tids.length; t++)
out.push('*[['+tids[t].title+']]');
  return out.join("\n");</script>
!!!Usage
Transclude TaskTabs in a tiddler {{{<<tiddler TaskTabs>>}}} for example see: [[Task Manager]]
!!!Customization
See the following Tiddlers: (basic Javascript understanding needed)
[[TaskTabs]] - Defines: Project Tabs, Status, New Project Button, and Delete Completed button
[[ProjectTemplate]] -  Defines: Project sub Tabs, New Task Button, and Delete Project button
If you make a mistake or wish to revert to the original just delete [[TaskTabs]] or [[ProjectTemplate]] and they will be re-created on startup
Note: If using [[TrashPlugin]] make sure to empty trash before reloading
!!!Removal
Delete all Task Manager Tiddlers Including: <<tag [[Task]]>> <<tag TaskTabs>> <<tag TaskManagerPackage>>
Note: Script will bypass [[TrashPlugin]]
{{button{<script label="Delete all TaskManager tiddlers" title="Use with Caution">
if(window.version && window.version.title == 'TiddlyWiki'){
	store.suspendNotifications();
	var t = store.getMatchingTiddlers("Task || TaskTabs || TaskManagerPackage")
	for(var i=0;
i<t.length;
i++)
		store.removeTiddler(t[i].title);
	store.resumeNotifications();
//	refreshDisplay();	
	story.closeAllTiddlers();refreshDisplay();	
}
return false; // ELS: added
</script>}}}
Finally save & reload your document (F5)

!!!Idea Based on Work by:
Paulo Soares ~TaskOrganizerPlugin @ http://www.math.ist.utl.pt/~psoares/addons.html
Jim @ http://tiddlywikitips.com/TiddlyWikiTasks.html
~TiddlyWiki Google Group @ http://groups.google.com/group/TiddlyWiki (specifically: FND & ELS)
{{hidden{
!!!TaskTabs
<script>
//	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","modified");
//	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","modified").reverse();
	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","title");
//	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","title").reverse();
	var fmt="[[%0]] 'view %0' [[%0]]";
	var out="";
	for (var i=0; i<tag.length; i++)
		out+=(fmt.format([tag[i].title]));
//	alert(out);
	if (out.length) return "<<tabs tabTabsForTags "+out+">>";
		return "There are no tiddlers tagged with <<tag TaskTabs>>";
</script>@@text-align:left;~~&nbsp;<script>
	var projects= store.getTaggedTiddlers("TaskTabs").length.toString();
	var tasks= store.getTaggedTiddlers("Task").length.toString();
	var urgent= store.getMatchingTiddlers("Urgent && !Completed").length.toString();
	var pending= store.getMatchingTiddlers("Task && !Urgent && !Completed").length.toString();
	var completed= store.getTaggedTiddlers("Completed").length.toString();
return ("Status: " + projects + " Projects, " + tasks + " Tasks (" + urgent + " Urgent, " + pending + " Pending, " + completed + " Completed) ");
</script>~~@@

{{button{<script label="New Project">
   var title=prompt("Enter Project Tag (No Spaces or special characters)");
   var txt=store.getTiddlerText("ProjectTemplate", "").replace(/Project1/g, title);
   var who=config.options.txtUserName;
   var when=new Date();
   var tags='"TaskTabs" "excludeLists"';
   var fields={};
   store.saveTiddler(title,title,txt,who,when,tags,fields);
   story.refreshTiddler(story.findContainingTiddler(place).getAttribute("tiddler"),null,true);
</script>}}} <<deleteCompleted daysOld:30 title:'Delete Completed Tasks'>>
!!!Project
<<tabs txtProject1
'Urgent Project1' 'Urgent Project1 Tab' Project1##Urgent
'Pending Project1' 'Pending Project1 Tab' Project1##Pending
'Completed Project1' 'Completed Project1 Tab' Project1##Completed
>>
{{button{<script label="New Task">
 var newTiddler = new Tiddler();
 newTiddler.title = prompt('Enter a new task title','New Project Task');
 newTiddler.tags[0] = "Project1";
 newTiddler.tags[1] = "Task";
 newTiddler.tags[2] = "excludeLists";
 newTiddler.modifier = config.options.txtUserName;
 if(config.macros.reminders){
 newTiddler.text = "Task:\nReminder: <<newReminder>>\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";
 } else {newTiddler.text = "Task:\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";}
 store.addTiddler(newTiddler);
 story.displayTiddler(null,newTiddler.title,DEFAULT_EDIT_TEMPLATE);
 story.focusTiddler(newTiddler.title,"title");
</script>}}} <<deleteAllTagged "Delete this Project" delete>>
@@display:none;"
!!!Urgent
~~Urgent Items~~
<script>
//	var tag=store.getMatchingTiddlers("Project1 && Urgent && ! Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("Project1 && Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Pending
~~Pending Items~~
<script>
//	var tag=store.getMatchingTiddlers("Project1 && ! Urgent && ! Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("Project1 && ! Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Completed
~~Completed Items~~
<script>
//	var tag=store.getMatchingTiddlers("Project1 && Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("Project1 && Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
@@
!!!End
}}}
!!!!!Code Create ProjectTemplate Tiddler
***/
{{{
var title= "ProjectTemplate";
var project = store.getTiddlerText("TaskManagerPlugin##Project", "");
var urgent = store.getTiddlerText("TaskManagerPlugin##Urgent", "");
var pending = store.getTiddlerText("TaskManagerPlugin##Pending", "");
var completed = store.getTiddlerText("TaskManagerPlugin##Completed", "");
var combined = (project +"\n"+"!!!Urgent" +"\n"+ urgent +"\n"+ "!!!Pending" +"\n"+ pending +"\n"+ "!!!Completed" +"\n"+ completed);
var txt= combined;
var who=config.options.txtUserName;
var when=new Date();
var tags='"TaskManagerPackage" "excludeLists"';
var fields={};
	if(store.tiddlerExists(title)){
	// displayMessage(title +' has already been created');
	} else {
	store.saveTiddler(title,title,txt,who,when,tags,fields);
	// displayMessage(title +' has been created');
	}
}}}
/***
!!!!!Code Create TaskTabs Tiddler
***/
{{{
var title= "TaskTabs";
var txt = store.getTiddlerText("TaskManagerPlugin##TaskTabs", "");
var who=config.options.txtUserName;
var when=new Date();
var tags='"TaskManagerPackage" "excludeLists"';
var fields={};
	if(store.tiddlerExists(title)){
	// displayMessage(title +' has already been created');
	} else {
	store.saveTiddler(title,title,txt,who,when,tags,fields);
	// displayMessage(title +' has been created');
	}
}}}
/***
!!!!!Code Create Completed Tiddler
***/
{{{
var title= "Completed";
var txt = "<<deleteCompleted daysOld:0 title:'Delete All Completed Items'>>";
var who=config.options.txtUserName;
var when=new Date();
var tags='"TaskManagerPackage" ""';
var fields={};
	if(store.tiddlerExists(title)){
	// displayMessage(title +' has already been created');
	} else {
	store.saveTiddler(title,title,txt,who,when,tags,fields);
	// displayMessage(title +' has been created');
	}
}}}
<script>
//	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","modified");
//	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","modified").reverse();
	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","title");
//	var tag=store.getMatchingTiddlers("TaskTabs && !Trash","title").reverse();
	var fmt="[[%0]] 'view %0' [[%0]]";
	var out="";
	for (var i=0; i<tag.length; i++)
		out+=(fmt.format([tag[i].title]));
//	alert(out);
	if (out.length) return "<<tabs tabTabsForTags "+out+">>";
		return "There are no tiddlers tagged with <<tag TaskTabs>>";
</script>@@text-align:left;~~&nbsp;<script>
	var projects= store.getTaggedTiddlers("TaskTabs").length.toString();
	var tasks= store.getTaggedTiddlers("Task").length.toString();
	var urgent= store.getMatchingTiddlers("Urgent && !Completed").length.toString();
	var pending= store.getMatchingTiddlers("Task && !Urgent && !Completed").length.toString();
	var completed= store.getTaggedTiddlers("Completed").length.toString();
return ("Status: " + projects + " Projects, " + tasks + " Tasks (" + urgent + " Urgent, " + pending + " Pending, " + completed + " Completed) ");
</script>~~@@

{{button{<script label="New Project">
   var title=prompt("Enter Project Tag (No Spaces or special characters)");
   var txt=store.getTiddlerText("ProjectTemplate", "").replace(/Project1/g, title);
   var who=config.options.txtUserName;
   var when=new Date();
   var tags='"TaskTabs" "excludeLists"';
   var fields={};
   store.saveTiddler(title,title,txt,who,when,tags,fields);
   story.refreshTiddler(story.findContainingTiddler(place).getAttribute("tiddler"),null,true);
</script>}}} <<deleteCompleted daysOld:30 title:'Delete Completed Tasks'>>
Task: Test Task Test Task Test Task Test Task Test Task Test Task
Reminder:<<newReminder>>
!!!Items
#
# Need to buy Item 01, 02 03
!!!Notes:
Test Data
!!!Due
<<reminder day:01 title:"Test Due Date" >>
<<reminder day:15 title:"Test Due Date" >>
<<reminder day:29 title:"Test Due Date" >>
Task: Test Task Test Task Test Task Test Task Test Task Test Task
Reminder:<<newReminder>>
!!!Items
#
#Need to buy Item 01, 02 03
!!!Notes:
Test Data
!!!Due
<<reminder day:01 title:"Test Due Date" >>
<<reminder day:15 title:"Test Due Date" >>
<<reminder day:29 title:"Test Due Date" >>
Task: Test Task Test Task Test Task Test Task Test Task Test Task
Reminder:<<newReminder>>
!!!Items
#
#Need to buy Item 01, 02 03
!!!Notes:
Test Data
!!!Due
<<reminder day:01 title:"Test Due Date" >>
<<reminder day:15 title:"Test Due Date" >>
<<reminder day:29 title:"Test Due Date" >>
Task: Test Task Test Task Test Task Test Task Test Task Test Task
Reminder:<<newReminder>>
!!!Items
#
#Need to buy Item 01, 02 03
!!!Notes:
Test Data
!!!Due
<<reminder day:01 title:"Test Due Date" >>
<<reminder day:15 title:"Test Due Date" >>
<<reminder day:29 title:"Test Due Date" >>
Task: Test Task Test Task Test Task Test Task Test Task Test Task
Reminder:<<newReminder>>
!!!Items
#
#Need to buy Item 01, 02 03
!!!Notes:
Test Data
!!!Due
<<reminder day:01 title:"Test Due Date" >>
<<reminder day:15 title:"Test Due Date" >>
<<reminder day:29 title:"Test Due Date" >>
<<tabs txtTestProject
'Urgent TestProject' 'Urgent TestProject Tab' TestProject##Urgent
'Pending TestProject' 'Pending TestProject Tab' TestProject##Pending
'Completed TestProject' 'Completed TestProject Tab' TestProject##Completed
>>
{{button{<script label="New Task">
 var newTiddler = new Tiddler();
 newTiddler.title = prompt('Enter a new task title','New Project Task');
 newTiddler.tags[0] = "TestProject";
 newTiddler.tags[1] = "Task";
 newTiddler.tags[2] = "excludeLists";
 newTiddler.modifier = config.options.txtUserName;
 if(config.macros.reminders){
 newTiddler.text = "Task:\nReminder: <<newReminder>>\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";
 } else {newTiddler.text = "Task:\n!!!Items\n#\n#\n!!!Notes\n\n!!!Due";}
 store.addTiddler(newTiddler);
 story.displayTiddler(null,newTiddler.title,DEFAULT_EDIT_TEMPLATE);
 story.focusTiddler(newTiddler.title,"title");
</script>}}} <<deleteAllTagged "Delete this Project" delete>>

@@display:none;
!!!Urgent
~~Urgent Items~~
<script>
//	var tag=store.getMatchingTiddlers("TestProject && Urgent && ! Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("TestProject && Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Pending
~~Pending Items~~
<script>
//	var tag=store.getMatchingTiddlers("TestProject && ! Urgent && ! Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("TestProject && ! Urgent && ! Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Reminders | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | ~~<<tiddler [[%0##Due]]>>~~ | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
!!!Completed
~~Completed Items~~
<script>
//	var tag=store.getMatchingTiddlers("TestProject && Completed && ! Trash","+title");
	var tag=store.getMatchingTiddlers("TestProject && Completed && ! Trash","modified").reverse();
	var hdr="|sortable|k\n| !Title | !Task | !Urgent? | !Complete? |h";
	var fmt="| [[%0|%0]] | %1 | [X(%0:Urgent)] | [X(%0:Completed)] |";
	var out=[hdr];
		if (!tag.length) out=["No Tiddlers found"];
	for (var i=0; i<tag.length; i++)
		out.push(fmt.format([tag[i].title,store.getTiddlerSlice(tag[i].title, "Task") ]));
	return out.join('\n');
</script>
@@
Task: Modify delete Plugins to use TrashPlugin if installed
Reminder: <<newReminder>>
!!!Items
#[[deleteAllTaggedPlugin]]
#[[deleteCompletedPlugin]]
!!!Notes

I've just refactored the TrashPlugin code to provide a suitable API:
   config.commands.deleteTiddler.sendToTrash(title)

For your purposes, you'll also want to check to make sure the function
exists before calling it, thus:
--------------------------
if (config.commands.deleteTiddler.sendToTrash)
   config.commands.deleteTiddler.sendToTrash(title);
else
   store.deleteTiddler(title);
--------------------------

Get the update (v1.1.0TT.5) here:
   http://www.TiddlyTools.com/#TrashPlugin

enjoy,
-e
Eric Shulman
TiddlyTools / ELS Design Studios 
!!!Due
/***
|Name:|TrashPlugin|
|Version:|1.1.0TT.5|
|Source:|http://www.TiddlyTools.com/#TrashPlugin|
|Author:|Eric Shulman|
|OriginalSource:|http://ido-xp.tiddlyspot.com/#TrashPlugin|
|OriginalAuthor:|Ido Magal (idoXatXidomagalXdotXcom)|
|License:|[[BSD open source license]]|
|CoreVersion:|2.1.0|
!Description
When you click on 'delete', instead of asking for confirmation and then permanently deleting the tiddler, TrashPlugin simply marks the tiddler by tagging it with: //trash, excludeLists, excludeMissing, excludeSearch,// and //systemConfigDisable//... and then closes that tiddler.  Empty the trash by clicking on the <<emptyTrash>> button in the [[Trash]] tiddler or, you can add the {{{<<emptyTrash>>}}} macro to your [[SideBarOptions]] or other appropriate location.  To reclaim something from the Trash, open the [[Trash]] tiddler to view a list of tiddlers tagged with 'trash', click on the desired tiddler title to open it, and then edit it's tags to remove the 'trash' tag (as well as the other tags noted above, as desired).  TrashPlugin also supports TWO keyboard modifiers that can be used when clicking on the 'delete' toolbar command:
* hold CTRL while clicking 'delete' to ''bypass the trash'' and use the normal delete handling (with the usual confirmation messages, if chkConfirmDelete is enabled).
* hold CTRL+SHIFT to ''bypass both the trash //and// the confirmation message'' and //immediately delete// the tiddler without any further interaction.
!Revisions
* V1.1.0TT.5 (TiddlyTools variant) (May 12, 2009)
** refactored code to add entry point: {{{config.commands.deleteTiddler.sendToTrash(title)}}}
* V1.1.0TT.4 (TiddlyTools variant) (Nov 14, 2008)
** added SHIFT-CLICK = bypass trash and delete immediately WITHOUT CONFIRMATION
* V1.1.0TT.3 (TiddlyTools variant) (Oct 14, 2008)
** return FALSE from emptyTrash() handler (fixes IE page transition error)
* V1.1.0TT.2 (TiddlyTools variant) (May 18, 2008)
** when creating the Trash tiddler, pass an empty tags array [] instead of a null value, so other plugins (e.g., InstantTimestampPlugin) won't fail
* V1.1.0TT.1 (TiddlyTools variant) (Dec 21, 2006) 
** only call setDirty() when actually removing tiddlers from trash
* V1.1.0 (Dec 12, 2006) 
** added movedMsg (feedback when tiddler is tagged as Trash)
** make sure tiddler actually exists before tagging it with 'Trash'
** fetch correct tiddler before checking for 'systemConfig' tag
* V1.0.3TT.1 (TiddlyTools variant) (Dec 11, 2006) 
** don't create Trash tiddler until needed
** remove Trash tiddler when no trash remains
** don't tag Trash tiddler with 'TrashPlugin'
** moved all user-visible strings to variables so they can be translated by 'lingo' plugins
** use displayMessage() instead of alert()
* v1.0.3 (Dec 11, 2006)
** Fixed broken reference to core deleteTiddler.
** Now storing reference to core deleteTiddler in emptyTrash macro.
** Reduced deleteTiddler hijacking to only the handler.
* v1.0.2 (Dec 11, 2006)
** EmptyTrash now uses removeTiddler instead of deleteTiddler.
** Supports trashing systemConfig tiddlers (adds systemConfigDisable tag).
* v1.0.1 (Dec 10, 2006)
** Replaced TW version with proper Core reference.
** Now properly hijacking deleteTiddler command.
* v1.0.0 (Dec 10, 2006)
** First draft.
!Code
***/
//{{{
config.macros.emptyTrash = {
	tag: 'Trash',
	movedMsg: "'%0' has been tagged as %1",
	label: 'empty trash',
	tooltip: 'Delete all items tagged as %0',
	tooltipOlder: 'Delete items tagged as %0 that are older than %1 days old',
	emptyMsg: 'The trash is empty',
	noneToDeleteMsg: 'There are no items in the trash older than %0 days',
	confirmMsg: "The following tiddlers will be deleted:\n\n'%0'\n\nIs it OK to proceed?",
	deletedMsg: "Deleted '%0'",
	handler: function ( place,macroName,params,wikifier,paramString,tiddler ) {
		var namedParams = (paramString.parseParams(daysOld))[0];
		var daysOld = namedParams['daysOld'] ? namedParams['daysOld'][0] : 0; // default
		var buttonTitle = namedParams['title'] ? namedParams['title'][0] : this.label;
		var buttonTip=this.tooltip.format([ config.macros.emptyTrash.tag ])
		if (daysOld) buttonTip=this.tooltipOlder.format([ config.macros.emptyTrash.tag,daysOld ])
		createTiddlyButton ( place, buttonTitle, buttonTip, this.emptyTrash( daysOld ));
	},
	emptyTrash: function( daysOld ) {
		return function() {
			var collected = [];
			var compareDate = new Date();
			compareDate.setDate( compareDate.getDate() - daysOld );
			store.forEachTiddler(function ( title,tiddler ) {
				if ( tiddler.tags.contains( config.macros.emptyTrash.tag ) && tiddler.modified < compareDate )
					collected.push( title );
			});
			if ( collected.length == 0 ) {
				if ( daysOld == 0 )
					displayMessage( config.macros.emptyTrash.emptyMsg );
				else
					displayMessage( config.macros.emptyTrash.emptyMsg.format( [daysOld] ) );
			}
			else {
				if (	confirm( config.macros.emptyTrash.confirmMsg.format( [collected.join( "', '" )] ) ) ) {
					for ( var i=0;i<collected.length;i++ ) {
						store.removeTiddler( collected[i] );
						store.setDirty( true );
						displayMessage( config.macros.emptyTrash.deletedMsg.format( [collected[i]] ) );
					}
				}
			}
			// remove Trash tiddler if no trash remains
			if ( store.getTaggedTiddlers( config.macros.emptyTrash.tag ).length == 0 ) {
				story.closeTiddler( config.macros.emptyTrash.tag,true,false);
				store.removeTiddler( config.macros.emptyTrash.tag );
			}
			else
				story.refreshTiddler( config.macros.emptyTrash.tag,false,true );

			return false; // ELS: fixes IE page transition error
		}
	}
}

////////////////// hijack delete command

config.commands.deleteTiddler.orig_handler = config.commands.deleteTiddler.handler;
config.commands.deleteTiddler.handler = function(event,src,title) {

	// BYPASS TRASH: CTRL=normal delete, CTRL+SHIFT=without confirmation
	if (event.ctrlKey) {
		if (event.shiftKey) { var temp=config.options.chkConfirmDelete; config.options.chkConfirmDelete=false; }
		config.commands.deleteTiddler.orig_handler.apply(this,arguments);
		if (event.shiftKey) config.options.chkConfirmDelete=temp;
		story.refreshTiddler(config.macros.emptyTrash.tag,false,true);
		return false;
	}
	config.commands.deleteTiddler.sendToTrash(title);
	return false;
};

config.commands.deleteTiddler.sendToTrash = function(title) {
	var cme=config.macros.emptyTrash; // abbrev
	if (!store.tiddlerExists(title)) return; // make sure tiddler actually exists
	if (!store.tiddlerExists(cme.tag)) // make sure Trash tiddler exists
		store.saveTiddler(cme.tag,cme.tag,'<<emptyTrash>>','TrashPlugin',new Date(),[],{});
	store.setTiddlerTag(title,1,cme.tag);
	store.setTiddlerTag(title,1,'excludeLists');
	store.setTiddlerTag(title,1,'excludeMissing');
	if (store.getTiddler(title).isTagged('systemConfig'))
		store.setTiddlerTag(title,1,'systemConfigDisable');
	story.closeTiddler(title,true);
	if(config.options.chkAutoSave) saveChanges();
	displayMessage(cme.movedMsg.format([title,cme.tag]));
	story.refreshTiddler(cme.tag,false,true);
};
//}}}
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span macro='tiddler ViewTemplate##Refresh'></span></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>

<div class='tagged' macro='tagging'><span macro='tags'></span></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>

<div style=display:none;>
!!!!!Refresh
{{button{<script label="refresh" title="redisplay the contents of this tiddler">
story.refreshTiddler(story.findContainingTiddler(place).getAttribute("tiddler"),null,true);</script>}}}
!!!!!End</div>
<!--}}}-->
/***
|Name:|deleteAllTaggedPlugin|
|Version:|1.8|
|Source:|http://www.STRM.us/Private/IJSTaskManager.htm#deleteAllTaggedPlugin|
|Author:|Mike Praeuner|
|OriginalSource:|http://ido-xp.tiddlyspot.com/#DeleteAllTaggedPlugin|
|OriginalAuthor:|Ido Magal (mailto:ido@idomagal.com)|
|CoreVersion:|2.4.3|
|Description|**Experimental** Delete Tiddler(s) tagged with Tiddler title + source tiddler |

!Revisions
*06.08.09 MTP v1.8
** change Refresh from story.refreshTiddler(story.findContainingTiddler(place).getAttribute("tiddler"),null,true); to refreshDisplay();
*05.21.09 MTP v1.7
**Clean up formatting, add TrashPluginCompatibility, disable autosave during operation, remove refresh until code fixed
*03.26.09 MTP v1.6
**Added tiddler refresh at end to remove deleted items from display
*01.29.09 MTP v1.5
**Does not match Source website, maintaining as a variant with delete source function
Original Concept (DeleteDoneTasks) by Simon Baird (mailto:simon.baird@gmail.com)
!Example
To use this insert {{{<<deleteAllTagged>>}}} into the desired tiddler.

Example usage:
{{{<<deleteAllTagged>>}}}
<<deleteAllTagged>>
Example + Delete Source Tiddler
{{{<<deleteAllTagged "delete these actions" delete>>}}}
<<deleteAllTagged "delete these actions" delete>>
!Code
***/
//{{{
config.macros.deleteAllTagged = {
	handler: function ( place,macroName,params,wikifier,paramString,tiddler ) {
		var buttonTitle = params[0] ? params[0] : "Delete Tagged w/ '"+tiddler.title+"'"; // simon's tweak
		var alsoDeleteThisTiddler = params[1] ? params[1] : "";
		createTiddlyButton( place, buttonTitle, "Delete every tiddler tagged with '"+tiddler.title+"'", this.deleteAllTagged( tiddler.title, alsoDeleteThisTiddler == "delete" ));
		config.options.chkAutosave=false;
	}, //end handler

	deleteAllTagged: function(tag,deleteMe) {
		return function() {
			var collected = [];
			store.forEachTiddler( function ( title,tiddler ) {
				if ( tiddler.tags.contains( tag )){
 					collected.push( title );
				} //end if
 			}); //end forEach

		if ( collected.length == 0 ){
			alert( "No tiddlers found tagged with '"+tag+"'." );
			} else {
			if ( confirm( "These tiddlers are tagged with '"+tag+"'\n'"
			+ collected.join( "', '" ) + "'\n\n\n"
			+ "Are you sure you want to delete these?" )){
				for ( var i=0;i<collected.length;i++ ){
					if (config.commands.deleteTiddler.sendToTrash){
						config.commands.deleteTiddler.sendToTrash(collected[i]);
						} else {
						store.deleteTiddler(collected[i]);
						displayMessage( "Deleted '"+collected[i]+"'" );
					} //end if else
				story.closeTiddler( collected[i], true );
				} //end for loop
			} //??
		} //end if collected

		if (deleteMe) {
			if ( confirm( "Also delete this tiddler ('"+tag+"')?" ) ) {
				if (config.commands.deleteTiddler.sendToTrash){
					config.commands.deleteTiddler.sendToTrash( tag );
					} else {
					store.deleteTiddler( tag );
					displayMessage( "Deleted '"+tag+"'" );
					story.refreshTiddler(story.findContainingTiddler(place).getAttribute("tiddler"),null,true);
				} //end if else
				story.closeTiddler( collected[i], true );
				story.closeTiddler( tag, true );
			} //end if confirm
		} //end if deleteMe
		config.options.chkAutosave=true;
		autoSaveChanges();
		refreshDisplay();
		} //end anonymous return function
	} //end deleteAllTagged function
}; //end deleteAllTagged macro
//}}}
/***
|Name:|deleteCompletedPlugin|
|Version:|1.8|
|Source:|http://www.STRM.us/Private/IJSTaskManager.htm#deleteCompletedPlugin|
|Author:|Mike Praeuner|
|OriginalSource:|http://ido-xp.tiddlyspot.com/#DeleteAllTaggedPlugin|
|OriginalAuthor:|Ido Magal (mailto:ido@idomagal.com)|
|CoreVersion:|2.4.3|
|Description|**Experimental** Delete Completed Tiddlers based on date modified and tag|

!Revisions
*06.08.09 MTP v1.8
** change Refresh from story.refreshTiddler(story.findContainingTiddler(place).getAttribute("tiddler"),null,true); to refreshDisplay();
*05.21.09 MTP v1.7
**Clean up formatting, add TrashPluginCompatibility, disable autosave during operation, remove refresh until code fixed
*03.26.09 MTP v1.6
**Added tiddler refresh at end to remove deleted items from display
*01.29.09 MTP v1.5
**Does not match Source website, maintaining as a variant with delete source function
Original Concept (DeleteDoneTasks) by Simon Baird (mailto:simon.baird@gmail.com)
!Example
Example usage: (For Items tagged Completed & Task)
{{{<<deleteCompleted>>}}}
<<deleteCompleted>>
{{{<<deleteCompleted daysOld:5 title:'Delete 5d'>>}}}
<<deleteCompleted daysOld:5 title:'Delete 5d'>>
{{{<<deleteCompleted daysOld:0 title:'Delete 0d'>>}}}
<<deleteCompleted daysOld:0 title:'Delete 0d'>>
!Code
***/
//{{{
config.macros.deleteCompleted = {
	handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		var namedParams = (paramString.parseParams('daysOld'))[0];
		var daysOld = namedParams['daysOld'] ? namedParams['daysOld'][0] : 30; // default
		var buttonTitle = namedParams['title'] ? namedParams['title'][0] : "Delete Completed Actions";
		createTiddlyButton(place,buttonTitle,"Delete Completed actions older than "+daysOld+" days old",this.deleteCompleted(daysOld));
		config.options.chkAutosave=false;
	}, //end handler

	deleteCompleted: function(daysOld) {
		return function() {
 			var collected = [];
 			var compareDate = new Date();
 			compareDate.setDate(compareDate.getDate() - daysOld);
	 		store.forEachTiddler(function (title,tiddler) {
 				if (tiddler.tags.containsAll(["Completed" , "Task"]) && tiddler.modified < compareDate) {
 					collected.push(title);
 				} //end if
			}); //end forEach

	if (collected.length == 0) {
		alert("No Completed actions found older than "+daysOld+" days");
		} else {
		if (confirm("Completed actions older than "+daysOld+" days:\n'"
		+ collected.join("', '") + "'\n\n\n"
		+ "Are you sure you want to delete these actions?")) {
			for (var i=0;i<collected.length;i++) {
				if (config.commands.deleteTiddler.sendToTrash) {
					config.commands.deleteTiddler.sendToTrash(collected[i]);
					} else {
					store.deleteTiddler(collected[i]);
					displayMessage("Deleted '"+collected[i]+"'");
				} //end if else
			story.closeTiddler( collected[i], true );;
			} //end for loop
			config.options.chkAutosave=true;
			autoSaveChanges()
			refreshDisplay();
			} //??
		} //end collected else
		} //end anonymous return function
	}  //end deleteCompleted function

}; //end deleteCompleted Macro
//}}}
Task: Test Task Test Task Test Task Test Task Test Task Test Task
Reminder:<<newReminder>>
!!!Items
#
#Need to buy Item 01, 02 03
!!!Notes:
Test Data
!!!Due
<<reminder day:01 title:"Test Due Date" >>
<<reminder day:15 title:"Test Due Date" >>
<<reminder day:29 title:"Test Due Date" >>
/***
|Name:|zConfig|
|Version:|1.0|
|Source:|http://www.STRM.us/Private/IJSTaskManager.htm#zConfig|
|Author:|Mike Praeuner|
|CoreVersion:|2.4.3|
|Description|Hard code cookies & modify shadow tiddlers|
***/
{{{
config.options.txtUserName="About";
config.options.txtBackupFolder="Backup";
config.options.chkAnimate=false;
config.options.chkSaveBackups=false;
config.options.chkAutoSave=true;
config.options.chkHttpReadOnly = false; // means web visitors can experiment with your site by clicking edit
readOnly = false; // Always editable
config.options.chkInsertTabs = true;    // tab inserts a tab when editing a tiddler
config.views.wikified.defaultText = ""; // don't need message when a tiddler doesn't exist
config.views.editor.defaultText = "";   // don't need message when creating a new tiddler

// Modify Shadow Tiddler Site Information
merge(config.shadowTiddlers,{
	SiteTitle: "Task Manager v<<tiddler 'TaskManagerPlugin::Version'>>",
	SiteSubtitle: "~TiddlyWiki v<<version>>",
	SiteUrl: "http://www.strm.us/Private/IJSTaskManager.htm",
	DefaultTiddlers: "[[Task Manager]][[Download]]",
	});
}}}