<!--{{{-->
<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 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 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:0 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 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

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

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

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding: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 0;}
.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 0 0 0.5em;}
.tab {margin:0 0 0 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 0 14em;}

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

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

.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:0 0.25em; padding:0 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 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin: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;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding: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;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<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>>
<<gtdActionList>>
<<gtdActionList>>
<<gtdActionList>>
Dieses Notizbuch versucht eine Umsetzung des [["kinkless" GTD system|http://www.kinkless.com]] mittels der [[TiddlyWiki-Software|http://www.tiddlywiki.com]], Version <<version>> (von Jeremy Ruston) und deren Erweiterung GTD plugin, Version <<gtdVersion>> (von Tom Otvos). Zum Anpassen dieses Notizbuchs und zum Erstellen eigener Erweiterungen vgl. [[GTD TiddlyWiki|http://groups.google.com/group/GTD-TiddlyWiki]] und [[TiddlyWikiDev|http://www.tiddlywiki.com/dev/]].

''~TiddlyWiki'' = ~Mikro-Wiki in einer einzelnen Datei, die sowohl ~JavaScript-Programmcode als auch Nutzdaten (="Tiddler", quasi Seiten eines Notizbuchs) enthält. Diese Form eines Wiki wird gerne für persönliche Notizbücher verwendet. Man liest und bearbeitet die Daten (Notizen) mittels eines Webbrowsers in der gleichen Weise, wie man einen Text mit einem Textverarbeitungsprogramm bearbeiten würde. Dadurch, dass alles in einer einzelnen Datei gespeichert ist, lässt sich ein ~TiddlyWiki einfach sichern und transportieren (z.B. auf einem ~USB-Speicherstick).
''GTD'' = //Getting Things Done//, eine Methode zur Selbstorganisation, die darauf abzielt, "jederzeit" einen Überblick über "alles" zu haben und dadurch "den Kopf frei zu bekommen". GTD erfordert die Disziplin, einzelne Tätigkeiten und Projekte (mehrere in Zusammenhang stehende Tätigkeiten) niederzuschreiben, und (u.a.) nach Kontexten zu ordnen. Insbesondere muss dabei immer ein "nächster Schritt" existieren und formuliert sein.

Anpassungen von ~ErwinLottemann:
* CookieJar, CookieSaverPlugin and CookieManagerPlugin hinzugefügt (um Einstellungen, die normalerweise als ~Browser-Cookie gespeichert werden, im ~TiddlyWiki speichern zu können)
* YourSearchPlugin hinzugefügt
* Version history entfernt (die Zeitrechnung beginnt mit TW 2.4.1, ~GTDPlugin 1.3.0)
* Sprachanpassung deutsch von [[karadeniz.de|http://karadeniz.de/tiddlywiki/]]
* Einzelne Übersetzungen (nicht durchgängig, sorry)
* Kleinkram (Änderungen in ~StyleSheets, Einstellungen, etc.)

~GTD-Buch (deutsch): Allen, David: "Wie ich die Dinge geregelt kriege", ~Piper-Verlag, München, 2002 (ISBN 978-3-492-24060-4). Taschenbuch, &euro;9,95

~TiddlyWiki- und ~GTD-Links ''intern'' (englisch):
* [[TiddlyWiki]]
* [[GettingStarted]]

~TiddlyWiki- und ~GTD-Links ''extern'' (deutsch und englisch):
* ~TiddlyWiki
** [[Wikipedia TiddlyWiki-Artikel|http://de.wikipedia.org/wiki/TiddlyWiki]]
** [[TiddlyWiki-Handbuch (deutsch)|http://www.tiddlywikihandbuch.de/tiddlywikihandbuch.html]]
** [[tiddlywiki.org|http://www.tiddlywiki.org/]]
** [[TiddlyWiki-Handbuch (englisch)|http://www.blogjones.com/TiddlyWikiTutorial.html#EasyToEdit]]
* GTD (//Getting Things Done//)
** [[Wikipedia GTD-Artikel|http://de.wikipedia.org/wiki/Getting_Things_Done]]
** [[GTD in einer Nusschale|http://tautoko.info/2005/06/13/gtd-in-einer-nusschale/]]
** [[imgriff.com GTD Grundlagen|http://imgriff.com/serien/gtd-grundlagen/]]
** [[zeitzuleben.de GTD Einführung|http://www.zeitzuleben.de/artikel/persoenlichkeit/getting-thins-done-david-allen.html]]
** [[GTD Primer (engl.)|http://7pproductions.com/blog/2008/02/18/a-primer-on-getting-things-done/]]
! Nächste Tätigkeiten in aktiven Kontexten
<<gtdActionList @>>
To make this system operate more efficiently, you should periodically archive completed projects and actions. When a project or action is archived, it is merely tagged in a special way to get it "out of sight", but all the information in the project and action tiddlers is preserved. This is important if you need to go back and find something. Click one of these buttons to view the current <<tag project-archive>> or <<tag action-archive>>.

** Click <<gtdArchive archive>> if you would like to archive all completed projects and actions now.
** Click <<gtdArchive unarchive>> if you would like to unarchive all previously archived projects and actions now.

If you are sure that you do not want to retain archived projects and actions, you can purge them completely from the system. //Once these archived items are removed, the only way they can be put back in is through manual importing or copy/paste.// ''For your safety, your file will be saved and a backup file will be automatically generated before an archive purge is performed.''

** Click <<gtdArchive purge>> if you would like to purge your archive now.


/***
|Name|CalendarPlugin|
|Source|http://www.TiddlyTools.com/#CalendarPlugin|
|Version|2008.06.17|
|Author|Eric Shulman|
|Original Author|SteveRumsby|
|License|unknown|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|display monthly and yearly calendars|

NOTE: For enhanced date display (including popups), you must also install [[DatePlugin]]
!!!!!Usage:
<<<
|{{{<<calendar>>}}}|Produce a full-year calendar for the current year|
|{{{<<calendar year>>}}}|Produce a full-year calendar for the given year|
|{{{<<calendar year month>>}}}|Produce a one-month calendar for the given month and year|
|{{{<<calendar thismonth>>}}}|Produce a one-month calendar for the current month|
|{{{<<calendar lastmonth>>}}}|Produce a one-month calendar for last month|
|{{{<<calendar nextmonth>>}}}|Produce a one-month calendar for next month|
<<<
!!!!!Configuration:
<<<
|''First day of week:''<br>{{{config.options.txtCalFirstDay}}}|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
|''First day of weekend:''<br>{{{config.options.txtCalStartOfWeekend}}}|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|

<<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//
|''Week number display format:''<br>{{{config.options.txtWeekNumberDisplayFormat }}}|<<option txtWeekNumberDisplayFormat >>|
|''Week number link format:''<br>{{{config.options.txtWeekNumberLinkFormat }}}|<<option txtWeekNumberLinkFormat >>|
<<<
!!!!!Revisions
<<<
2008.06.17: added support for config.macros.calendar.todaybg
2008.02.27: in handler(), DON'T set hard-coded default date format, so that *customized* value (pre-defined in config.macros.calendar.journalDateFmt is used.
2008.02.17: in createCalendarYear(), fix next/previous year calculation (use parseInt() to convert to numeric value).  Also, use journalDateFmt for date linking when NOT using [[DatePlugin]].
2008.02.16: in createCalendarDay(), week numbers now created as TiddlyLinks, allowing quick creation/navigation to 'weekly' journals (based on request from Kashgarinn)
2008.01.08: in createCalendarMonthHeader(), "month year" heading is now created as TiddlyLink, allowing quick creation/navigation to 'month-at-a-time' journals
2007.11.30: added "return false" to onclick handlers (prevent IE from opening blank pages)
2006.08.23: added handling for weeknumbers (code supplied by Martin Budden (see "wn**" comment marks).  Also, incorporated updated by Jeremy Sheeley to add caching for reminders (see [[ReminderMacros]], if installed)
2005.10.30: in config.macros.calendar.handler(), use "tbody" element for IE compatibility.  Also, fix year calculation for IE's getYear() function (which returns '2005' instead of '105'). Also, in createCalendarDays(), use showDate() function (see [[DatePlugin]], if installed) to render autostyled date with linked popup.  Updated calendar stylesheet definition: use .calendar class-specific selectors, add text centering and margin settings
2006.05.29: added journalDateFmt handling
<<<
***/
/***
!!!!!Code section:
***/
//{{{
version.extensions.calendar = { major: 0, minor: 7, revision: 0, date: new Date(2008, 6, 17)};

if(config.options.txtCalFirstDay == undefined)
  config.options.txtCalFirstDay = 0;
if(config.options.txtCalStartOfWeekend == undefined)
  config.options.txtCalStartOfWeekend = 5;
if(config.options.chkDisplayWeekNumbers == undefined)//wn**
  config.options.chkDisplayWeekNumbers = false;
if(config.options.chkDisplayWeekNumbers)
  config.options.txtCalFirstDay = 0;
if(config.options.txtWeekNumberDisplayFormat == undefined)//wn**
  config.options.txtWeekNumberDisplayFormat = "w0WW";
if(config.options.txtWeekNumberLinkFormat == undefined)//wn**
  config.options.txtWeekNumberLinkFormat = "YYYY-w0WW";

config.macros.calendar = {};
config.macros.calendar.monthnames = ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
config.macros.calendar.daynames = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];
config.macros.calendar.todaybg = "#ccccff";
config.macros.calendar.weekendbg = "#c0c0c0";
config.macros.calendar.monthbg = "#e0e0e0";
config.macros.calendar.holidaybg = "#ffc0c0";
config.macros.calendar.journalDateFmt = "DD MMM YYYY";
config.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
config.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead
//}}}
//{{{
function calendarIsHoliday(date) // Is the given date a holiday?
{
	var longHoliday = date.formatString("0DD/0MM/YYYY");
	var shortHoliday = date.formatString("0DD/0MM");
	for(var i = 0; i < config.macros.calendar.holidays.length; i++) {
		if(config.macros.calendar.holidays[i] == longHoliday || config.macros.calendar.holidays[i] == shortHoliday)
			return true;
	}
	return false;
}
//}}}
//{{{
config.macros.calendar.handler = function(place,macroName,params) {
	var calendar = createTiddlyElement(place, "table", null, "calendar", null);
	var tbody = createTiddlyElement(calendar, "tbody", null, null, null);
	var today = new Date();
	var year = today.getYear();
	if (year<1900) year+=1900;

 	// get format for journal link by reading from SideBarOptions (ELS 5/29/06 - based on suggestion by Martin Budden)
	var text = store.getTiddlerText("SideBarOptions");
	var re = new RegExp("<<(?:newJournal)([^>]*)>>","mg"); var fm = re.exec(text);
	if (fm && fm[1]!=null) { var pa=fm[1].readMacroParams(); if (pa[0]) this.journalDateFmt = pa[0]; }

	if (params[0] == "thismonth") {
		cacheReminders(new Date(year, today.getMonth(), 1, 0, 0), 31);
		createCalendarOneMonth(tbody, year, today.getMonth());
	} 
	else if (params[0] == "lastmonth") {
		var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
		cacheReminders(new Date(year, month, 1, 0, 0), 31);
		createCalendarOneMonth(tbody, year, month);
	}
	else if (params[0] == "nextmonth") {
		var month = today.getMonth()+1; if (month>11) { month=0; year++; }
		cacheReminders(new Date(year, month, 1, 0, 0), 31);
		createCalendarOneMonth(tbody, year, month);
	} else {
		if (params[0]) year = params[0];
		if(params[1]) {
			cacheReminders(new Date(year, params[1]-1, 1, 0, 0), 31);
			createCalendarOneMonth(tbody, year, params[1]-1);
		} else {
			cacheReminders(new Date(year, 0, 1, 0, 0), 366);
			createCalendarYear(tbody, year);
		}
	}
	window.reminderCacheForCalendar = null;
}
//}}}
//{{{
//This global variable is used to store reminders that have been cached
//while the calendar is being rendered.  It will be renulled after the calendar is fully rendered.
window.reminderCacheForCalendar = null;
//}}}
//{{{
function cacheReminders(date, leadtime)
{
	if (window.findTiddlersWithReminders == null) return;
	window.reminderCacheForCalendar = {};
	var leadtimeHash = [];
	leadtimeHash [0] = 0;
	leadtimeHash [1] = leadtime;
	var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);
	for(var i = 0; i < t.length; i++) {
		//just tag it in the cache, so that when we're drawing days, we can bold this one.
		window.reminderCacheForCalendar[t[i]["matchedDate"]] = "reminder:" + t[i]["params"]["title"]; 
	}
}
//}}}
//{{{
function createCalendarOneMonth(calendar, year, mon)
{
	var row = createTiddlyElement(calendar, "tr", null, null, null);
	createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);
	row = createTiddlyElement(calendar, "tr", null, null, null);
	createCalendarDayHeader(row, 1);
	createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarMonth(calendar, year, mon)
{
	var row = createTiddlyElement(calendar, "tr", null, null, null);
	createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, false, year, mon);
	row = createTiddlyElement(calendar, "tr", null, null, null);
	createCalendarDayHeader(row, 1);
	createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarYear(calendar, year)
{
	var row;
	row = createTiddlyElement(calendar, "tr", null, null, null);
	var back = createTiddlyElement(row, "td", null, null, null);
	var backHandler = function() {
		removeChildren(calendar);
		createCalendarYear(calendar, parseInt(year)-1);
		return false; // consume click
	};
	createTiddlyButton(back, "<", "Previous year", backHandler);
	back.align = "center";
	var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);
	yearHeader.align = "center";
	yearHeader.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?22:19);//wn**
	var fwd = createTiddlyElement(row, "td", null, null, null);
	var fwdHandler = function() {
		removeChildren(calendar);
		createCalendarYear(calendar, parseInt(year)+1);
		return false; // consume click
	};
	createTiddlyButton(fwd, ">", "Next year", fwdHandler);
	fwd.align = "center";
	createCalendarMonthRow(calendar, year, 0);
	createCalendarMonthRow(calendar, year, 3);
	createCalendarMonthRow(calendar, year, 6);
	createCalendarMonthRow(calendar, year, 9);
}
//}}}
//{{{
function createCalendarMonthRow(cal, year, mon)
{
	var row = createTiddlyElement(cal, "tr", null, null, null);
	createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);
	createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);
	createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);
	row = createTiddlyElement(cal, "tr", null, null, null);
	createCalendarDayHeader(row, 3);
	createCalendarDayRows(cal, year, mon);
}
//}}}
//{{{
function createCalendarMonthHeader(cal, row, name, nav, year, mon)
{
	var month;
	if (nav) {
		var back = createTiddlyElement(row, "td", null, null, null);
		back.align = "center";
		back.style.background = config.macros.calendar.monthbg;

		var backMonHandler = function() {
			var newyear = year;
			var newmon = mon-1;
			if(newmon == -1) { newmon = 11; newyear = newyear-1;}
			removeChildren(cal);
			cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
			createCalendarOneMonth(cal, newyear, newmon);
			return false; // consume click
		};
		createTiddlyButton(back, "<", "Previous month", backMonHandler);
		month = createTiddlyElement(row, "td", null, "calendarMonthname")
		createTiddlyLink(month,name,true);
		month.setAttribute("colSpan", config.options.chkDisplayWeekNumbers?6:5);//wn**
		var fwd = createTiddlyElement(row, "td", null, null, null);
		fwd.align = "center";
		fwd.style.background = config.macros.calendar.monthbg; 

		var fwdMonHandler = function() {
			var newyear = year;
			var newmon = mon+1;
			if(newmon == 12) { newmon = 0; newyear = newyear+1;}
			removeChildren(cal);
			cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
			createCalendarOneMonth(cal, newyear, newmon);
			return false; // consume click
		};
		createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);
	} else {
		month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
		month.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?8:7);//wn**
	}
	month.align = "center";
	month.style.background = config.macros.calendar.monthbg;
}
//}}}
//{{{
function createCalendarDayHeader(row, num)
{
	var cell;
	for(var i = 0; i < num; i++) {
		if (config.options.chkDisplayWeekNumbers) createTiddlyElement(row, "td");//wn**
		for(var j = 0; j < 7; j++) {
			var d = j + (config.options.txtCalFirstDay - 0);
			if(d > 6) d = d - 7;
			cell = createTiddlyElement(row, "td", null, null, config.macros.calendar.daynames[d]);
			if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))
				cell.style.background = config.macros.calendar.weekendbg;
		}
	}
}
//}}}
//{{{
function createCalendarDays(row, col, first, max, year, mon) {
	var i;
	if (config.options.chkDisplayWeekNumbers){
		if (first<=max) {
			var ww = new Date(year,mon,first);
			var td=createTiddlyElement(row, "td");//wn**
			var link=createTiddlyLink(td,ww.formatString(config.options.txtWeekNumberLinkFormat),false);
			link.appendChild(document.createTextNode(ww.formatString(config.options.txtWeekNumberDisplayFormat)));
		}
		else createTiddlyElement(row, "td", null, null, null);//wn**
	}
	for(i = 0; i < col; i++)
		createTiddlyElement(row, "td", null, null, null);
	var day = first;
	for(i = col; i < 7; i++) {
		var d = i + (config.options.txtCalFirstDay - 0);
		if(d > 6) d = d - 7;
		var daycell = createTiddlyElement(row, "td", null, null, null);
		var isaWeekend = ((d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))? true:false);
		if(day > 0 && day <= max) {
			var celldate = new Date(year, mon, day);
			// ELS 2005.10.30: use <<date>> macro's showDate() function to create popup
			// ELS 5/29/06 - use journalDateFmt 
			if (window.showDate)
				showDate(daycell,celldate,"popup","DD",config.macros.calendar.journalDateFmt,true, isaWeekend);
			else {
				if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
				var title = celldate.formatString(config.macros.calendar.journalDateFmt);
				if(calendarIsHoliday(celldate))
					daycell.style.background = config.macros.calendar.holidaybg;
				var now=new Date();
				if ((now-celldate>=0) && (now-celldate<86400000)) // is today?
					daycell.style.background = config.macros.calendar.todaybg;
				if(window.findTiddlersWithReminders == null) {
					var link = createTiddlyLink(daycell, title, false);
					link.appendChild(document.createTextNode(day));
				} else
					var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
			}
		}
		day++;
	}
}
//}}}
//{{{
// We've clicked on a day in a calendar - create a suitable pop-up of options.
// The pop-up should contain:
//  * a link to create a new entry for that date
//  * a link to create a new reminder for that date
//  * an <hr>
//  * the list of reminders for that date
// NOTE: The following code is only used when [[DatePlugin]] is not present
function onClickCalendarDate(e)
{
	var button = this;
	var date = button.getAttribute("title");
	var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));

	date = dat.formatString(config.macros.calendar.journalDateFmt);
	var popup = createTiddlerPopup(this);
	popup.appendChild(document.createTextNode(date));
	var newReminder = function() {
		var t = store.getTiddlers(date);
		displayTiddler(null, date, 2, null, null, false, false);
		if(t) {
			document.getElementById("editorBody" + date).value += "\n<<reminder day:" + dat.getDate() +
				" month:" + (dat.getMonth()+1) + " year:" + (dat.getYear()+1900) + " title: >>";
		} else {
			document.getElementById("editorBody" + date).value = "<<reminder day:" + dat.getDate() +
				" month:" + (dat.getMonth()+1) +" year:" + (dat.getYear()+1900) + " title: >>";
		}
		return false; // consume click
	};
	var link = createTiddlyButton(popup, "New reminder", null, newReminder); 
	popup.appendChild(document.createElement("hr"));
	var t = findTiddlersWithReminders(dat, [0,14], null, 1);
	for(var i = 0; i < t.length; i++) {
		link = createTiddlyLink(popup, t[i].tiddler, false);
		link.appendChild(document.createTextNode(t[i].tiddler));
	}
	return false; // consume click
}
//}}}
//{{{
function calendarMaxDays(year, mon)
{
	var max = config.macros.calendar.monthdays[mon];
	if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) max++;
	return max;
}
//}}}
//{{{
function createCalendarDayRows(cal, year, mon)
{
	var row = createTiddlyElement(cal, "tr", null, null, null);
	var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
	if(first1 < 0) first1 = first1 + 7;
	var day1 = -first1 + 1;
	var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
	if(first2 < 0) first2 = first2 + 7;
	var day2 = -first2 + 1;
	var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
	if(first3 < 0) first3 = first3 + 7;
	var day3 = -first3 + 1;

	var max1 = calendarMaxDays(year, mon);
	var max2 = calendarMaxDays(year, mon+1);
	var max3 = calendarMaxDays(year, mon+2);

	while(day1 <= max1 || day2 <= max2 || day3 <= max3) {
		row = createTiddlyElement(cal, "tr", null, null, null);
		createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
		createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;
		createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;
	}
}
//}}}
//{{{
function createCalendarDayRowsSingle(cal, year, mon)
{
	var row = createTiddlyElement(cal, "tr", null, null, null);
	var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
	if(first1 < 0) first1 = first1+ 7;
	var day1 = -first1 + 1;
	var max1 = calendarMaxDays(year, mon);
	while(day1 <= max1) {
		row = createTiddlyElement(cal, "tr", null, null, null);
		createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
	}
}
//}}}
//{{{
setStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }", "calendarStyles");
//}}}
/***
|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;
	}
}
//}}}
These configuration options enable you to customize the default behaviour of this wiki. They are saved locally as cookies, just like other TiddlyWiki configuration options. Note that in some cases, you will need to reload the document for the changes to take effect.

!!Action display settings
This value, if specified, is a semi-colon-delimited list of tags that are used to prioritize projects and actions for those projects. If left blank, the single priority tag "important" is used to sort projects. Otherwise, the specified tags are used in the listed order of importance, the first tag being most important (you will need to reload the document to see your change):
<<option txtGTDProjectPriorities>>

This value, if specified, is the number of days to keep completed actions in context and review action lists (leave blank to show all unarchived, completed actions):
<<option txtGTDActionAging>>

!!Magic tags
The following tag is used for the "reference" context, used to identify tiddlers that show up in the [[Reference]] list: 
<<option txtGTDReferenceContext>>

The following tag is used for the "someday-maybe" context, used to identify tiddlers that show up in the [[Someday-Maybe]] list:
<<option txtGTDSomedayContext>>

The following tag is used for the "unfiled" context, used to tag actions when the context is not known (such as orphaned actions from a deleted context):
<<option txtGTDUnfiledContext>>

!!Miscellaneous functionality
<<option chkGTDLazyAutoSave>> Use this checkbox to enable or disable "lazy" autosaving of changes to your document. If turned on, then the autosave will fire every <<option txtGTDLazyAutoSaveInterval>> seconds.


/***
<<tiddler CookieManager>>
***/
/***
!!![[Portable cookies:|CookieSaverPlugin]] {{fine{<<option chkPortableCookies>>enable <<option chkMonitorCookieJar>>monitor}}}
^^This section is ''//__automatically maintained__//'' by [[CookieSaverPlugin]].  To block specific cookies, see [[CookieSaverPluginConfig]].^^
***/
//{{{
if (config.options.txtUserName=="ErwinLottemann" && config.options.chkPortableCookies) {
	config.options.txtMoreTab="Schatten";
}
//}}}
// // /% end portable cookies %/
/***
!!![[Baked cookies:|CookieManagerPlugin]]
^^Press {{smallform{<<cookieManager button>>}}} to save the current browser cookies... then hand-edit this section to customize the results.^^
***/

// 5 cookies saved on Tuesday, April 8th 2008 at 17:30:05 by ELSDesignStudios//
//^^(edit/remove username check and/or individual option settings as desired)^^//
//{{{
if (config.options.txtUserName=="ELSDesignStudios" || config.options.txtUserName=="Eric") {
	config.options.chkInsertTabs=true;
	config.options.chkSearchByDate=true;
	config.options.chkTOCIncludeHidden=true;
	config.options.txtUploadUserName="ELSDesignStudios";
	config.options.txtUploadBackupDir="backup";
	config.options.txtUploadStoreUrl="http://www.tiddlytools.com/store.php";
	config.options.txtPrivWizardDefaultStep="2";
}
//}}}
// The following settings are applied as defaults for all users: //
//{{{
	config.options.txtMaxEditRows=30;
	config.options.txtTiddlerLinkTootip='%0 - %2 (%3 bytes) - %4';
	if (!config.options.txtTheme.length) config.options.txtTheme='StyleSheet';

	// Make sure FAQ panels are *always* closed on startup (so load-on-demand can be used later on):
	config.options.chkSliderWelcomeShowFAQ=false;	saveOptionCookie('chkSliderWelcomeShowFAQ');
	config.options.chkSliderMainMenu_faq=false;	saveOptionCookie('chkSliderMainMenu_faq');
	config.options.chkSliderSiteMenu_faq=false;	saveOptionCookie('chkSliderSiteMenu_faq');
//}}}

// 73 options saved on Dienstag, Februar 17th 2009 at 11:44:03 by ErwinLottemann//
//^^(edit/remove username check and/or individual option settings as desired)^^//
//{{{
if (config.options.txtUserName=="ErwinLottemann") {
	config.options.chkAllowBrowserCookies=true;
	config.options.chkAnimate=true;
	config.options.chkAutoSave=false;
	config.options.chkBackstage=false;
	config.options.chkCaseSensitiveSearch=false;
	config.options.chkConfirmDelete=true;
	config.options.chkCookieJarAddToAdvancedOptions=true;
	config.options.chkCookieManagerAddToAdvancedOptions=true;
	config.options.chkDisplayInstrumentation=false;
	config.options.chkDisplayWeekNumbers=true;
	config.options.chkFloatingSlidersAnimate=false;
	config.options.chkForceMinorUpdate=false;
	config.options.chkGTDFancyStyle=true;
	config.options.chkGTDLazyAutoSave=true;
	config.options.chkGTDReleaseNotes=false;
	config.options.chkGenerateAnRssFeed=false;
	config.options.chkHideMissingMacros=false;
	config.options.chkHttpReadOnly=true;
	config.options.chkIncrementalSearch=true;
	config.options.chkInsertTabs=false;
	config.options.chkLooseLinks=false;
	config.options.chkMonitorBrowserCookies=false;
	config.options.chkMonitorCookieJar=false;
	config.options.chkOpenInNewWindow=true;
	config.options.chkPortableCookies=true;
	config.options.chkPreviewText=true;
	config.options.chkRegExpSearch=false;
	config.options.chkSaveBackups=true;
	config.options.chkSaveEmptyTemplate=false;
	config.options.chkSearchAsYouType=true;
	config.options.chkSearchExtendedFields=true;
	config.options.chkSearchInTags=true;
	config.options.chkSearchInText=true;
	config.options.chkSearchInTitle=true;
	config.options.chkSliderMainMenu_faq=false;
	config.options.chkSliderOptionsPanel=true;
	config.options.chkSliderSiteMenu_faq=false;
	config.options.chkSliderWelcomeShowFAQ=false;
	config.options.chkSlidergtdActionsSliderState=false;
	config.options.chkSlidergtdImportantProjectsSliderState=false;
	config.options.chkSlidergtdOtherProjectsSliderState=false;
	config.options.chkSlidergtdProjectsSliderState=false;
	config.options.chkSlidergtdReferenceSliderState=true;
	config.options.chkSlidergtdReviewSliderState=false;
	config.options.chkSlidergtdSomedaySliderState=false;
	config.options.chkToggleLinks=false;
	config.options.chkUsePreForStorage=true;
	config.options.chkUseYourSearch=true;
	config.options.txtBackupFolder=".twBackups";
	config.options.txtCalFirstDay="0";
	config.options.txtCalStartOfWeekend="5";
	config.options.txtCookieJar="CookieJar";
	config.options.txtEditorFocus="text";
	config.options.txtFileSystemCharSet="UTF-8";
	config.options.txtGTDActionAging="";
	config.options.txtGTDLazyAutoSaveInterval="300";
	config.options.txtGTDProjectPriorities="";
	config.options.txtGTDReferenceContext="reference";
	config.options.txtGTDSomedayContext="someday";
	config.options.txtGTDUnfiledContext="unfiled";
	config.options.txtItemsPerPage="25";
	config.options.txtItemsPerPageWithPreview="10";
	config.options.txtMainTab="Alles";
	config.options.txtMaxEditRows="30";
	config.options.txtMoreTab="Fehlend";
	config.options.txtTheme="StyleSheet";
	config.options.txtTiddlerLinkTooltipDate="DDD, MMM DDth YYYY 0hh12:0mm AM";
	config.options.txtTiddlerLinkTootip="%0 - %2 (%3 bytes) - %4";
	config.options.txtUploadStoreUrl="store.php";
	config.options.txtUploadUserName="ErwinLottemann";
	config.options.txtUserName="ErwinLottemann";
	config.options.txtWeekNumberDisplayFormat="KW0WW";
	config.options.txtWeekNumberLinkFormat="YYYY-kw0WW";
}
//}}}
/***
|Name|CookieManagerPlugin|
|Source|http://www.TiddlyTools.com/#CookieManagerPlugin|
|Version|2.3.2|
|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||
|Options|##Configuration|
|Description|view/add/delete browser-based cookies and "bake" cookies to CookieJar tiddler for 'sticky' settings|
!!!!!Usage
<<<
This plugin provides an interactive control panel that lets you select, view, modify, or delete any of the current values for TiddlyWiki options that have been stored as local, private, //browser cookies//.  You can also use the control panel to "bake cookies", which generates a set of javascript statements that assign hard-coded option values to the TiddlyWiki internal variables that correspond to the current browser cookie settings.  These hard-coded values are then stored in the [[CookieJar]] tiddler, which is tagged with<<tag systemConfig>> so that each time the document is loaded, the baked cookie settings will be automatically applied.

When a set of baked cookies is added to the [[CookieJar]], it is automatically surrounded by a conditional test so that the hard-coded settings will only be applied for the username that was in effect when they were initially generated.  In this way, if you publish or share your document with others, //your// particular baked cookie settings are not automatically applied to others, so that their own browser-based cookie settings (if defined) will be applied as usual.

Whenever you "bake cookies", new hard-coded javascript assignment statements are *appended* to the end of the [[CookieJar]].  However, any baked cookies that were previously generated and stored in the [[CookieJar]] are not automatically removed from the tiddler.  As a result, because the most recently baked cookie settings in the [[CookieJar]] are always the last to be processed, the values assigned by older baked cookies are immediately overridden by the values from the newest baked cookies, so that the newest values will be in effect when the CookieJar startup processing is completed.

Each time you bake a new batch of cookies, it is recommended that you should review and hand-edit the [[CookieJar]] to remove any "stale cookies" or merge the old and new sets of baked cookies into a single block to simplify readability (as well as saving a little tiddler storage space).  Of course, you can also hand-edit the [[CookieJar]] tiddler at any time simply to remove a few individual //baked cookies// if they are no longer needed, and you can even delete the entire [[CookieJar]] tiddler and start fresh, if that is appropriate.  Please note that changing or deleting a baked cookie does not alter the current value of the corresponding option setting, and any changes you make to the [[CookieJar]] will only be applied after you have saved and reloaded the document in your browser.
<<<
!!!!!Examples
<<<
{{{<<cookieManager>>}}}
{{smallform small center{
@@display:block;width:35em;<<cookieManager>>@@}}}
<<<
!!!!!Configuration
<<<
<<option chkAllowBrowserCookies>> store ~TiddlyWiki option settings using private browser cookies
<<option chkMonitorBrowserCookies>> monitor browser cookie activity (show a message whenever a cookie is set or deleted)
<<option chkCookieManagerAddToAdvancedOptions>> display [[CookieManager]] in [[AdvancedOptions]]
//note: this setting does not take effect until you reload the document//
<<<
!!!!!Revisions
<<<
2008.09.14 [2.3.2] fixed handling for blocked cookies (was still allowing some blocked cookies to be set)
2008.09.12 [2.3.1] added blocked[] array and allowBrowserCookie() test function for selective blocking of changes to browser cookies based on cookie name
2008.09.08 [2.3.0] extensive code cleanup: defined removeCookie(), renamed cookies, added 'button' param for stand-alone "bake cookies" button, improved init of shadow [[CookieManager]] and [[CookieJar]] tiddlers for compatibility with new [[CookieSaverPlugin]]. 
2008.07.11 [2.2.1] fixed recursion error in hijack for saveOptionCookie()
2008.06.26 [2.2.0] added chkCookieManagerNoNewCookies option
2008.06.05 [2.1.3] replaced hard-coded definition for "CookieJar" title with option variable
2008.05.12 [2.1.2] add "cookies" task to backstage (moved from BackstageTasks)
2008.04.09 [2.1.0] added options: chkCookieManagerAddToAdvancedOptions
2008.04.08 [2.0.1] automatically include CookieManager control panel in AdvancedOptions shadow tiddler
2007.08.02 [2.0.0] converted from inline script
2007.04.29 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.CookieManagerPlugin= {major: 2, minor: 3, revision: 1, date: new Date(2008,9,12)};
//}}}
//{{{
config.macros.cookieManager = {
	target:
		config.options.txtCookieJar||"CookieJar",
	blockedCookies:
		[],
	allowBrowserCookie: function(name) {
		return true;
	},
	displayStatus: function(msg) {
		if (config.options.chkMonitorBrowserCookies && !startingUp)
			displayMessage("CookieManager: "+msg);
	},
	init: function() {
		if (config.options.txtCookieJar===undefined)
			config.options.txtCookieJar=this.target;
		if (config.options.chkAllowBrowserCookies===undefined)
			config.options.chkAllowBrowserCookies=true;
		if (config.options.chkMonitorBrowserCookies===undefined)
			config.options.chkMonitorBrowserCookies=false;

		config.shadowTiddlers.CookieManager=
			 "/***\n"
			+"!!![[Browser cookies:|CookieManagerPlugin]] "
			+"{{fine{<<option chkAllowBrowserCookies>>enable <<option chkMonitorBrowserCookies>>monitor}}}\n"
			+"^^Review, modify, or delete browser cookies..."
			+"To block specific cookies, see [[CookieManagerPluginConfig]].^^\n"
			+"@@display:block;width:30em;{{smallform small{\n<<cookieManager>>}}}@@\n"
			+"***/\n";

		// add CookieManager to shadow CookieJar
		var h="/***\n<<tiddler CookieManager>>\n***/\n";
		var t=(config.shadowTiddlers[this.target]||"").replace(new RegExp(h.replace(/\*/g,'\\*'),''),'')
		config.shadowTiddlers[this.target]=h+t;

		if (config.options.chkCookieManagerAddToAdvancedOptions===undefined)
			config.options.chkCookieManagerAddToAdvancedOptions=true;
		if (config.options.chkCookieManagerAddToAdvancedOptions)
			config.shadowTiddlers.AdvancedOptions+="\n!!CookieManager\n><<tiddler CookieManager>>";

		// add "cookies" backstage task
		if (config.tasks && !config.tasks.cookies) { // for TW2.2b3 or above
			config.tasks.cookies = {
				text: "cookies",
				tooltip: "manage cookie-based option settings",
				content: "{{groupbox{<<tiddler CookieManager>><<tiddler [["+this.target+"]]>>}}}"
			}
			config.backstageTasks.push("cookies");
		}
	},
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var span=createTiddlyElement(place,"span");
		span.innerHTML=(params[0]&&params[0].toLowerCase()=="button")?this.button:this.panel;
		this.setList(span.firstChild.list);
	},
	panel: '<form style="display:inline;margin:0;padding:0" onsubmit="return false"><!--\
		--><select style="width:99%" name="list" \
			onchange="this.form.val.value=this.value.length?config.options[this.value]:\'\';"><!--\
		--></select><br>\
		<input type="text" style="width:98%;margin:0;" name="val" title="enter an option value"><br>\
		<input type="button" style="width:33%;margin:0;" value="get" title="refresh list" \
			onclick="config.macros.cookieManager.setList(this.form.list);"><!--\
		--><input type="button" style="width:33%;margin:0;" value="set" title="save cookie value" \
			onclick="var cmc=config.macros.cookieManager;\
				var opt=this.form.list.value; var v=this.form.val.value; \
				var msg=opt+\' is a blocked cookie.  OK to proceed?\';\
				if ((!cmc.blockedCookies.contains(opt) && cmc.allowBrowserCookie(opt))||confirm(msg)) {\
					config.options[opt]=opt.substr(0,3)==\'txt\'?v:(v.toLowerCase()==\'true\'); \
					saveOptionCookie(opt);config.macros.cookieManager.setList(this.form.list);\
				}"><!--\
		--><input type="button" style="width:33%;margin:0;" value="del" title="remove cookie" \
			onclick="var cmc=config.macros.cookieManager; var opt=this.form.list.value; \
				var msg=opt+\' is a blocked cookie.  OK to proceed?\';\
				if ((!cmc.blockedCookies.contains(opt) && cmc.allowBrowserCookie(opt))||confirm(msg)) {\
					removeCookie(this.form.list.value,true); \
					cmc.setList(this.form.list);\
				}"><br>\
		<input type="button" style="width:50%;margin:0;" value="bake cookies" \
			title="save current cookie-based option values into a tiddler" \
			onclick="return config.macros.cookieManager.bake(this,false)"><!--\
		--><input type="button" style="width:50%;margin:0;" value="bake all options" \
			title="save ALL option values (including NON-COOKIE values) into a tiddler" \
			onclick="return config.macros.cookieManager.bake(this,true)"><!--\
		--></form>\
	',
	button: '<form style="display:inline;margin:0;padding:0" onsubmit="return false"><!--\
		--><input type="button" style="margin:0;" value="bake cookies" \
			title="save current browser-based cookie values into a tiddler" \
			onclick="return config.macros.cookieManager.bake(this,false)"><!--\
		--></form>\
	',
	getCookieList: function() {
		var cookies = { };
		if (document.cookie != "") {
			var p = document.cookie.split("; ");
			for (var i=0; i < p.length; i++) {
				var pos=p[i].indexOf("=");
				if (pos==-1) cookies[p[i]]="";
				else cookies[p[i].substr(0,pos)]=unescape(p[i].slice(pos+1));
			}
		}
		var opt=new Array(); for (var i in config.options) if (cookies[i]) opt.push(i); opt.sort();
		return opt;
	},
	setList: function(list) {
		if (!list) return false;
		var opt=this.getCookieList();
		var sel=list.selectedIndex;
		while (list.options.length > 1) { list.options[1]=null; } // clear list (except for header item)
		list.options[0]=new Option("There are "+opt.length+" cookies...","",false,false);
		if (!opt.length) { list.form.val.value=""; return; } // no cookies
		var c=1;
		for(var i=0; i<opt.length; i++) {
			var txt="";
			if  (opt[i].substr(0,3)=="chk")
				txt+="["+(config.options[opt[i]]?"\u221A":"_")+"] ";
			txt+=opt[i];
			list.options[c++]=new Option(txt,opt[i],false,false);
		}
		list.selectedIndex=sel>0?sel:0;
		list.form.val.value=sel>0?config.options[list.options[sel].value]:"";
	},
	header:
		"/***\n"
		+"!!![[Baked cookies:|CookieManagerPlugin]]\n"
		+"^^Press {{smallform{<<cookieManager button>>}}} to save the current browser cookies... "
		+"then hand-edit this section to customize the results.^^\n"
		+"***/\n",
	format: function(name) {
		if (name.substr(0,3)=='chk')
			return '\tconfig.options.'+name+'='+(config.options[name]?'true;':'false;');
		return '\tconfig.options.'+name+'="'+config.options[name]+'";';
	},
	bake: function(here,all) {
		if (story.isDirty(this.target)) return false; // target is being hand-edited... do nothing
		var text=store.getTiddlerText(this.target);
		if (text.indexOf(this.header)==-1) {
			text+=this.header;
			displayMessage("CookieManager: added 'Baked Cookies' section to CookieJar");
		}
		var who=config.options.txtUserName;
		var when=new Date();
		var tags=['systemConfig'];
		var tid=store.getTiddler(this.target)||store.saveTiddler(this.target,this.target,text,who,when,tags,{});
		if (!tid) return false; // if no target... do nothing
		if (all) { 
			var opts=new Array();
			for (var i in config.options) if (i.substr(0,3)=='chk'||i.substr(0,3)=='txt') opts.push(i);
			opts.sort();
		}
		else var opts=this.getCookieList();
		var t=tid.text;
		if (t.indexOf(this.header)==-1) t+=this.header;
		t+='\n// '+opts.length+(all?' options':' cookies')+' saved ';
		t+=when.formatString('on DDD, MMM DDth YYYY at 0hh:0mm:0ss');
		t+=' by '+who+'//\n';
		t+='//^^(edit/remove username check and/or individual option settings as desired)^^//\n';
		t+='//{{{\n';
		t+='if (config.options.txtUserName=="'+who+'") {\n';
		for (i=0; i<opts.length; i++) t+=config.macros.cookieManager.format(opts[i])+"\n";
		t+='}\n//}}}\n';
		store.saveTiddler(this.target,this.target,t,who,when,tags,tid?tid.fields:{});
		story.displayTiddler(story.findContainingTiddler(this),this.target);
		story.refreshTiddler(this.target,null,true);
		var msg=opts.length+(all?' options':' cookies')+' have been saved in '+this.target+'.  ';
		msg+='Please review all stored settings.';
		displayMessage(msg);
		return false;
	}
}
//}}}
//{{{
// Hijack saveOptionCookie() to add cookie blocking and monitoring messages
config.macros.cookieManager.saveOptionCookie=saveOptionCookie;
window.saveOptionCookie=function(name,force)
{
	var cmc=config.macros.cookieManager; // abbrev
	if (force || ((config.options.chkAllowBrowserCookies || name=="chkAllowBrowserCookies")
		&& !cmc.blockedCookies.contains(name) && cmc.allowBrowserCookie(name))) {
		cmc.saveOptionCookie.apply(this,arguments);
		cmc.displayStatus(name+"="+config.options[name]);
	} else cmc.displayStatus("setting of '"+name+"' is blocked");
}

// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
	window.removeCookie=function(name) {
		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;'; 
	}
}

// ... and then hijack it to add cookie blocking and monitoring messages
config.macros.cookieManager.removeCookie=removeCookie;
window.removeCookie=function(name,force)
{
	var cmc=config.macros.cookieManager; // abbrev
	if (!cmc.getCookieList().contains(name))
		return; // not a current cookie!
	if (force || ((config.options.chkAllowBrowserCookies || name=="chkAllowBrowserCookies")
		&& !cmc.blockedCookies.contains(name) && cmc.allowBrowserCookie(name))) {
		cmc.removeCookie.apply(this,arguments);
		cmc.displayStatus("deleted "+name);
	} else cmc.displayStatus("deletion of '"+name+"' is blocked");
}
//}}}
/***
|Name|CookieManagerPluginConfig|
|Source|http://www.TiddlyTools.com/#CookieManagerPluginConfig|
|Requires|CookieManagerPlugin|
|Description|custom settings for [[CookieManagerPlugin]]|
!!!!!Browser Cookie Configuration:
***/
// // <<option chkAllowBrowserCookies>> store ~TiddlyWiki option settings using private browser cookies
// // <<option chkMonitorBrowserCookies>> monitor browser cookie activity (shows a message whenever a cookie is updated)
//{{{
// default settings:
config.options.chkAllowBrowserCookies=true;	// if FALSE, this blocks *all* cookies
config.options.chkMonitorBrowserCookies=false;
//}}}

// // Individual cookie names can be prevented from being created, modified, or deleted in your browser's stored cookies by adding them to the {{{config.macros.cookieManager.blockedCookies}}} array: 
//{{{
var bc=config.macros.cookieManager.blockedCookies; // abbreviation
bc.push("chkBackstage");		// TiddlyWiki:  core
bc.push("txtMainTab");			// TiddlyWiki:  SideBarTabs
bc.push("txtTOCSortBy");		// TiddlyTools: TableOfContentsPlugin
bc.push("txtCatalogTab");		// TiddlyTools: ShowCatalog
bc.push("txtUploadFilename");		// BidiX: UploadPlugin
bc.push("txtUploadDir");		// BidiX: UploadPlugin
bc.push("txtUploadUserName");		// BidiX: UploadPlugin
bc.push("pasPassword");			// BidiX: UploadPlugin
bc.push("pasUploadPassword");		// BidiX: UploadPlugin
//}}}
// // You can also define a javascript test function that determines whether or not any particular cookie name should be blocked or allowed.  The following function should return FALSE if the browser cookie should be blocked, or TRUE if changes to the cookie should be allowed:
//{{{
config.macros.cookieManager.allowBrowserCookie=function(name) {
	// add tests based on specific cookie names and runtime conditions
	return true;
}
//}}}
/***
|Name|CookieSaverPlugin|
|Source|http://www.TiddlyTools.com/#CookieSaverPlugin|
|Version|1.0.2|
|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||
|Options|##Configuration|
|Description|automatically save TiddlyWiki cookie options to [[CookieJar]] tiddler for portable settings|
|Status|BETA EXPERIMENTAL - USE WITH CAUTION - SUBJECT TO CHANGE|
!!!!!Usage
<<<
Whenever TiddlyWiki option settings or other 'stateful' program values are changed, a browser-based cookie value is typically added, removed, or changed.  Each time this occurs, the CookieSaverPlugin generates an equivalent ''portable cookie'', which is a single line of javascript code that simply assigns a fixed value directly to the specific TiddlyWiki internal config.options.* variable corresponding to the browser cookie with the same name.

The portable cookies are automatically written into a tiddler named [[CookieJar]] that is tagged with<<tag systemConfig>>so that their values will be applied as soon as the document is saved and reloaded.  You can change or delete an individual portable cookie by editing the contents of the [[CookieJar]] and removing the appropriate line of javascript from the tiddler source code.  Note: editing the portable cookie definitions does not alter the values of any corresponding browser cookies, nor does it update the internal value that is in use within the current TiddlyWiki document session.  Changes made directly to the [[CookieJar]] are only applied after saving and reloading the document.  In any case, whenever a browser cookie value is updated, any modifications you made to the equivalent portable cookie are immediately rewritten to reflect the current browser cookie value.

Browser cookies are, obviously, stored with your browser... and are kept separate from the document itself.  In contrast, because your portable cookies are stored in a [[CookieJar]] within the document, they remain part of that document.

When the document is copied and shared with others, each copy includes the [[CookieJar]] containing //your// stored portable cookies.  Fortunately, CookieSaverPlugin can generate and maintain several separate sets of portable cookies in the same [[CookieJar]] tiddler, where each set is associated with a different TiddlyWiki username.  As long as other readers have not chosen the same username, your portable cookie values will not be automatically applied when they are reading the document.  Rather, as they interact with the document, a new set of portable cookies, associated with //their// username, will be automatically added to the [[CookieJar]].

In addition to tracking and applying separate portable cookies for each user, CookieSaverPlugin can also be configured so that sensitive data (such as internal URLs, email addresses, login IDs and passwords, etc.) will never be inadvertently stored in the [[CookieJar]].  To achieve this, you can selectively prevent specific cookienames from being used as portable cookies by placing a special javascript function definition in a tiddler named [[CookieSaverPluginConfig]], tagged with 'systemConfig':
{{{
config.macros.cookieSaver.allowPortableCookie=function(name){
	if ( ... some test using 'name' ...) return false;
	if ( ... another test with 'name' ...) return true;
	etc.
	return true;  // default=allow
}
}}}
The allowPortableCookie() function offers a flexible method for plugin developers and other technically skilled document authors to implement their own custom-defined, application-specific cookie data protection by applying sophisticated logic for deciding which cookies should be allowed or blocked based on variety of different conditions.  The basic operation of this function is to accept a cookie name as text input, apply some tests based on that cookie name (combined with any other useful criteria), and then return //true// if saving the portable cookie should be permitted, or //false// if the cookie should be excluded from the [[CookieJar]].

Unfortunately, although the technical expertise needed to write this test function is relatively minor, the level of programming ability that is needed can nonetheless be beyond the skills that many people possess.  To help address this, CookieSaverPlugin also supports an alternative syntax that allows you to define a simple array of cookie names that is used by the plugin to automatically block the indicated names from being included as portable cookies in the [[CookieJar]].  The array definition syntax looks like this:
{{{
// define a complete set of blocked cookie names
config.macros.cookieSaver.blockedCookies=['cookie','cookie','cookie',etc...];
}}}
or
{{{
// add individual cookies names to the current set of blocked cookies
config.macros.cookieSaver.blockedCookies.push('cookie');
config.macros.cookieSaver.blockedCookies.push('cookie');
etc...
}}}
Note: the allowPortableCookie() function and the blockedCookies[] array are only used to limit the creation of portable cookies within the [[CookieJar]], and are //not// applied when creating normal browser cookies.  Thus, regardless of whether or not a given portable cookie has been excluded or permitted, all the usual TiddlyWiki settings and internal state data can still be saved as secure, private, local browser cookies that are never made visible to others, even when the document is shared.
<<<
!!!!!Configuration
<<<
<<option chkPortableCookies>> allow ~CookieSaver to store //''portable cookies''// in [[CookieJar]] tiddler
<<option chkMonitorCookieJar>> monitor ~CookieSaver activity (show messages whenever [[CookieJar]] is updated)
<<option chkCookieJarAddToAdvancedOptions>> display [[CookieJar]] in [[AdvancedOptions]]
^^//note: changing this setting does not take effect until you reload the document//^^
<<<
!!!!!Revisions
<<<
2008.09.11 [1.0.2] automatically add portable cookies header to existing CookieJar (if any).  Also, added chkMonitorCookieJar option to display CookieJar activity messages
2008.09.10 [1.0.1] documentation, code cleanup, improvements in 'allowPortableCookie()' function handling
2008.09.09 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.CookieSaverPlugin= {major: 1, minor: 0, revision: 2, date: new Date(2008,9,11)};

config.macros.cookieSaver = {
	target:
		config.options.txtCookieJar||"CookieJar",
	init: function() {
		if (config.options.chkPortableCookies===undefined)
			config.options.chkPortableCookies=false;
		if (config.options.txtCookieJar===undefined)
			config.options.txtCookieJar=this.target;
		if (config.options.chkCookieJarAddToAdvancedOptions===undefined)
			config.options.chkCookieJarAddToAdvancedOptions=true;
		if (config.options.chkCookieJarAddToAdvancedOptions)
			config.shadowTiddlers.AdvancedOptions+="\n!!%0\n><<tiddler [[%0]]>>".format([this.target]);
		if (config.options.chkMonitorCookieJar===undefined)
			config.options.chkMonitorCookieJar=false;

		// add empty Portable Cookies section to shadow CookieJar
		var h="/***\n<<tiddler CookieManager>>\n***/\n";
		var t=(config.shadowTiddlers[this.target]||"").replace(new RegExp(h.replace(/\*/g,'\\*'),''),'')
		config.shadowTiddlers[this.target]=this.header+this.footer+t;

		// add empty Portable Cookies section to real CookieJar (if one exists)
		if (store.tiddlerExists(this.target) && !readOnly) {
			var tid=this.get(this.target);
			var t=tid.text;
			if (t.indexOf(this.header)==-1){
				t=this.header+this.footer+t.replace(new RegExp(h.replace(/\*/g,'\\*'),''),'');
				var who=config.options.chkForceMinorUpdate?tid.modifier:config.options.txtUserName;
				var when=config.options.chkForceMinorUpdate?tid.modified:new Date();
				store.saveTiddler(tid.title,tid.title,t,who,when,tid.tags,tid.fields);
				displayMessage("CookieSaver: added 'Portable Cookies' section to CookieJar");
			}
		}

		// add "cookies" backstage task
		if (config.tasks && !config.tasks.cookies) { // for TW2.2b3 or above
			config.tasks.cookies = {
				text: "cookies",
				tooltip: "manage cookie-based option settings",
				content: "{{groupbox{<<tiddler CookieManager>><<tiddler [[%0]]>>}}}".format([this.target])
			}
			config.backstageTasks.push("cookies");
		}
	},
	header:
		 "/***\n<<tiddler CookieManager>>\n***/\n"
		+"/***\n"
		+"!!![[Portable cookies:|CookieSaverPlugin]] "
		+"{{fine{<<option chkPortableCookies>>enable <<option chkMonitorCookieJar>>monitor}}}\n"
		+"^^This section is ''//__automatically maintained__//'' by [[CookieSaverPlugin]].  "
		+"To block specific cookies, see [[CookieSaverPluginConfig]].^^\n"
		+"***/\n",
	startUser:
		 "//{{{\n"
		+"if (config.options.txtUserName==\"%0\" && config.options.chkPortableCookies) {",
	endUser:
		"\n}\n//}}}\n",
	footer:
		"// // /% end portable cookies %/\n",
	get: function(tid) { // create or retrieve tiddler
		if (story.isDirty(tid)) return null; // tiddler is being hand-edited... leave it alone.
		var text=config.shadowTiddlers[this.target];
		var who=config.options.txtUserName;
		var when=new Date();
		var tags=['systemConfig'];
		return store.getTiddler(tid)||store.saveTiddler(tid,tid,text,who,when,tags,{});
	},
	format: function(name) {
		if (name.substr(0,3)=='chk')
			return '\tconfig.options.'+name+'='+(config.options[name]?'true;':'false;');
		return '\tconfig.options.'+name+'="'+config.options[name]+'";';
	},
	blockedCookies: [],
	allowPortableCookie: function(name) {
		return true;
	},
	set: function(name) {
		if (!name||!name.trim().length) return;
		if (name=='txtUserName' || this.blockedCookies.contains(name) || !this.allowPortableCookie(name)) {
			if (config.options.chkMonitorCookieJar && !startingUp)
				displayMessage("CookieJar: blocked '"+name+"'");
			return false; // don't save excluded cookies
		}
		var tid=this.get(this.target);
		if (!tid) return false; // if no tiddler... do nothing
		var t=tid.text;
		if (t.indexOf(this.header)==-1) {  // re-add Portable Cookies section if it was deleted by hand edit
			var h="/***\n<<tiddler CookieManager>>\n***/\n";
			t=this.header+this.footer+t.replace(new RegExp(h.replace(/\*/g,'\\*'),''),'');
		}
		var who=config.options.txtUserName;
		var when=new Date();
		var startmark=this.startUser.format([who]);
		var endmark=this.endUser;
		var startpos=t.indexOf(startmark);
		if (startpos==-1) { // insert new user (just before footer)
			if (config.options.chkMonitorCookieJar && !startingUp)
				displayMessage("CookieJar: added new user '"+who+"'");
			var addpos=t.indexOf(this.footer); if (addpos==-1) addpos=t.length;
			t=t.substr(0,addpos)+startmark+endmark+t.substr(addpos);
			startpos=addpos;
		}
		startpos+=startmark.length;
		var endpos=t.indexOf(endmark,startpos);
		var pre=t.substr(0,startpos);
		var lines=t.substring(startpos,endpos).split('\n');
		var post=t.substr(endpos);
		var code=this.format(name);
		var match='\tconfig.options.'+name+'=';
		var found=false; var changed=false;
		for (var i=0; i<lines.length; i++) { // find and replace existing setting
			if (lines[i].substr(0,match.length)==match) {
				found=true;
				if (changed=lines[i]!=code) lines[i]=code; // replace value
				if (config.options.chkMonitorCookieJar && !startingUp && changed)
					displayMessage("CookieJar: "+code);
			}
		}
		if (!found && code.length) { // OR, add new setting
			lines[lines.length]=code;
			if (config.options.chkMonitorCookieJar && !startingUp)
				displayMessage("CookieJar: "+code);
		}
		if (found && !changed) return; // don't alter tiddler unless necessary
		t=pre+lines.join('\n')+post;
		var who=config.options.chkForceMinorUpdate?tid.modifier:config.options.txtUserName;
		var when=config.options.chkForceMinorUpdate?tid.modified:new Date();
		store.saveTiddler(this.target,this.target,t,who,when,tid.tags,tid.fields);
		story.refreshTiddler(this.target,null,true);
	},
	remove: function(name) {
		if (!name||!name.trim().length) return;
		var who=config.options.txtUserName;
		var when=new Date();
		var tid=store.getTiddler(this.target);
		if (!tid) return false; // if no tiddler... do nothing
		var t=tid.text;
		var who=config.options.txtUserName
		var startmark=this.startUser.format([who]);
		var endmark=this.endUser;
		var startpos=t.indexOf(startmark);
		if (startpos==-1) return false; // no such user... do nothing
		startpos+=startmark.length;
		var endpos=t.indexOf(endmark,startpos);
		var pre=t.substr(0,startpos);
		var lines=t.substring(startpos,endpos).split('\n');
		var post=t.substr(endpos);
		var match='\tconfig.options.'+name;
		var found=false; var changed=false;
		for (var i=0; i<lines.length; i++) { // find and remove setting
			if (lines[i].substr(0,match.length)==match) {
				lines.splice(i,1);
				changed=true;
				if (config.options.chkMonitorCookieJar && !startingUp)
					displayMessage("CookieJar: deleted '"+name+"'");
				break;
			}
		}
		if (!changed) return; // not found... do nothing
		t=pre+lines.join('\n')+post;
		if (lines.length==1) { // no cookies left, remove user
			t=pre.substr(0,pre.length-startmark.length)+post.substr(endmark.length);
			if (config.options.chkMonitorCookieJar && !startingUp)
				displayMessage("CookieJar: removed user '"+who+"'");
		}
		var who=config.options.chkForceMinorUpdate?tid.modifier:config.options.txtUserName;
		var when=config.options.chkForceMinorUpdate?tid.modified:new Date();
		store.saveTiddler(this.target,this.target,t,who,when,tid.tags,tid.fields);
		story.refreshTiddler(this.target,null,true);
	}
}
//}}}
//{{{
// Hijack saveOptionCookie() to add CookieSaver processing
config.macros.cookieSaver.saveOptionCookie=saveOptionCookie;
window.saveOptionCookie=function(name)
{
	config.macros.cookieSaver.saveOptionCookie.apply(this,arguments);
	if (!readOnly && (config.options.chkPortableCookies || name=="chkPortableCookies"))
		config.macros.cookieSaver.set(name);
}
// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
	window.removeCookie=function(name) {
		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;'; 
	}
}
// ... and then hijack it to also remove any corresponding PortableCookie
config.macros.cookieSaver.removeCookie=removeCookie;
window.removeCookie=function(name)
{
	if (config.options.chkPortableCookies && !readOnly)
		config.macros.cookieSaver.remove(name);
	config.macros.cookieSaver.removeCookie.apply(this,arguments);
}
//}}}
/***
|Name|CookieSaverPluginConfig|
|Source|http://www.TiddlyTools.com/#CookieSaverPluginConfig|
|Requires|CookieSaverPlugin|
|Description|custom settings for [[CookieSaverPlugin]]|
!!!!!Portable Cookie Configuration:
***/
// // <<option chkPortableCookies>> allow ~CookieSaver to store //''portable cookies''// in [[CookieJar]] tiddler
// // <<option chkMonitorCookieJar>> monitor ~CookieSaver activity (show messages whenever [[CookieJar]] is updated)
//{{{
// default to these settings:
// config.options.chkPortableCookies=false;	// when FALSE this blocks ALL portable cookies
// config.options.chkMonitorCookieJar=false;
//}}}

// // Individual cookie names can be added to the {{{config.macros.cookieSaver.blockedCookies}}} array to prevent them from being stored in the [[CookieJar]].
//{{{
var bc=config.macros.cookieSaver.blockedCookies;
bc.push("chkBackstage");		// core
bc.push("txtMainTab");			// TiddlyWiki: SideBarTabs
bc.push("txtTOCSortBy");		// TiddlyTools: TableOfContentsPlugin
bc.push("txtCatalogTab");		// TiddlyTools: ShowCatalog
bc.push("txtUploadFilename");		// BidiX: UploadPlugin
bc.push("txtUploadDir");		// BidiX: UploadPlugin
bc.push("pasPassword");			// BidiX: UploadPlugin
bc.push("pasUploadPassword");		// BidiX: UploadPlugin
//}}}
// // You can also define a javascript test function that determines whether or not any particular cookie name should be stored in the [[CookieJar]].  The following function should return FALSE if the portable cookie should be blocked, or TRUE if the cookie should be allowed:
//{{{
config.macros.cookieSaver.allowPortableCookie=function(name) {
	// add tests based on specific cookie names and runtime conditions
	if (name.substr(0,9)=="chkSlider") 	return false;	// NestedSlidersPlugin
	if (name.substr(0,13)=="txtFirstVisit")	return false;	// VisitCounter
	if (name.substr(0,12)=="txtLastVisit")	return false;	// VisitCounter
	if (name.substr(0,13)=="txtVisitCount")	return false;	// VisitCounter
	return true;
}
//}}}
/***
|Name|CoreTweaks|
|Source|http://www.TiddlyTools.com/#CoreTweaks|
|Version|n/a|
|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.2.4|
|Type|plugin|
|Requires||
|Overrides|various|
|Description|a small collection of overrides to TW core functions|
This tiddler contains some quick tweaks and modifications to TW core functions to provide minor changes in standard features or behavior.  It is hoped that some of these tweaks may be incorporated into later versions of the TW core, so that these adjustments will be available without needing these add-on definitions. ''Note: the changes contained in this tiddler are generally applicable for the current version of TiddlyWiki (<<version>>)./% Please view [[CoreTweaksArchive]] for tweaks and modifications that may be used with earlier versions of TiddlyWiki.%/''

To install //all// of these tweaks, import (or copy/paste) this tiddler into your document.  To include only //some// of the tweaks, you can edit the imported tiddler to remove the tweaks that you don't want.  Alternatively, you could copy/paste a few selected tweaks from this tiddler into a tiddler that you create in your own document.  Be certain to tag that tiddler with<<tag systemConfig>> (i.e., a plugin tiddler) and then save-and-reload for the tweaks to take effect.
***/
/***
!!! Ticketed Tweaks
***/
// // {{groupbox small{
/***
!!FireFox3 Import bug: "browse" button replacement
http://trac.tiddlywiki.org/ticket/683 - OPEN
see also http://trac.tiddlywiki.org/ticket/604 - cross-platform askForFilename()
The web standard "type=file" input control that has been used as a local path/file picker for TiddlyWiki no longer works as expected in FireFox3, which has, for "security" reasons, limited javascript access to this control so that *no* local filesystem path information can be revealed, even when it is intentional and necessary, as it is with TiddlyWiki.  This tweak provides alternative HTML source that patches the backstage import panel.  It replaces the "type=file" input control with a text+button combination of controls that invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.
***/
//{{{
if (window.Components) {
	var fixhtml='<input name="txtBrowse" style="width:30em"><input type="button" value="..."'
		+' onClick="window.browseForFilename(this.previousSibling,true)">';
	var cmi=config.macros.importTiddlers;
	cmi.step1Html=cmi.step1Html.replace(/<input type='file' size=50 name='txtBrowse'>/,fixhtml);
}

merge(config.messages,{selectFile:"Please enter or select a file"}); // ready for I18N translation

window.browseForFilename=function(target,mustExist) { // note: both params are optional
	var msg=config.messages.selectFile;
	if (target && target.title) msg=target.title; // use target field tooltip (if any) as dialog prompt text
	// get local path for current document
	var path=getLocalPath(document.location.href);
	var p=path.lastIndexOf("/"); if (p==-1) p=path.lastIndexOf("\\"); // Unix or Windows
	if (p!=-1) path=path.substr(0,p+1); // remove filename, leave trailing slash
	var file=""
	var result=window.askForFilename(msg,path,file,mustExist); // requires #604
	if (target && result.length) // set target field and trigger handling
		{ target.value=result; target.onchange(); }
	return result; 
}
//}}}
// // }}}
// // {{groupbox small{
/***
!!cross-platform askForFilename()
http://trac.tiddlywiki.org/ticket/604 - OPEN
invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.
***/
//{{{
window.askForFilename=function(msg,path,file,mustExist) {
	var r = window.mozAskForFilename(msg,path,file,mustExist);
	if(r===null || r===false)
		r = window.ieAskForFilename(msg,path,file,mustExist);
	if(r===null || r===false)
		r = window.javaAskForFilename(msg,path,file,mustExist);
	if(r===null || r===false)
		r = prompt(msg,path+file);
	return r||"";
}

window.mozAskForFilename=function(msg,path,file,mustExist) {
	if(!window.Components) return false;
	try {
		netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
		var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
		picker.init(window, msg, mustExist?nsIFilePicker.modeOpen:nsIFilePicker.modeSave);
		var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
		thispath.initWithPath(path);
		picker.displayDirectory=thispath;
		picker.defaultExtension='html';
		picker.defaultString=file;
		picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
		if (picker.show()!=nsIFilePicker.returnCancel)
			var result=picker.file.persistentDescriptor;
	}
	catch(ex) { displayMessage(ex.toString()); }
	return result;
}

window.ieAskForFilename=function(msg,path,file,mustExist) {
	if(!config.browser.isIE) return false;
	try {
		var s = new ActiveXObject('UserAccounts.CommonDialog');
		s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
		s.FilterIndex=3; // default to HTML files;
		s.InitialDir=path;
		s.FileName=file;
		return s.showOpen()?s.FileName:"";
	}
	catch(ex) { displayMessage(ex.toString()); }
	return result;
}

window.javaAskForFilename=function(msg,path,file,mustExist) {
	if(!document.applets["TiddlySaver"]) return false;
	// TBD: implement java-based askFile(...) function
	try { return document.applets["TiddlySaver"].askFile(msg,path,file,mustExist); } 
	catch(ex) { displayMessage(ex.toString()); }
}
//}}}
// // }}}
// // {{groupbox small{
/***
!!#story:... paramifier
http://trac.tiddlywiki.org/ticket/676 - OPEN
scan the specified 'story' tiddler content for embedded links, rather than simply parsing the content as a space-separated bracketed list.  This allows links from ''any'' tiddler to be used as a story, regardless of other wiki-syntax contained in that tiddler.  If specified tiddler is a shadow, fallback to using parseParams() to extract the list of links.
***/
//{{{
config.paramifiers.story = {
	onstart: function(v) {
		var t=store.getTiddler(v); if (t) t.changed();
		var list=t?t.links:store.getTiddlerText(v,"").parseParams("open",null,false);
		story.displayTiddlers(null,list);
	}
};
//}}}
// // }}}
// // {{groupbox small{
/***
!!Loose links (case-folded/space-folded wiki words)
http://trac.tiddlywiki.org/ticket/664 - OPEN
This tweak matches non-WikiWord variations of mixed-case and/or added/omitted spaces within double-bracketed text with titles of //existing// tiddlers, using a "loose" (case-folded/space-folded) comparison.  This allows text that occurs in normal prose to be more easily linked to tiddler titles by using double-brackets without the full "pretty link" syntax.  For example:
{{{
[[CoreTweaks]], [[coreTweaks]], [[core tweaks]],
[[CORE TWEAKS]], [[CoRe TwEaKs]], [[coreTWEAKS]]
}}}
>[[CoreTweaks]], [[coreTweaks]], [[core tweaks]],
>[[CORE TWEAKS]], [[CoRe TwEaKs]], [[coreTWEAKS]]
Configuration:
><<option chkLooseLinks>> Allow case-folded and/or space-folded text to link to existing tiddler titles
>{{{usage: <<option chkLooseLinks>>}}}
***/
//{{{
if (!config.options.chkLooseLinks)
	config.options.chkLooseLinks=false; // default to standard behavior
window.caseFold_createTiddlyLink = window.createTiddlyLink;
window.createTiddlyLink = function(place,title,includeText,className) {
	var btn=window.caseFold_createTiddlyLink.apply(this,arguments); // create core link
	if (!config.options.chkLooseLinks) return btn;
	if (store.getTiddlerText(title)) return btn; // matching tiddler (or shadow) exists
	var target=title.toLowerCase().replace(/\s/g,"");
	var tids=store.getTiddlers("title");
	for (var t=0; t<tids.length; t++) {
		if (tids[t].title.toLowerCase().replace(/\s/g,"")==target) {
			var i=getTiddlyLinkInfo(tids[t].title,className);
			btn.setAttribute("tiddlyLink",tids[t].title);
			btn.title=i.subTitle;
			btn.className=i.classes;
			break;
		}
	}
	return btn;
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/657 - OPEN
// // This tweak inserts an extra space element following each tab, allowing them to wrap onto multiple lines if needed.
//{{{
config.macros.tabs.handler = function(place,macroName,params)
{
	var cookie = params[0];
	var numTabs = (params.length-1)/3;
	var wrapper = createTiddlyElement(null,"div",null,"tabsetWrapper " + cookie);
	var tabset = createTiddlyElement(wrapper,"div",null,"tabset");
	tabset.setAttribute("cookie",cookie);
	var validTab = false;
	for(var t=0; t<numTabs; t++) {
		var label = params[t*3+1];
		var prompt = params[t*3+2];
		var content = params[t*3+3];
		var tab = createTiddlyButton(tabset,label,prompt,this.onClickTab,"tab tabUnselected");
		createTiddlyElement(tab,"span",null,null," ",{style:"font-size:0pt;line-height:0px"}); // ELS
		tab.setAttribute("tab",label);
		tab.setAttribute("content",content);
		tab.title = prompt;
		if(config.options[cookie] == label)
			validTab = true;
	}
	if(!validTab)
		config.options[cookie] = params[1];
	place.appendChild(wrapper);
	this.switchTab(tabset,config.options[cookie]);
};
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/637 - OPEN
// // This tweak modifies the tooltip format that appears when you mouseover a link to a tiddler.  It adds an option to control the date format, as well as displaying the size of the tiddler (in bytes)
// //
// // Tiddler link tooltip format:
// // {{stretch{<<option txtTiddlerLinkTootip>>}}}
// // ^^where: %0=title, %1=username, %2=modification date, %3=size in bytes^^
// // Tiddler link tooltip date format:
// // {{stretch{<<option txtTiddlerLinkTooltipDate>>}}}
//{{{
config.messages.tiddlerLinkTooltip="%0 - %1, %2 (%3 bytes)";
config.messages.tiddlerLinkTooltipDate="DDD, MMM DDth YYYY 0hh12:0mm AM";

config.options.txtTiddlerLinkTootip=
	config.options.txtTiddlerLinkTootip||config.messages.tiddlerLinkTooltip;
config.options.txtTiddlerLinkTooltipDate=
	config.options.txtTiddlerLinkTooltipDate||config.messages.tiddlerLinkTooltipDate;

Tiddler.prototype.getSubtitle = function() {
	var modifier = this.modifier;
	if(!modifier) modifier = config.messages.subtitleUnknown;
	var modified = this.modified;
	if(modified) modified = modified.formatString(config.options.txtTiddlerLinkTooltipDate);
	else modified = config.messages.subtitleUnknown;
	return config.options.txtTiddlerLinkTootip.format([this.title,modifier,modified,this.text.length]);
};
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/628 - OPEN
// // When invoking a macro that is not defined, this tweak prevents the display of the "error in macro... no such macro" message.  This is useful when rendering tiddler content or templates that reference macros that are defined by //optional// plugins that have not been installed in the current document.
// //
// // <<option chkHideMissingMacros>> hide "no such macro" error messages
//{{{
if (config.options.chkHideMissingMacros===undefined)
	config.options.chkHideMissingMacros=false;

window.coreTweaks_missingMacro_invokeMacro = window.invokeMacro;
window.invokeMacro = function(place,macro,params,wikifier,tiddler) {
	if (!config.macros[macro] || !config.macros[macro].handler)
		if (config.options.chkHideMissingMacros) return;
	window.coreTweaks_missingMacro_invokeMacro.apply(this,arguments);
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/609 - OPEN (separators)
// // http://trac.tiddlywiki.org/ticket/610 - OPEN (wikify tiddler/slice/section content)
// // These tweaks extend the {{{<<toolbar>>}}} macro to permit use of "|" as separators, as well as recognizing references to tiddlernames, slices, or sections and rendering their content inline within the toolbar
// // ''see [[ToolbarCommands]] for examples of how these features can be used''
//{{{
merge(config.macros.toolbar,{
	separator: "|"
	});
config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	for(var t=0; t<params.length; t++) {
		var c = params[t];
		switch(c) {
			case '|':  // ELS - SEPARATOR
			case '!':  // ELS - SEPARATOR (alternative for use in tiddler slices)
				createTiddlyText(place,this.separator); // ELS
				break; // ELS
			case '>':
				var btn = createTiddlyButton(place,this.moreLabel,this.morePrompt,config.macros.toolbar.onClickMore);
				addClass(btn,"moreCommand");
				var e = createTiddlyElement(place,"span",null,"moreCommand");
				e.style.display = "none";
				place = e;
				break;
			default:
				var theClass = "";
				switch(c.substr(0,1)) {
					case "+":
						theClass = "defaultCommand";
						c = c.substr(1);
						break;
					case "-":
						theClass = "cancelCommand";
						c = c.substr(1);
						break;
				}
				if(c in config.commands)
					this.createCommand(place,c,tiddler,theClass);
				else { // ELS - WIKIFY TIDDLER/SLICE/SECTION
					if (c.substr(0,1)=="~") c=c.substr(1); // ignore leading ~
					var txt=store.getTiddlerText(c);
					if (txt) {
						txt=txt.replace(/^\n*/,"").replace(/\n*$/,""); // trim any leading/trailing newlines
						txt=txt.replace(/^\{\{\{\n/,"").replace(/\n\}\}\}$/,""); // trim PRE format wrapper if any
						wikify(txt,createTiddlyElement(place,"span"),null,tiddler);
					}
				} // ELS - end WIKIFY CONTENT
				break;
		}
	}
};
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/608 - OPEN
// // This tweak extends the {{{<<toolbar>>}}} macro to make the ">" (more) a //toggle// between more/less with the additional toolbar commands displayed on a separate line.
//{{{
merge(config.macros.toolbar,{
	moreLabel: 'more',
	morePrompt: "Show additional commands",
	lessLabel: 'less',
	lessPrompt: "Hide additional commands"
});
config.macros.toolbar.onClickMore = function(ev)
{
	var e = this.nextSibling;
	var showing=e.style.display=="block";
	e.style.display = showing?"none":"block";
	this.innerHTML=showing?config.macros.toolbar.moreLabel:config.macros.toolbar.lessLabel;
	this.title=showing?config.macros.toolbar.morePrompt:config.macros.toolbar.lessPrompt;
	return false;
};
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/607 - OPEN
// // This tweak automatically sets the HREF for the 'permaview' sidebar command link so you can use the 'right click' context menu for faster, easier bookmarking.  Note that this does ''not'' automatically set the permaview in the browser's current location URL... it just sets the HREF on the command link.  You still have to click the link to apply the permaview.
//{{{
config.macros.permaview.handler = function(place)
{
	var btn=createTiddlyButton(place,this.label,this.prompt,this.onClick);
	addEvent(btn,"mouseover",this.setHREF);
	addEvent(btn,"focus",this.setHREF);
};
config.macros.permaview.setHREF = function(event){
	var links = [];
	story.forEachTiddler(function(title,element) {
		links.push(String.encodeTiddlyLink(title));
	});
	var newURL=document.location.href;
	var hashPos=newURL.indexOf("#");
	if (hashPos!=-1) newURL=newURL.substr(0,hashPos);
	this.href=newURL+"#"+encodeURIComponent(links.join(" "));
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/529 - OPEN
// // This tweak hijacks the standard browser function, document.getElementById(), to work-around the case-INsensitivity error in Internet Explorer (all versions up to and including IE7) //''Note: This tweak is only applied when using IE, and only for lookups of rendered tiddler elements within the containing "tiddlerDisplay" element.''//
//{{{
if (config.browser.isIE) {
document.coreTweaks_coreGetElementById=document.getElementById;
document.getElementById=function(id) {
	var e=document.coreTweaks_coreGetElementById(id);
	if (!e || !e.parentNode || e.parentNode.id!="tiddlerDisplay") return e;
	for (var i=0; i<e.parentNode.childNodes.length; i++)
		if (id==e.parentNode.childNodes[i].id) return e.parentNode.childNodes[i];
	return null;
};
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/471 - OPEN
// // This tweak HIJACKS the core's saveTiddler() function to automatically add a "creator" field to a tiddler when it is FIRST created. You can use {{{<<view creator>>}}} (or {{{<<view creator wikified>>}}} if you prefer) to show this value embedded directly within the tiddler content, or {{{<span macro="view creator"></span>}}} in the ViewTemplate and/or EditTemplate to display the creator value in each tiddler.  
//{{{
// hijack saveTiddler()
TiddlyWiki.prototype.CoreTweaks_creatorSaveTiddler=TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler=function(title,newTitle,newBody,modifier,modified,tags,fields)
{
	var existing=store.tiddlerExists(title);
	var tiddler=this.CoreTweaks_creatorSaveTiddler.apply(this,arguments);
	if (!existing) store.setValue(title,"creator",config.options.txtUserName);
	return tiddler;
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/458 - CLOSED: WON'T FIX
// // This tweak assigns a "permalink"-like HREF to internal Tiddler links (which normally do not have any HREF defined).  This permits the link's context menu (right-click) to include 'open link in another window/tab' command.  Based on a request from Dustin Spicuzza.
//{{{
window.coreTweaks_createTiddlyLink=window.createTiddlyLink;
window.createTiddlyLink=function(place,title,includeText,theClass,isStatic,linkedFromTiddler,noToggle)
{
	// create the core button, then add the HREF (to internal links only)
	var link=window.coreTweaks_createTiddlyLink.apply(this,arguments);
	if (!isStatic)
		link.href=document.location.href.split("#")[0]+"#"+encodeURIComponent(String.encodeTiddlyLink(title));
	return link;
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/444 - OPEN
// // When invoking a macro, this tweak makes the current containing tiddler object and DOM rendering location available as global variables (window.tiddler and window.place, respectively).  These globals can then be used within "computed macro parameters" to retrieve tiddler-relative and/or DOM-relative values or perform tiddler-specific side-effect functionality.
//{{{
window.coreTweaks_invokeMacro = window.invokeMacro;
window.invokeMacro = function(place,macro,params,wikifier,tiddler) {
	var here=story.findContainingTiddler(place);
	window.tiddler=here?store.getTiddler(here.getAttribute("tiddler")):null;
	window.place=place;
	window.coreTweaks_invokeMacro.apply(this,arguments);
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/401 - CLOSED: WON'T FIX
// // This tweak allows definition of an optional [[PageTitle]] tiddler that, when present, provides alternative text for display in the browser window's titlebar, instead of using the combined text content from [[SiteTitle]] and [[SiteSubtitle]] (which will still be displayed as usual in the TiddlyWiki document header area)
//{{{
window.coreTweaks_getPageTitle=window.getPageTitle;
window.getPageTitle=function() { 
	var txt=wikifyPlain("PageTitle"); if (txt.length) return txt;
	return window.coreTweaks_getPageTitle.apply(this,arguments);
}
store.addNotification("PageTitle",refreshPageTitle); // so title stays in sync with tiddler changes
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/67 - OPEN
// // The "missing links" list includes items contained within "quoted" text (i.e., content that will not render as wiki-syntax, and so CANNOT create any tiddler links, even if the quoted text matches valid link syntax).  This tweak removes content contained between certain delimiters before scanning tiddler source for possible links.
/***
Delimiters include:
{{{
/%...%/
{{{...}}}
"""..."""
<nowiki>...</nowiki>
<html>...</html>
<script>...</script>
}}}
***/
//{{{
Tiddler.prototype.coreTweaks_changed = Tiddler.prototype.changed;
Tiddler.prototype.changed = function()
{
	var savedtext=this.text;
	// remove 'quoted' text before scanning tiddler source
	this.text=this.text.replace(/\/%((?:.|\n)*?)%\//g,""); // /%...%/
	this.text=this.text.replace(/\{{3}((?:.|\n)*?)\}{3}/g,""); // {{{...}}}
	this.text=this.text.replace(/"{3}((?:.|\n)*?)"{3}/g,""); // """..."""
	this.text=this.text.replace(/\<nowiki\>((?:.|\n)*?)\<\/nowiki\>/g,""); // <nowiki>...</nowiki>
	this.text=this.text.replace(/\<html\>((?:.|\n)*?)\<\/html\>/g,""); // <html>...</html>
	this.text=this.text.replace(/\<script((?:.|\n)*?)\<\/script\>/g,""); // <script>...</script>
	this.coreTweaks_changed.apply(this,arguments);
	// restore quoted text to tiddler source
	this.text=savedtext;
};
//}}}
// // }}}
/***
!!! Fixed in current release (TW<<version>>)
***/
// // {{groupbox small{
// // calculate version number for conditional inclusion of tweaks below...
//{{{
var ver=version.major+version.minor/10+version.revision/100;
//}}}
// // }}}
// // {{groupbox small{
/***
!!#filter:"..." paramifier
http://trac.tiddlywiki.org/ticket/678 - FIXED IN TW241
displays all tiddlers that match any filter criteria (including tag-matching), using the {{{store.filterTiddlers()}}} syntax.  Note use of double-quotes to enclose value to ensure that square-brackets within filter syntax are passed through for processing.
***/
//{{{
if (ver<2.41) {
config.paramifiers.filter = {
	onstart: function(v) {
		var tagged = store.filterTiddlers(v);
		story.displayTiddlers(null,tagged,null,false,null);
	}
};
}
//}}}
// // }}}
// // {{groupbox small{
/***
!!#tag:... paramifier
http://trac.tiddlywiki.org/ticket/677 - FIXED IN TW241
use {{{store.filterTiddlers()}}} instead of {{{store.getTaggedTiddlers()}}}.  This permits enhanced tag-matching logic (such as boolean expression processing provided by [[MatchTagsPlugin]]) to be used, e.g., {{{#tag:"tag1 OR (tag2 AND NOT tag3)"}}}, instead of simply matching a single tag value.
***/
//{{{
if (ver<2.41) {
config.paramifiers.tag = {
	onstart: function(v) {
		var tagged = store.filterTiddlers("[tag["+v+"]]");
		story.displayTiddlers(null,tagged,null,false,null);
	}
};
}
//}}}
// // }}}
// // {{groupbox small{
/***
!!#recent:... paramifier
http://trac.tiddlywiki.org/ticket/675 - FIXED IN TW241
automatically display the N most recently changed tiddlers.  N is, of course, an integer number.  If N=0 (or is not a numeric value), the regular [[DefaultTiddlers]] will be displayed.
***/
//{{{
if (ver<2.41) {
config.paramifiers.recent= {
	onstart: function(v) {
		var titles=[];
		var tids=store.getTiddlers("modified","excludeLists").reverse();
		for (var t=0; t<v && t<tids.length; t++) titles.push(tids[t].title);
		story.displayTiddlers(null,titles); 
	}
};
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/635 - FIXED IN TW241
// // When using backstage>import "browse" button, resulting URL is improperly formed with "file://" prefix instead of "file:///" prefix.  This causes errors when using Firefox 3 (beta) or when running under Windows Vista OS.
// // http://trac.tiddlywiki.org/ticket/638 - FIXED IN TW241
// // When entering text directly into path/file field, each keystroke is displayed and then discarded, preventing manual entry of path/file.
// // http://trac.tiddlywiki.org/ticket/639 - FIXED IN TW241
// // Pressing "enter" from URL or Browse input field immediately reloads the current document.  Instead, it should trigger the "open" button for the import wizard (if a URL has been entered)
//{{{
if (ver<2.41) {
// #635 and #638
config.macros.importTiddlers.onBrowseChange = function(e)
{
	var wizard = new Wizard(this);
	var fileInput = wizard.getElement("txtPath");
	fileInput.value = config.macros.importTiddlers.getURLFromLocalPath(this.value); // #635
	var serverType = wizard.getElement("selTypes");
	serverType.value = "file";
	return true; // #638
};
// #635 - fixup local path/file to form absolute URL reference
config.macros.importTiddlers.getURLFromLocalPath = function(v)
{
	if (!v||!v.length) return v;
	v=v.replace(/\\/g,"/"); // use "/" for cross-platform consistency
	var t=v.split(":"); p=t[1]||t[0]; // remove drive letter (if any)
	if (t[1] && (t[0]=="http"||t[0]=="https"||t[0]=="file")) { // input is already a URL
		var u=v;
	} else if (p.substr(0,1)=="/") { // path is absolute, add protocol+domain+extra slash (if drive letter)
		var u=document.location.protocol+"//"+document.location.hostname+(t[1]?"/":"")+v;
	} else { // path is relative, add current document protocol+domain+path
		var c=document.location.href.replace(/\\/g,"/");
		var pos=c.lastIndexOf("/"); if (pos!=-1) c=c.substr(0,pos); // remove filename
		var u=c+"/"+p;
	}
	return u;
}
// #639 - prevent form action and click "open" button if ENTER is pressed
config.macros.importTiddlers.coreTweaks_restart = config.macros.importTiddlers.restart;
config.macros.importTiddlers.restart = function(wizard)
{
	config.macros.importTiddlers.coreTweaks_restart.apply(this,arguments);
	wizard.formElem.action="javascript:;"
	wizard.formElem.onsubmit=function() {
		if (this.txtPath.value.length)
			this.lastChild.firstChild.onclick();  // press "open" button
	}
};
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/623 - FIXED IN TW241
/***
This tweak allows date format strings to contain backslash-quoted characters that bypass date format replacement.  This allows sequences such as "s\s", "m\m" or "a\m" to be used so that "ss", "mm" or "am" can appears as literal text within journal titles or other date-formatted values.

For example:
>{{{<<today "withhold less hummingbirds - YYYY.0MM.0DD 0hh:0mm:0ss">>}}}
>results in: <<today "withhold less hummingbirds - YYYY.0MM.0DD 0hh:0mm:0ss">>
while:
>{{{<<today "with\hold les\s hum\mingbirds - YYYY.0MM.0DD 0hh:0mm:0ss">>}}}
>results in: <<today "with\hold les\s hum\mingbirds - YYYY.0MM.0DD 0hh:0mm:0ss">>
***/
//{{{
if (ver<2.41) {
Date.prototype.coreTweaks_formatString = Date.prototype.formatString;
Date.prototype.formatString = function(template) {
	var t = Date.prototype.coreTweaks_formatString.apply(this,arguments);
	t = t.replace(/\\/g,""); // strip backslashes used to quote formats
	return t;
};
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/578 - FIXED IN TW240
// // This tweak trims any leading whitespace/newline and the trailing newline from tiddler sections
//{{{
if (ver<2.4) {
TiddlyWiki.prototype.coreTweaks_getTiddlerText = TiddlyWiki.prototype.getTiddlerText;
TiddlyWiki.prototype.getTiddlerText = function(title,defaultText)
{
	var r=TiddlyWiki.prototype.coreTweaks_getTiddlerText.apply(this,arguments);
	if (r&&title.indexOf(config.textPrimitives.sectionSeparator)!=-1)
		r=r.replace(/^[ \t]*\n/,"").replace(/\n$/,""); // trim any leading/trailing newlines
	return r;
};
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/541 - FIXED IN TW240
// // This tweak adds a conditional check to the core's 'open' paramifier, so that when the document is viewed in readOnly mode, non-existent tiddlers specified using a permalink/permaview (i.e. "#TiddlerName" in the document URL) will not be displayed as an empty tiddler (which shows the "double-click to create" default text).
//{{{
if (ver<2.4) {
config.paramifiers.open = { 
onstart: function(v) { 
		if(!readOnly || store.tiddlerExists(v) || store.isShadowTiddler(v)) 
			story.displayTiddler("bottom",v,null,false,null); 
	} 
}; 
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/470 - FIXED IN TW240
// // This tweak lets you set an alternative initial focus field when editing a tiddler (default field is "text")
// // Enter initial focus field name: <<option txtEditorFocus>> (//usage:// {{{<<option txtEditorFocus>>}}})
//{{{
if (ver<2.4) {
config.commands.editTiddler.coreTweaks_handler = config.commands.editTiddler.handler;
config.commands.editTiddler.handler = function(event,src,title)
{
	if (config.options.txtEditorFocus==undefined) config.options.txtEditorFocus="text";
	this.coreTweaks_handler.apply(this,arguments);
	story.focusTiddler(title,config.options.txtEditorFocus);
	return false;
};
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/468 - FIXED IN TW240
// // This tweak extends the core's {{{<<tag>>}}} macro to accept additional parameters for specifying alternative label and tooltip text for the tag popup "button" link (i.e., "`PrettyTags").  Based on a suggestion by ~PBee.
//{{{
// hijack tag handler()
if (ver<2.4) {
config.macros.tag.CoreTweaks_handler=config.macros.tag.handler;
config.macros.tag.handler = function(place,macroName,params)
{
	this.CoreTweaks_handler.apply(this,arguments);
	var btn=place.lastChild;
	if (params[1]) btn.innerHTML=params[1];
	if (params[2]) btn.title=params[2];
}
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/320 - FIXED IN TW240
// // This tweak updates the core's forceReflow() function to fix a Firefox rendering problem, whereby the contents of the a tiddler editor text area can be incorrectly displayed (overlapping other content) when more than one tiddler is in edit mode.
//{{{
if (ver<2.4) {
function forceReflow()
{
	if(config.browser.isGecko) {
		setStylesheet("body {top:-0px;margin-top:0px;}");
		setTimeout('setStylesheet("")',1); // invoke async to bypass browser optimization
	}
}
}
//}}}
// // }}}
// // {{groupbox small{
// // http://trac.tiddlywiki.org/ticket/42 - FIXED IN TW240
// // This tweak adjusts the left position of a TW popup so that it won't overlap with the browser window's vertical scrollbar, when present.
//{{{
if (ver<2.4) {
Popup.place = function(root,popup,offset)
{
	if(!offset) var offset = {x:0, y:0};
	var rootLeft = findPosX(root);
	var rootTop = findPosY(root);
	var rootHeight = root.offsetHeight;
	var popupLeft = rootLeft + offset.x;
	var popupTop = rootTop + rootHeight + offset.y;
	var winWidth = findWindowWidth();
	if(popup.offsetWidth > winWidth*0.75)
		popup.style.width = winWidth*0.75 + "px";
	var popupWidth = popup.offsetWidth;
	// ELS: leave space for vertical scrollbar
	var scrollWidth=winWidth-document.body.offsetWidth;
	if(popupLeft+popupWidth > winWidth-scrollWidth-1)
		popupLeft = winWidth-popupWidth-scrollWidth-1;
	popup.style.left = popupLeft + "px";
	popup.style.top = popupTop + "px";
	popup.style.display = "block";
};
}
//}}}
// // }}}
/***
!!!Unticketed Tweaks
***/
// // {{groupbox small{
/***
!!#animate:... paramifier
http://trac.tiddlywiki.org/ticket/TBD - TBD
This tweak provides a paramifier to turn on/off animation
***/
//{{{
config.paramifiers.animate= {
	onstart: function(v) {
		config.options.chkAnimate=eval(v);
	}
};
//}}}
// // }}}
// // {{groupbox small{
// // This tweak adds an optional 'sortby' parameter to the {{{<<tag tagname label tip sortby>>}}} macro, as well as the {{{<<allTags excludeTag sortby>>}}} macro used to generate the sidebar contents 'tags' list.  Specify the field on which the contents of each tag popup is to be sorted, with a "+" or "-" prefix to indicate ascending/descending order, respectively.

// // Example: {{{<<tag systemConfig "plugins" "list plugins by date, most recent first" "-modified">>}}}
// // Try it: <<tag systemConfig "plugins" "list plugins by date, most recent first" "-modified">>

// // Similarly, to change the sort order used by the popups from all tags shown in the sidebar contents, edit the [[TagTags]] shadow tiddler and enter: {{{<<allTags excludeLists -modified>>}}}

//{{{
// hijack tag handler() to add 'sortby' attribute to tag button
config.macros.tag.CoreTweaksSortTags_handler=config.macros.tag.handler;
config.macros.tag.handler = function(place,macroName,params)
{
	this.CoreTweaksSortTags_handler.apply(this,arguments);
	var btn=place.lastChild;
	if (params[3]) btn.setAttribute("sortby",params[3]);
}

// TWEAK <<allTags>> macro to add 'sortby' attribute to each tag button
var fn=config.macros.allTags.handler;
var lines=fn.toString().split("\n");
lines.splice(lines.length-2,0,['if(params[1]) btn.setAttribute("sortby",params[1]);']);
fn=lines.join("\n");
eval("config.macros.allTags.handler="+fn);

// TWEAK event handler for clicking on a tiddler tag to use 'sortby' attribute
var fn=onClickTag;
fn=fn.toString().replace(
	/store.getTaggedTiddlers\(tag\);/g,
	'store.getTaggedTiddlers(tag);'
	+'var sortby=this.getAttribute("sortby");'
	+'if(sortby&&sortby.length) store.sortTiddlers(tagged,sortby);'
);
eval(fn);

//}}}
// // }}}
// // {{groupbox small{
// // This HIJACK tweak pre-processes source content to convert "double-backslash-newline" into {{{<br>}}} before wikify(), so that literal newlines can be embedded in line-mode wiki syntax (e.g., tables, bullets, etc.).  Based on a suggestion from Sitaram Chamarty.
//{{{
window.coreWikify = wikify;
window.wikify = function(source,output,highlightRegExp,tiddler)
{
	if (source) arguments[0]=source.replace(/\\\\\n/mg,"<br>");
	coreWikify.apply(this,arguments);
}
//}}}
// // }}}
/***
|Name|DatePlugin|
|Source|http://www.TiddlyTools.com/#DatePlugin|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.7.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||
|Options|##Configuration|
|Description|formatted dates plus popup menu with 'journal' link, changes and (optional) reminders|
There are quite a few calendar generators, reminders, to-do lists, 'dated tiddlers' journals, blog-makers and GTD-like schedule managers that have been built around TW.  While they all have different purposes, and vary in format, interaction, and style, in one way or another each of these plugins displays and/or uses date-based information to make finding, accessing and managing relevant tiddlers easier.  This plugin provides a general approach to embedding dates and date-based links/menus within tiddler content.
!!!!!Documentation
>see [[DatePluginInfo]]
!!!!!Configuration
<<<
<<option chkDatePopupHideCreated>> omit 'created' section from date popups
<<option chkDatePopupHideChanged>> omit 'changed' section from date popups
<<option chkDatePopupHideTagged>> omit 'tagged' section from date popups
<<option chkDatePopupHideReminders>> omit 'reminders' section from date popups
<<option chkShowJulianDate>> display Julian day number (1-365) below current date

see [[DatePluginConfig]] for additional configuration settings, for use in calendar displays, including:
*date formats
*color-coded backgrounds
*annual fixed-date holidays
*weekends
<<<
!!!!!Revisions
<<<
2008.03.08 [2.7.0] in addModifiedsToPopup(), if a tiddler was created on the specified date, don't list it in the 'changed' section of the popup.  Based on a request from Kashgarinn.
|please see [[DatePluginInfo]] for additional revision details|
2005.10.30 [0.9.0] pre-release
<<<
!!!!!Code
***/
//{{{
version.extensions.date = {major: 2, minor: 7, revision: 0, date: new Date(2008,3,8)};

config.macros.date = {
	format: "YYYY.0MM.0DD", // default date display format
	linkformat: "YYYY.0MM.0DD", // 'dated tiddler' link format
	linkedbg: "#babb1e", // "babble"
	todaybg: "#ffab1e", // "fable"
	weekendbg: "#c0c0c0", // "cocoa"
	holidaybg: "#ffaace", // "face"
	createdbg: "#bbeeff", // "beef"
	modifiedsbg: "#bbeeff", // "beef"
	remindersbg: "#c0ffee", // "coffee"
	holidays: [ "01/01", "07/04", "07/24", "11/24" ], // NewYearsDay, IndependenceDay(US), Eric's Birthday (hooray!), Thanksgiving(US)
	weekend: [ 1,0,0,0,0,0,1 ] // [ day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6 ]
};

config.macros.date.handler = function(place,macroName,params)
{
	// do we want to see a link, a popup, or just a formatted date?
	var mode="display";
	if (params[0]=="display") { mode=params[0]; params.shift(); }
	if (params[0]=="popup") { mode=params[0]; params.shift(); }
	if (params[0]=="link") { mode=params[0]; params.shift(); }
	// get the date
	var now = new Date();
	var date = now;
	if (!params[0] || params[0]=="today")
		{ params.shift(); }
	else if (params[0]=="filedate")
		{ date=new Date(document.lastModified); params.shift(); }
	else if (params[0]=="tiddler")
		{ date=store.getTiddler(story.findContainingTiddler(place).id.substr(7)).modified; params.shift(); }
	else if (params[0].substr(0,8)=="tiddler:")
		{ var t; if ((t=store.getTiddler(params[0].substr(8)))) date=t.modified; params.shift(); }
	else {
		var y = eval(params.shift().replace(/Y/ig,(now.getYear()<1900)?now.getYear()+1900:now.getYear()));
		var m = eval(params.shift().replace(/M/ig,now.getMonth()+1));
		var d = eval(params.shift().replace(/D/ig,now.getDate()+0));
		date = new Date(y,m-1,d);
	}
	// date format with optional custom override
	var format=this.format; if (params[0]) format=params.shift();
	var linkformat=this.linkformat; if (params[0]) linkformat=params.shift();
	showDate(place,date,mode,format,linkformat);
}

window.showDate=showDate;
function showDate(place,date,mode,format,linkformat,autostyle,weekend)
{
	if (!mode) mode="display";
	if (!format) format=config.macros.date.format;
	if (!linkformat) linkformat=config.macros.date.linkformat;
	if (!autostyle) autostyle=false;

	// format the date output
	var title = date.formatString(format);
	var linkto = date.formatString(linkformat);

	// just show the formatted output
	if (mode=="display") { place.appendChild(document.createTextNode(title)); return; }

	// link to a 'dated tiddler'
	var link = createTiddlyLink(place, linkto, false);
	link.appendChild(document.createTextNode(title));
	link.title = linkto;
	link.date = date;
	link.format = format;
	link.linkformat = linkformat;

	// if using a popup menu, replace click handler for dated tiddler link
	// with handler for popup and make link text non-italic (i.e., an 'existing link' look)
	if (mode=="popup") {
		link.onclick = onClickDatePopup;
		link.style.fontStyle="normal";
	}
	// format the popup link to show what kind of info it contains (for use with calendar generators)
	if (autostyle) setDateStyle(place,link,weekend);
}
//}}}

//{{{
// NOTE: This function provides default logic for setting the date style when displayed in a calendar
// To customize the date style logic, please see[[DatePluginConfig]]
function setDateStyle(place,link,weekend) {
	// alias variable names for code readability
	var date=link.date;
	var fmt=link.linkformat;
	var linkto=date.formatString(fmt);
	var cmd=config.macros.date;

	if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=""))
		{ place.style.background = cmd.weekendbg; }
	if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
		{ link.style.fontStyle="normal"; link.style.fontWeight="bold"; }
	if (hasReminders(date))
		{ link.style.textDecoration="underline"; }
	if (isToday(date))
		{ link.style.border="1px solid black"; }
	if (isHoliday(date)&&(cmd.holidaybg!=""))
		{ place.style.background = cmd.holidaybg; }
	if (hasCreateds(date)&&(cmd.createdbg!=""))
		{ place.style.background = cmd.createdbg; }
	if (hasModifieds(date)&&(cmd.modifiedsbg!=""))
		{ place.style.background = cmd.modifiedsbg; }
	if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=""))
		{ place.style.background = cmd.linkedbg; }
	if (hasReminders(date)&&(cmd.remindersbg!=""))
		{ place.style.background = cmd.remindersbg; }
	if (isToday(date)&&(cmd.todaybg!=""))
		{ place.style.background = cmd.todaybg; }
	if (config.options.chkShowJulianDate) { // optional display of Julian date numbers
		var m=[0,31,59,90,120,151,181,212,243,273,304,334];
		var d=date.getDate()+m[date.getMonth()];
		var y=date.getFullYear();
		if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0)
			d++; // after February in a leap year
		wikify("@@font-size:80%;<br>"+d+"@@",place);
	}

}
//}}}

//{{{
function isToday(date) // returns true if date is today
	{ var now=new Date(); return ((now-date>=0) && (now-date<86400000)); }

function isWeekend(date) // returns true if date is a weekend
	{ return (config.macros.date.weekend[date.getDay()]); }

function isHoliday(date) // returns true if date is a holiday
{
	var longHoliday = date.formatString("0MM/0DD/YYYY");
	var shortHoliday = date.formatString("0MM/0DD");
	for(var i = 0; i < config.macros.date.holidays.length; i++) {
		var holiday=config.macros.date.holidays[i];
		if (holiday==longHoliday||holiday==shortHoliday) return true;
	}
	return false;
}
//}}}

//{{{
// Event handler for clicking on a day popup
function onClickDatePopup(e)
{
	if (!e) var e = window.event;
	var theTarget = resolveTarget(e);
	var popup = Popup.create(this);
	if(popup) {
		// always show dated tiddler link (or just date, if readOnly) at the top...
		if (!readOnly || store.tiddlerExists(this.date.formatString(this.linkformat)))
			createTiddlyLink(popup,this.date.formatString(this.linkformat),true);
		else
			createTiddlyText(popup,this.date.formatString(this.linkformat));
		if (!config.options.chkDatePopupHideCreated)
			addCreatedsToPopup(popup,this.date,this.format);
		if (!config.options.chkDatePopupHideChanged)
			addModifiedsToPopup(popup,this.date,this.format);
		if (!config.options.chkDatePopupHideTagged)
			addTaggedToPopup(popup,this.date,this.linkformat);
		if (!config.options.chkDatePopupHideReminders)
			addRemindersToPopup(popup,this.date,this.linkformat);
	}
	Popup.show(popup,false);
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

//{{{
function indexCreateds() // build list of tiddlers, hash indexed by creation date
{
	var createds= { };
	var tiddlers = store.getTiddlers("title","excludeLists");
	for (var t = 0; t < tiddlers.length; t++) {
		var date = tiddlers[t].created.formatString("YYYY0MM0DD")
		if (!createds[date])
			createds[date]=new Array();
		createds[date].push(tiddlers[t].title);
	}
	return createds;
}
function hasCreateds(date) // returns true if date has created tiddlers
{
	if (!config.macros.date.createds) config.macros.date.createds=indexCreateds();
	return (config.macros.date.createds[date.formatString("YYYY0MM0DD")]!=undefined);
}

function addCreatedsToPopup(popup,when,format)
{
	var force=(store.isDirty() && when.formatString("YYYY0MM0DD")==new Date().formatString("YYYY0MM0DD"));
	if (force || !config.macros.date.createds) config.macros.date.createds=indexCreateds();
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	var createds = config.macros.date.createds[when.formatString("YYYY0MM0DD")];
	if (createds) {
		createds.sort();
		var e=createTiddlyElement(popup,"div",null,null,"created ("+createds.length+")");
		for(var t=0; t<createds.length; t++) {
			var link=createTiddlyLink(popup,createds[t],false);
			link.appendChild(document.createTextNode(indent+createds[t]));
			createTiddlyElement(popup,"br",null,null,null);
		}
	}
}
//}}}

//{{{
function indexModifieds() // build list of tiddlers, hash indexed by modification date
{
	var modifieds= { };
	var tiddlers = store.getTiddlers("title","excludeLists");
	for (var t = 0; t < tiddlers.length; t++) {
		var date = tiddlers[t].modified.formatString("YYYY0MM0DD")
		if (!modifieds[date])
			modifieds[date]=new Array();
		modifieds[date].push(tiddlers[t].title);
	}
	return modifieds;
}
function hasModifieds(date) // returns true if date has modified tiddlers
{
	if (!config.macros.date.modifieds) config.macros.date.modifieds = indexModifieds();
	return (config.macros.date.modifieds[date.formatString("YYYY0MM0DD")]!=undefined);
}

function addModifiedsToPopup(popup,when,format)
{
	var date=when.formatString("YYYY0MM0DD");
	var force=(store.isDirty() && date==new Date().formatString("YYYY0MM0DD"));
	if (force || !config.macros.date.modifieds) config.macros.date.modifieds=indexModifieds();
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	var mods = config.macros.date.modifieds[date];
	if (mods) {
		// if a tiddler was created on this date, don't list it in the 'changed' section
		if (config.macros.date.createds && config.macros.date.createds[date]) {
			var temp=[];
			for(var t=0; t<mods.length; t++)
				if (!config.macros.date.createds[date].contains(mods[t]))
					temp.push(mods[t]);
			mods=temp;
		}
		mods.sort();
		var e=createTiddlyElement(popup,"div",null,null,"changed ("+mods.length+")");
		for(var t=0; t<mods.length; t++) {
			var link=createTiddlyLink(popup,mods[t],false);
			link.appendChild(document.createTextNode(indent+mods[t]));
			createTiddlyElement(popup,"br",null,null,null);
		}
	}
}
//}}}

//{{{
function hasTagged(date,format) // returns true if date is tagging other tiddlers
{
	return store.getTaggedTiddlers(date.formatString(format)).length>0;
}

function addTaggedToPopup(popup,when,format)
{
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	var tagged=store.getTaggedTiddlers(when.formatString(format));
	if (tagged.length) var e=createTiddlyElement(popup,"div",null,null,"tagged ("+tagged.length+")");
	for(var t=0; t<tagged.length; t++) {
		var link=createTiddlyLink(popup,tagged[t].title,false);
		link.appendChild(document.createTextNode(indent+tagged[t].title));
		createTiddlyElement(popup,"br",null,null,null);
	}
}
//}}}

//{{{
function indexReminders(date,leadtime) // build list of tiddlers with reminders, hash indexed by reminder date
{
	var reminders = { };
	if(window.findTiddlersWithReminders!=undefined) { // reminder plugin is installed
		// DEBUG var starttime=new Date();
		var t = findTiddlersWithReminders(date, [0,leadtime], null, null, 1);
		for(var i=0; i<t.length; i++) reminders[t[i].matchedDate]=true;
		// DEBUG var out="Found "+t.length+" reminders in "+((new Date())-starttime+1)+"ms\n";
		// DEBUG out+="startdate: "+date.toLocaleDateString()+"\n"+"leadtime: "+leadtime+" days\n\n";
		// DEBUG for(var i=0; i<t.length; i++) { out+=t[i].matchedDate.toLocaleDateString()+" "+t[i].params.title+"\n"; }
		// DEBUG alert(out);
	}
	return reminders;
}

function hasReminders(date) // returns true if date has reminders
{
	if (window.reminderCacheForCalendar)
		return window.reminderCacheForCalendar[date]; // use calendar cache
	if (!config.macros.date.reminders)
		config.macros.date.reminders = indexReminders(date,90); // create a 90-day leadtime reminder cache
	return (config.macros.date.reminders[date]);
}

function addRemindersToPopup(popup,when,format)
{
	if(window.findTiddlersWithReminders==undefined) return; // reminder plugin not installed

	var indent = String.fromCharCode(160)+String.fromCharCode(160);
	var reminders=findTiddlersWithReminders(when, [0,31],null,null,1);
	createTiddlyElement(popup,"div",null,null,"reminders ("+(reminders.length||"none")+")");
	for(var t=0; t<reminders.length; t++) {
		link = createTiddlyLink(popup,reminders[t].tiddler,false);
		var diff=reminders[t].diff;
		diff=(diff<1)?"Today":((diff==1)?"Tomorrow":diff+" days");
		var txt=(reminders[t].params["title"])?reminders[t].params["title"]:reminders[t].tiddler;
		link.appendChild(document.createTextNode(indent+diff+" - "+txt));
		createTiddlyElement(popup,"br",null,null,null);
	}
	if (readOnly) return;	// omit "new reminder..." link
	var link = createTiddlyLink(popup,indent+"new reminder...",true); createTiddlyElement(popup,"br");
	var title = when.formatString(format);
	link.title="add a reminder to '"+title+"'";
	link.onclick = function() {
		// show tiddler editor
		story.displayTiddler(null, title, 2, null, null, false, false);
		// find body 'textarea'
		var c =document.getElementById("tiddler" + title).getElementsByTagName("*");
		for (var i=0; i<c.length; i++) if ((c[i].tagName.toLowerCase()=="textarea") && (c[i].getAttribute("edit")=="text")) break;
		// append reminder macro to tiddler content
		if (i<c.length) {
			if (store.tiddlerExists(title)) c[i].value+="\n"; else c[i].value="";
			c[i].value += "<<reminder";
			c[i].value += " day:"+when.getDate();
			c[i].value += " month:"+(when.getMonth()+1);
			c[i].value += " year:"+when.getFullYear();
			c[i].value += ' title:"Enter a title" >>';
		}
	};
}
//}}}
//{{{

config.macros.date.holidays=[ ]; // use reminders instead

if (config.options.chkGTDFancyStyle) {
 // these colours are somewhat friendlier to the default d3 menu colour scheme
 config.macros.calendar.weekendbg= "seagreen";
 config.macros.calendar.monthbg = "transparent";

 config.macros.date.weekendbg="seagreen";
 config.macros.date.holidaybg="seagreen";
 config.macros.date.modifiedsbg="transparent";
 config.macros.date.remindersbg="red";
}


//}}}
[[Summary Review]]
Einkaufen
lt. Standard-Einkaufszettel
immer Montags

<<reminder dayofweek:1 title:"Einkaufen" leadtime:1 >>
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.7.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|select and extract tiddlers from your ~TiddlyWiki documents and save them to a separate file|
ExportTiddlersPlugin lets you select and extract tiddlers from your ~TiddlyWiki documents using interactive control panel lets you specify a destination, and then select which tiddlers to export. Tiddler data can be output as complete, stand-alone TiddlyWiki documents, or just the selected tiddlers ("~PureStore" format -- smaller files!) that can be imported directly into another ~TiddlyWiki, or as an ~RSS-compatible XML file that can be published for RSS syndication.
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2008.05.27 [2.7.0] added ability to 'merge' with existing export file. Also, revised 'matchTags' functionality to be more robust and more efficient
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 [0.0.0] development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.exportTiddlers = {major: 2, minor: 7, revision: 0, date: new Date(2008,5,27)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers="<<exportTiddlers inline>>";

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		text:"export",
		tooltip:"Export selected tiddlers to another file",
		content:"<<exportTiddlers inline>>"
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf("importTask")+1,0,"exportTask");
}

// macro handler
config.macros.exportTiddlers = {
	label: "export tiddlers",
	prompt: "Copy selected tiddlers to an export document",
	newdefault: "export.html",
	datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss" // for "filter date/time" edit fields
};

config.macros.exportTiddlers.handler = function(place,macroName,params) {
	if (params[0]!="inline")
		{ createTiddlyButton(place,this.label,this.prompt,onClickExportMenu); return; }
	var panel=createExportPanel(place);
	panel.style.position="static";
	panel.style.display="block";
}

function createExportPanel(place) {
	var panel=document.getElementById("exportPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(config.macros.exportTiddlers.css,"exportTiddlers");
	panel=createTiddlyElement(place,"span","exportPanel",null,null)
	panel.innerHTML=config.macros.exportTiddlers.html;
	exportInitFilter();
	refreshExportList(0);
	var fn=document.getElementById("exportFilename");
	if (window.location.protocol=="file:" && !fn.value.length) {
		// get new target path/filename
		var newPath=getLocalPath(window.location.href);
		var slashpos=newPath.lastIndexOf("/"); if (slashpos==-1) slashpos=newPath.lastIndexOf("\\"); 
		if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
		fn.value=newPath+config.macros.exportTiddlers.newdefault;
	}
	return panel;
}

function onClickExportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("exportPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createExportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	if (panel.style.display!="none") { // update list and set focus when panel is made visible
		refreshExportList(0);
		var fn=document.getElementById("exportFilename"); fn.focus(); fn.select();
	}
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

// // IE needs explicit scoping for functions called by browser events
//{{{
window.onClickExportMenu=onClickExportMenu;
window.onClickExportButton=onClickExportButton;
window.exportShowFilterFields=exportShowFilterFields;
window.refreshExportList=refreshExportList;
//}}}

// // CSS for floating export control panel
//{{{
config.macros.exportTiddlers.css = '\
#exportPanel {\
	display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;\
	background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#exportPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\
#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\
#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%; }\
#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }\
#exportPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px; }\
#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
#exportPanel .rad { width:auto;border:0 }\
#exportPanel .chk { width:auto;border:0 }\
#exportPanel .btn { width:auto; }\
#exportPanel .btn1 { width:98%; }\
#exportPanel .btn2 { width:48%; }\
#exportPanel .btn3 { width:32%; }\
#exportPanel .btn4 { width:24%; }\
#exportPanel .btn5 { width:19%; }\
';
//}}}

// // HTML for export control panel interface
//{{{
config.macros.exportTiddlers.html = '\
<!-- target path/file  -->\
<div>\
export to path/filename:<br>\
<input type="text" id="exportFilename" size=40 style="width:93%"><input \
	type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
	onclick="var fn=window.promptForExportFilename(this); if (fn.length) this.previousSibling.value=fn; ">\
</div>\
\
<!-- output format -->\
<div>\
output file format:\
<select id="exportFormat" size=1>\
<option value="TW">TiddlyWiki document (includes core code)</option>\
<option value="DIV">TiddlyWiki "PureStore" file (tiddler data only)</option>\
<option value="XML">XML (for RSS newsfeed)</option>\
</select>\
</div>\
\
<!-- notes -->\
<div>\
notes:<br>\
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
</div>\
\
<!-- list of tiddlers -->\
<table><tr align="left"><td>\
	select:\
	<a href="JavaScript:;" id="exportSelectAll"\
		onclick="onClickExportButton(this)" title="select all tiddlers">\
		&nbsp;all&nbsp;</a>\
	<a href="JavaScript:;" id="exportSelectChanges"\
		onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\
		&nbsp;changes&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectOpened"\
		onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\
		&nbsp;opened&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectRelated"\
		onclick="onClickExportButton(this)" title="select all tiddlers related (by link or transclusion) to the currently selected tiddlers">\
		&nbsp;related&nbsp;</a> \
	<a href="JavaScript:;" id="exportToggleFilter"\
		onclick="onClickExportButton(this)" title="show/hide selection filter">\
		&nbsp;filter&nbsp;</a>  \
</td><td align="right">\
	<a href="JavaScript:;" id="exportListSmaller"\
		onclick="onClickExportButton(this)" title="reduce list size">\
		&nbsp;&#150;&nbsp;</a>\
	<a href="JavaScript:;" id="exportListLarger"\
		onclick="onClickExportButton(this)" title="increase list size">\
		&nbsp;+&nbsp;</a>\
</td></tr></table>\
<select id="exportList" multiple size="10" style="margin-bottom:5px;"\
	onchange="refreshExportList(this.selectedIndex)">\
</select><br>\
</div><!--box-->\
\
<!-- selection filter -->\
<div id="exportFilterPanel" style="display:none">\
<table><tr align="left"><td>\
	selection filter\
</td><td align="right">\
	<a href="JavaScript:;" id="exportHideFilter"\
		onclick="onClickExportButton(this)" title="hide selection filter">hide</a>\
</td></tr></table>\
<div class="box">\
<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
	onclick="exportShowFilterFields(this)"> starting date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterStartBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportStartDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterStartBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
	onclick="exportShowFilterFields(this)"> ending date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterEndBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportEndDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterEndBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id=exportFilterTags value="1"\
	onclick="exportShowFilterFields(this)"> match tags<br>\
<input type="text" id="exportTags" onfocus="this.select()">\
<input type="checkbox" class="chk" id=exportFilterText value="1"\
	onclick="exportShowFilterFields(this)"> match titles/tiddler text<br>\
<input type="text" id="exportText" onfocus="this.select()">\
</div> <!--box-->\
</div> <!--panel-->\
\
<!-- action buttons -->\
<div style="text-align:center">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportFilter" value="apply filter">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportStart" value="export tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportDelete" value="delete tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportClose" value="close">\
</div><!--center-->\
';
//}}}

// // initialize interface

// // exportInitFilter()
//{{{
function exportInitFilter() {
	// start date
	document.getElementById("exportFilterStart").checked=false;
	document.getElementById("exportStartDate").value="";
	// end date
	document.getElementById("exportFilterEnd").checked=false;
	document.getElementById("exportEndDate").value="";
	// tags
	document.getElementById("exportFilterTags").checked=false;
	document.getElementById("exportTags").value="";
	// text
	document.getElementById("exportFilterText").checked=false;
	document.getElementById("exportText").value="";
	// show/hide filter input fields
	exportShowFilterFields();
}
//}}}

// // exportShowFilterFields(which)
//{{{
function exportShowFilterFields(which) {
	var show;

	show=document.getElementById('exportFilterStart').checked;
	document.getElementById('exportFilterStartBy').style.display=show?"block":"none";
	document.getElementById('exportStartDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterStartBy').value;
	document.getElementById('exportStartDate').value
		=getFilterDate(val,'exportStartDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterStartBy') && (val=='other'))
		document.getElementById('exportStartDate').focus();

	show=document.getElementById('exportFilterEnd').checked;
	document.getElementById('exportFilterEndBy').style.display=show?"block":"none";
	document.getElementById('exportEndDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterEndBy').value;
	document.getElementById('exportEndDate').value
		=getFilterDate(val,'exportEndDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterEndBy') && (val=='other'))
		document.getElementById('exportEndDate').focus();

	show=document.getElementById('exportFilterTags').checked;
	document.getElementById('exportTags').style.display=show?"block":"none";

	show=document.getElementById('exportFilterText').checked;
	document.getElementById('exportText').style.display=show?"block":"none";
}
//}}}

// // onClickExportButton(which): control interactions
//{{{
function onClickExportButton(which)
{
	// DEBUG alert(which.id);
	var theList=document.getElementById('exportList'); if (!theList) return;
	var count = 0;
	var total = store.getTiddlers('title').length;
	switch (which.id)
		{
		case 'exportFilter':
			count=filterExportList();
			var panel=document.getElementById('exportFilterPanel');
			if (count==-1) { panel.style.display='block'; break; }
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage("filtered "+formatExportMessage(count,total));
			if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }
			break;
		case 'exportStart':
			exportTiddlers();
			break;
		case 'exportDelete':
			exportDeleteTiddlers();
			break;
		case 'exportHideFilter':
		case 'exportToggleFilter':
			var panel=document.getElementById('exportFilterPanel')
			panel.style.display=(panel.style.display=='block')?'none':'block';
			break;
		case 'exportSelectChanges':
			var lastmod=new Date(document.lastModified);
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
				theList.options[t].selected=(tiddler.modified>lastmod);
				count += (tiddler.modified>lastmod)?1:0;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no unsaved changes");
			break;
		case 'exportSelectAll':
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				theList.options[t].selected=true;
				count += 1;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,count));
			break;
		case 'exportSelectOpened':
			for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;
			var tiddlerDisplay = document.getElementById("tiddlerDisplay"); // for TW2.1-
			if (!tiddlerDisplay) tiddlerDisplay = document.getElementById("storyDisplay"); // for TW2.2+
			for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {
				var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
				for (var i = 0; i < theList.options.length; i++) {
					if (theList.options[i].value!=tiddler) continue;
					theList.options[i].selected=true; count++; break;
				}
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no tiddlers currently opened");
			break;
		case 'exportSelectRelated':
			// recursively build list of related tiddlers
			function getRelatedTiddlers(tid,tids) {
				var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
				tids.push(t.title);
				if (!t.linksUpdated) t.changed();
				for (var i=0; i<t.links.length; i++)
					if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
				return tids;
			}
			// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
			var tids=[];
			for (var i=0; i<theList.options.length; i++)
				if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
			// select related tiddlers (includes original selected tiddlers)
			for (var i=0; i<theList.options.length; i++)
				theList.options[i].selected=tids.contains(theList.options[i].value);
			clearMessage(); displayMessage(formatExportMessage(tids.length,total));
			break;
		case 'exportListSmaller':	// decrease current listbox size
			var min=5;
			theList.size-=(theList.size>min)?1:0;
			break;
		case 'exportListLarger':	// increase current listbox size
			var max=(theList.options.length>25)?theList.options.length:25;
			theList.size+=(theList.size<max)?1:0;
			break;
		case 'exportClose':
			document.getElementById('exportPanel').style.display='none';
			break;
		}
}
//}}}

// // promptForFilename(msg,path,file) uses platform/browser specific functions to get local filespec
//{{{
window.promptForExportFilename=function(here)
{
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file=config.macros.exportTiddlers.newdefault;
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeSave);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}
//}}}

// // list display
//{{{
function formatExportMessage(count,total)
{
	var txt=total+' tiddler'+((total!=1)?'s':'')+" - ";
	txt += (count==0)?"none":(count==total)?"all":count;
	txt += " selected for export";
	return txt;
}

function refreshExportList(selectedIndex)
{
	var theList  = document.getElementById("exportList");
	var sort;
	if (!theList) return;
	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) sort='modified';
	if (selectedIndex==1) sort='title';
	if (selectedIndex==2) sort='modified';
	if (selectedIndex==3) sort='modifier';
	if (selectedIndex==4) sort='tags';

	// unselect headings and count number of tiddlers actually selected
	var count=0;
	for (var t=5; t < theList.options.length; t++) {
		if (!theList.options[t].selected) continue;
		if (theList.options[t].value!="")
			count++;
		else { // if heading is selected, deselect it, and then select and count all in section
			theList.options[t].selected=false;
			for ( t++; t<theList.options.length && theList.options[t].value!=""; t++) {
				theList.options[t].selected=true;
				count++;
			}
		}
	}

	// disable "export" and "delete" buttons if no tiddlers selected
	document.getElementById("exportStart").disabled=(count==0);
	document.getElementById("exportDelete").disabled=(count==0);
	// show selection count
	var tiddlers = store.getTiddlers('title');
	if (theList.options.length) { clearMessage(); displayMessage(formatExportMessage(count,tiddlers.length)); }

	// if a [command] item, reload list... otherwise, no further refresh needed
	if (selectedIndex>4)  return;

	// clear current list contents
	while (theList.length > 0) { theList.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	theList.options[i++]=
		new Option(tiddlers.length+" tiddlers in document", "",false,false);
	theList.options[i++]=
		new Option(((sort=="title"        )?">":indent)+' [by title]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="tags"	)?">":indent)+' [by tags]', "",false,false);
	// output the tiddler list
	switch(sort)
		{
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modifier":
		case "modified":
			var tiddlers = store.getTiddlers(sort);
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++)
				{
				var tiddler = tiddlers[t];
				var theSection = "";
				if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();
				if (sort=="modifier") theSection=tiddler.modifier;
				if (theSection != lastSection)
					{
					theList.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
					}
				theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
				}
			 break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				theList.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	theList.selectedIndex=selectedIndex;		  // select current control item
	document.getElementById("exportStart").disabled=true;
	document.getElementById("exportDelete").disabled=true;
	clearMessage(); displayMessage(formatExportMessage(0,tiddlers.length));
}
//}}}

// // list filtering
//{{{
function getFilterDate(val,id)
{
	var result=0;
	switch (val) {
		case 'site':
			var timestamp=store.getTiddlerText("SiteDate");
			if (!timestamp) timestamp=document.lastModified;
			result=new Date(timestamp);
			break;
		case 'file':
			result=new Date(document.lastModified);
			break;
		case 'other':
			result=new Date(document.getElementById(id).value);
			break;
		default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
			var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
			var oneday=86400000;
			if (id=='exportStartDate')
				result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
			else
				result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
			break;
	}
	// DEBUG alert('getFilterDate('+val+','+id+')=='+result+"\nnow="+now);
	return result;
}

function filterExportList()
{
	var theList  = document.getElementById("exportList"); if (!theList) return -1;

	var filterStart=document.getElementById("exportFilterStart").checked;
	var val=document.getElementById("exportFilterStartBy").value;
	var startDate=getFilterDate(val,'exportStartDate');

	var filterEnd=document.getElementById("exportFilterEnd").checked;
	var val=document.getElementById("exportFilterEndBy").value;
	var endDate=getFilterDate(val,'exportEndDate');

	var filterTags=document.getElementById("exportFilterTags").checked;
	var tags=document.getElementById("exportTags").value;

	var filterText=document.getElementById("exportFilterText").checked;
	var text=document.getElementById("exportText").value;

	if (!(filterStart||filterEnd||filterTags||filterText)) {
		alert("Please set the selection filter");
		document.getElementById('exportFilterPanel').style.display="block";
		return -1;
	}
	if (filterStart&&filterEnd&&(startDate>endDate)) {
		var msg="starting date/time:\n"
		msg+=startDate.toLocaleString()+"\n";
		msg+="is later than ending date/time:\n"
		msg+=endDate.toLocaleString()
		alert(msg);
		return -1;
	}

	// if filter by tags, set up conditional expression
	if (filterTags) {
		var all = store.getTags(); // get list of all tags
		for (var i=0; i<all.length; i++) all[i]=all[i][0]; // remove tag counts
		// convert "tag1 AND ( tag2 OR NOT tag3 )"
		// into javascript expression containing regexp tests:
		// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag2\~/.test(...) )"
		var c=tags;
		c = c.replace(/[\[\]]/g,""); // remove [[...]] quoting around tagvalues
		// change AND/OR/NOT/parens to javascript operators and delimit terms with "~"
		c = c.replace(/\sand\s/ig,"~&&~");
		c = c.replace(/\sor\s/ig,"~||~");
		c = c.replace(/(\s)?not([\s\(])/ig,"~!~$2");
		c = c.replace(/([\(\)])/ig,"~$1~");
		// change existing tags to regexp tests and non-existing tags to "false"
		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
			terms[i]=!all.contains(t)?"false":("/\\~"+t+"\\~/.test(tiddlertags)");
		}
		c=terms.join(" ");
	}
	function matchTags(t,c) {
		if (!c||!c.trim().length) return false;
		// assemble tags from tiddler into string "~tag1~tag2~tag3~"
		var tiddlertags = "~"+t.tags.join("~")+"~";
		// eval string against boolean test expression
		try { if(eval(c)) return true; }
		catch(e) { displayMessage(e.toString()); }
		return false;
	}
	
	// scan list and select tiddlers that match all applicable criteria
	var total=0;
	var count=0;
	for (var i=0; i<theList.options.length; i++) {
		// get item, skip non-tiddler list items (section headings)
		var opt=theList.options[i]; if (opt.value=="") continue;
		// get tiddler, skip missing tiddlers (this should NOT happen)
		var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
		var sel=true;
		if ( (filterStart && tiddler.modified<startDate)
		|| (filterEnd && tiddler.modified>endDate)
		|| (filterTags && !matchTags(tiddler,c))
		|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
			sel=false;
		opt.selected=sel;
		count+=sel?1:0;
		total++;
	}
	return count;
}
//}}}

// // OUTPUT FORMATTING AND FILE I/O
//{{{
function exportTWHeader()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything up to store area
	return source.substr(0,posOpeningDiv+startSaveArea.length);
}

function exportTWFooter()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything after store area
	return source.substr(posClosingDiv);
}

function exportDIVHeader()
{
	var out=[];
	var now = new Date();
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<html><body>");
	out.push("<style type=\"text/css\">");
	out.push("#storeArea {display:block;margin:1em;}");
	out.push("#storeArea div");
	out.push("{padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}");
	out.push("#javascriptWarning");
	out.push("{width:100%;text-align:left;background-color:#eeeeee;padding:1em;}");
	out.push("</style>");
	out.push("<div id=\"javascriptWarning\">");
	out.push("TiddlyWiki export file<br>");
	out.push("Source"+": <b>"+convertUnicodeToUTF8(document.location.href)+"</b><br>");
	out.push("Title: <b>"+title+"</b><br>");
	out.push("Subtitle: <b>"+subtitle+"</b><br>");
	out.push("Created: <b>"+now.toLocaleString()+"</b> by <b>"+user+"</b><br>");
	out.push("TiddlyWiki "+twver+" / "+"ExportTiddlersPlugin "+pver+"<br>");
	out.push("Notes:<hr><pre>"+document.getElementById("exportNotes").value.replace(/\n/g,"<br>")+"</pre>");
	out.push("</div>");
	out.push("<div id=\"storeArea\">");
	return out;
}

function exportDIVFooter()
{
	return ["</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>"];
}

function exportXMLHeader()
{
	var out=[];
	var now = new Date();
	var u = store.getTiddlerText("SiteUrl",null);
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<" + "?xml version=\"1.0\"?" + ">");
	out.push("<rss version=\"2.0\">");
	out.push("<channel>");
	out.push("<title>" + title + "</title>");
	if(u) out.push("<link>" + convertUnicodeToUTF8(u.htmlEncode()) + "</link>");
	out.push("<description>" + subtitle + "</description>");
	out.push("<language>en-us</language>");
	out.push("<copyright>Copyright " + now.getFullYear() + " " + user + "</copyright>");
	out.push("<pubDate>" + now.toGMTString() + "</pubDate>");
	out.push("<lastBuildDate>" + now.toGMTString() + "</lastBuildDate>");
	out.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
	out.push("<generator>TiddlyWiki "+twver+" plus ExportTiddlersPlugin "+pver+"</generator>");
	return out;
}

function exportXMLFooter()
{
	return ["</channel></rss>"];
}

function exportData(target,list,fmt)
{
	function getData(s,f,t) { var r="";
		switch (f) {
			case "TW": r=s.getSaver().externalizeTiddler(s,t); break;
			case "DIV": r=t.title+"\n"+s.getSaver().externalizeTiddler(s,t); break;
			case "XML": r=t.saveToRss(store.getTiddlerText("SiteUrl","")); break;
		}
		return convertUnicodeToUTF8(r);
	}

	var out=[]; var tids=[];
	// get selected tiddlers
	for (var i=0; i<list.options.length; i++) {
		var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
		var tid=store.getTiddler(opt.value); if (!tid) continue;
		tids.push(tid.title);
		out.push(getData(store,fmt,tid));
	}
	var count=out.length;
	// merge with existing tiddlers
	var text=loadFile(target);
	if (text && text.length) {
		var msg=target+"\nalready contains tiddler definitions.\n";
		msg+="\nPress OK to add new/revised tiddlers to current file contents.";
		msg+="\nPress Cancel to completely replace file contents";
		var remoteStore=new TiddlyWiki();
		if (remoteStore.importTiddlyWiki(text) && confirm(msg)) {
			var existing=remoteStore.getTiddlers("title");
			for (var i=0; i<existing.length; i++)
				if (!tids.contains(existing[i].title))
					out.push(getData(remoteStore,fmt,existing[i]));
			var msg="Merged %0 new/revised tiddlers and %1 existing tiddlers";
			displayMessage(msg.format([count,out.length-count]));
		}
	}
	return out;
}
//}}}

// // exportTiddlers(): output selected data to local file
//{{{
function exportTiddlers()
{
	clearMessage();
	var list  = document.getElementById("exportList"); if (!list) return;
	var fmt = document.getElementById("exportFormat").value;
	var target = document.getElementById("exportFilename").value.trim();
	if (!target.length) {
		displayMessage("A local target path/filename is required",target);
		return;
	}
	switch (fmt) {
		case "TW":	var head=exportTWHeader(); break;
		case "DIV":	var head=exportDIVHeader(); break;
		case "XML":	var head=exportXMLHeader(); break;
	}
	var theData=exportData(target,list,fmt);
	var c=theData.length;
	switch (fmt) {
		case "TW":	var foot=exportTWFooter(); break;
		case "DIV":	var foot=exportDIVFooter(); break;
		case "XML":	var foot=exportXMLFooter(); break;
	}
	var out=[]; var txt=out.concat(head,theData,foot).join("\n");
	var msg="An error occurred while saving to "+target;
	if (saveFile(target,txt)) msg=c+" tiddler"+((c!=1)?"s":"")+" written to "+target;
	displayMessage(msg,"file:///"+target);
}
//}}}

// // exportDeleteTiddlers(): delete selected tiddlers from file
//{{{
function exportDeleteTiddlers()
{
	var list=document.getElementById("exportList"); if (!list) return;
	var tids=[];
	for (i=0;i<list.length;i++)
		if (list.options[i].selected && list.options[i].value.length)
			tids.push(list.options[i].value);
	if (!confirm("Are you sure you want to delete these tiddlers:\n\n"+tids.join(', '))) return;
	store.suspendNotifications();
	for (t=0;t<tids.length;t++) {
		var tid=store.getTiddler(tids[t]); if (!tid) continue;
		if (tid.tags.contains("systemConfig"))
			if (!confirm("'"+tid.title+"' is tagged with 'systemConfig'.\n\nRemoving this tiddler may cause unexpected results.  Are you sure?"))
				continue;
		store.removeTiddler(tid.title);
		story.closeTiddler(tid.title);
	}
	store.resumeNotifications();
	alert(tids.length+" tiddlers deleted");
	refreshExportList(0); // reload listbox
	store.notifyAll(); // update page display
}
//}}}
+++(gtdProjectsSliderState)[Projekte]<<tiddler ProjectList>>===
+++(gtdActionsSliderState)[Tätigkeiten]<<list tagged context>>===
+++(gtdReviewSliderState)[Übersicht]
*[[Gesamt-Übersicht|Summary Review]]
*[[Projekt-Übersicht|Project Review]]
*[[Tätigkeiten-Übersicht|Action Review]]
*[[Erinnerungen|Reminders]]
===

<<newTiddler label:"Neues Projekt" prompt:"Neues Projekt erstellen" title:"NeuesProjekt" tag:"project" text:{{store.getTiddlerText('NewProjectTemplate')}} focus:title>> <<newTiddler label:"Neuer Kontext" prompt:"Neuen Kontext erstellen" title:"NeuerKontext" tag:"context" text:{{store.getTiddlerText('NewContextTemplate')}} focus:title">> <<newTiddler label:"Neue Tätigkeit" prompt:"Neue Tätigkeit erstellen" title:"NeueTaetigkeit" tag:"action" text:{{store.getTiddlerText('NewActionTemplate')}} focus:title>>
+++(gtdReferenceSliderState)[Referenzen]<<list tagged reference>>=== +++(gtdSomedaySliderState)[VielleichtIrgendwann]<<list tagged someday>>===

[[Konfiguration|Configuration Options]] [[Auf Updates prüfen|UpdateApplication]] [[Archive|Archives]]
/***
|''Name:''|GTDPlugins|
|''Description:''|Plugin to support Getting Things Done|
|''Version:''|<<gtdVersion>>|
|''Date:''|October 27, 2008|
|''Source:''|http://www.dcubed.ca/|
|''Author:''|Tom Otvos|
|''CoreVersion:''|2.4|
|''Browser:''|Firefox 1.5+; InternetExplorer 6.0+; Safari 3.1+|
***/

/***
''Macros:''
*{{{<<gtdAction "}}}//title//{{{" "}}}//context list//{{{">>}}}
*{{{<<gtdActionList {"}}}//context list//{{{" | "*" | "@" {"all" | "noproject" | "projectonly"} }>>}}}
** //if no parameters are specified, current context or project is used//
** //specify "*" for actions across all projects, "@" for incomplete actions across all contexts (or "all" for all actions)//
** //use "projectonly" or "noproject" to filter actions by project association//
*{{{<<list tagged "}}}//tag list//{{{" {any | all}>>}}}
** //if no parameters are specified, all tags are necessary//
*{{{<<gtdActionCompleted>>}}}
*{{{<<gtdToggleTag>>}}}
*{{{<<gtdToggleState>>}}}
*{{{<<importUpdates "}}}//url//{{{" {updates | all} "}}}//buttonTitle//{{{" "}}}//buttonHelp//{{{" "}}}//loadTiddlers params...//{{{">>}}}
*{{{<<gtdArchive { archive | unarchive | purge }>>}}}

''Commands:''
*{{{newAction}}}
*{{{newProjectAction}}}
*{{{changeContext}}}
*{{{deleteAction}}}
*{{{deleteContext}}}
*{{{deleteProject}}}
*{{{deleteProjectAll}}}
*{{{projectify}}}

''Wiki formatting:''
*{{{..new action title|context}}}

***/
//{{{

version.extensions.GTDPlugins = {major: 1, minor: 3, revision: 0, patch: 0 };

var _GTD = {

	lazyAutoSave: 0,
	contextCache: null,
	usingProjectTags: true,
	projectPriorities: [],

	initialize: function ()
	{
		var d = new Date();

		if (config.options.txtGTDReferenceContext == undefined) config.options.txtGTDReferenceContext = "reference";
		if (config.options.txtGTDSomedayContext == undefined) config.options.txtGTDSomedayContext = "someday";
		if (config.options.txtGTDUnfiledContext == undefined) config.options.txtGTDUnfiledContext = "unfiled";
		if (config.options.txtGTDActionAging == undefined) config.options.txtGTDActionAging = "";
		if (config.options.chkGTDFancyStyle == undefined) config.options.chkGTDFancyStyle = true;
		if (config.options.chkGTDLazyAutoSave == undefined) config.options.chkGTDLazyAutoSave = true;
		if (config.options.txtGTDLazyAutoSaveInterval == undefined) config.options.txtGTDLazyAutoSaveInterval = "60";
		if (config.options.txtGTDProjectPriorities == undefined) config.options.txtGTDProjectPriorities = "";
		
		// some tricks to work when our script is loaded from an external file...
		if (!store) config.notifyTiddlers.push( {name: "GTDStyleSheet", notify: refreshStyles} );
		if (!store && config.options.chkGTDFancyStyle) config.notifyTiddlers.push( {name: "GTDTWStyleSheet", notify: refreshStyles} );
		if (!store) config.notifyTiddlers.push( {name: null, notify: _GTD.refreshActionViews} );
		
		this.setReviewUpdate();
		this.setLazyAutoSave();
		
		if (config.options.txtGTDProjectPriorities.length == 0)
			this.projectPriorities = [ "important" ];
		else
			this.projectPriorities = config.options.txtGTDProjectPriorities.split(';');
		
		if (!store) return;
		
		if ((version.major == 2 && version.minor < 1) || !store.tiddlerExists("d3 settings")) {
			// we force a changed() call on all projects, contexts, and actions, to enable them to set up their cross-references
			var tiddlers = [];
			tiddlers = tiddlers.concat(store.getTaggedTiddlers("project"), store.getTaggedTiddlers("context"), store.getTaggedTiddlers("action"));
			for (var i = 0; i < tiddlers.length; i++)
				tiddlers[i].changed();
			
			// if we have tiddler meta data, rebuild it
			if (version.major > 2 || version.minor > 0)
				this.rebuildMetaData();
		}
		else {
			this.initializeFromMetaData();
			this.usingProjectTags = false;
		}
		
		//store.addNotification("GTDStyleSheet", refreshStyles);
		//if (config.options.chkGTDFancyStyle) store.addNotification("GTDTWStyleSheet", refreshStyles);
		store.addNotification(null, _GTD.refreshActionViews);
		
		// force a display of release notes, if required
		var v = version.extensions.GTDPlugins;
		var releaseNotesTiddler = "About version " + v.major + '.' + v.minor + '.' + v.revision;
		if ((config.options.chkGTDReleaseNotes || config.options.chkGTDReleaseNotes == undefined) && store.tiddlerExists(releaseNotesTiddler)) {
			params = "open:\"" + releaseNotesTiddler + "\"";
			params = params.parseParams("open",null,false);
			config.options.chkGTDReleaseNotes = false;
			saveOptionCookie("chkGTDReleaseNotes");
		}

		if (version.major > 2 || version.minor > 0)
			pluginInfo.log.push('Initialized in ' + ((new Date()).getTime() - d.getTime()) + ' milliseconds');
	},
	
	rebuildMetaData: function()
	{
		pluginInfo.log.push('Rebuilding action metadata...');

		store.suspendNotifications();
		var tiddlers = store.getTaggedTiddlers("action");
		for (var i = 0; i < tiddlers.length; i++) {
			var t = tiddlers[i];
			store.setValue(t, "gtd");
			store.setValue(t, "gtd.context", t.gtdContextName);
			if (t.gtdProject) store.setValue(t, "gtd.project", t.gtdProject.title);
			if (t.gtdProject) store.setValue(t, "gtd.projectindex", t.gtdProject.gtdActions.indexOf(t));
			// booo...scary...strip out project tag
			if (t.gtdProject) t.tags.remove(t.gtdProject.title);
		}
		store.resumeNotifications();
			
		var tiddler = store.createTiddler("d3 conversion");
		var s = "Completed document conversion. Do not delete this tiddler unless you want to rebuild the action metadata.\n\nThis tiddler also contains document-specific preferences which, if deleted, will revert to default settings.";
		tiddler.assign("d3 settings", s, config.options.txtUserName, new Date(), ["excludeLists"]);
	},
	
	initializeFromMetaData: function()
	{
		var tiddlers = store.getTaggedTiddlers("action");
		// ??? one possible optimization is to sort action list by project, to avoid repeatedly fetching project tiddler
		for (var i = 0; i < tiddlers.length; i++) {
			var t = tiddlers[i];
			t.gtdActionName = store.getValue(t, "title");
			t.gtdActionDone = this.tiddlerHasTag(t, "done");
			t.gtdProjectName = store.getValue(t, "gtd.project");
			t.gtdContextName = store.getValue(t, "gtd.context");
			if (t.gtdProjectName) {
				t.gtdProject = store.getTiddler(t.gtdProjectName);
				if (t.gtdProject) {
					if (t.gtdProject.gtdActions == undefined) t.gtdProject.gtdActions = [];
					t.gtdProject.gtdActions.push(t);
				}
			}
		}
		
		tiddlers = store.getTaggedTiddlers("project");
		for (i = 0; i < tiddlers.length; i++) {
			t = tiddlers[i];
			if (t.gtdActions) {
				t.gtdActions.sort( 
					function(a,b) { var ai = parseInt(store.getValue(a, "gtd.projectindex")), bi = parseInt(store.getValue(b, "gtd.projectindex")); return (ai < bi) ? -1 : +1; }
				);
			}
			else
				t.gtdActions = [];
			this.setNextAction(t);
		}
		
		tiddlers = this.getCachedContexts();
		for (i = 0; i < tiddlers.length; i++)
			tiddlers[i].gtdContextName = tiddlers[i].title;
	},
	
	tiddlerHasTag: function (tiddler, tag)
	{
		if (typeof(tiddler) == "string") tiddler = store.getTiddler(tiddler);
		return tiddler.isTagged(tag);
	},
	
	tiddlerSwapTag: function (tiddler, oldTag, newTag)
	{
		for (var i = 0; i < tiddler.tags.length; i++)
			if (tiddler.tags[i] == oldTag) {
				tiddler.tags[i] = newTag;
				return true;
			}
		return false;
	},
	
	setExtendedValue: function (tiddler, name, value)
	{
		// this bottleneck safely sets an extended data value, quietly ignoring the request
		// if the setValue function is not available AND it disables notifications during
		// the setValue if it is defined
		
		if (version.major > 2 || version.minor > 0) {
			store.suspendNotifications();
			store.setValue(tiddler, name, value);
			store.resumeNotifications();
		}
	},
	
	tiddlerHasChanged: function (tiddler, doSave)
	{
		tiddler.changed();
		//story.setDirty(tiddler.title, true);
		store.setDirty(true);
		if (this.tiddlerHasTag(tiddler, 'context'))
			this.clearContextCache();
		if (doSave == undefined) doSave = true;
		if (doSave) tiddler.modified = new Date();
		if (config.options.chkAutoSave && doSave)
			saveChanges();
		else if (doSave)
			this.lazyAutoSave++;
	},
	
	tiddlerAgeInDays: function(tiddler)
	{
		var now = new Date();
		return (now.getTime() - tiddler.modified.getTime()) / 1000 / 86400;
	},
	
	filteredTags: function (tags, specialTags, filterTags)
	{
		var resultTags = [];
		specialTags = specialTags.concat(filterTags);
		for (var i = 0; i < tags.length; i++)
			if (!specialTags.contains(tags[i])) resultTags.push(tags[i]);
		return resultTags;
	},
	
	filteredActionTags: function (tags, filterTags)
	{
		return this.filteredTags(tags, [ "action", "done", "floating", "action-archive" ], filterTags);
	},
	
	filteredProjectTags: function (tags, filterTags)
	{
		return this.filteredTags(tags, [ "project", "done", "important", "project-archive" ], filterTags);
	},
	
	qualifiedProjectName: function(p)
	{
		var tags = this.filteredProjectTags(p.tags, []);
		var q = '';
		for (var i = 0; i < tags.length; i++)
			q += tags[i] + '.';
		return q + p.title;
	},
	
	toggleTag: function (tiddler, tag, toggle)
	{
		var tagIndex = -1;
		for (var i = 0; i < tiddler.tags.length; i++)
			if (tiddler.tags[i] == tag) {
				tagIndex = i;
				break;
			}
		
		if (toggle && tagIndex == -1) {
			tiddler.tags.push(tag);
		}
		else if (!toggle && tagIndex != -1) {
			tiddler.tags.splice(tagIndex, 1);
		}
	},
	
	getTiddlerElement: function (tiddler)
	{
		return document.getElementById(story.idPrefix + tiddler.title);
	},
	
	refreshActionViews: function (tiddler)
	{
		if (tiddler) {
			if (typeof(tiddler) == "string") tiddler = store.getTiddler(tiddler);
			if (tiddler) {
				// first refresh the action tiddler
				story.refreshTiddler(tiddler.title, null, true);
				// do not do anything else if we are not an action!
				// no, we still want to do review updates below, so only do the next bit for actions
				// if (!_GTD.tiddlerHasTag(tiddler, "action")) return;
				if (_GTD.tiddlerHasTag(tiddler, "action")) {
					// now refresh all tiddlers that are tags of the action, which should be the context and project
					// no...now use explicit reference to project/context
					//for (var i = 0; i < tiddler.tags.length; i++)
						// ...of course, we don't refresh action-specific state tags
					//	if (tiddler.tags[i] != "action" && tiddler.tags[i] != "done" && tiddler.tags[i] != "floating") {
					//		story.refreshTiddler(tiddler.tags[i], null, true);
					//	}
					if (tiddler.gtdProjectName && tiddler.gtdProjectName.length > 0) story.refreshTiddler(tiddler.gtdProjectName, null, true);
					// because an action change can affect multiple contexts (via next actions), the only way we can ensure that everything
					// gets updated is to refresh all the displayed contexts...hopefully, there won't be many open and DOM lookups fairly snappy
					// if (tiddler.gtdContextName && tiddler.gtdContextName.length > 0) story.refreshTiddler(tiddler.gtdContextName, null, true);
					_GTD.refreshAllContexts();
				}
				else if (_GTD.tiddlerHasTag(tiddler, "context"))
					_GTD.clearContextCache();
			}
		}
	
		var specialTiddlers = store.getTaggedTiddlers("review");
		for (var i = 0; i < specialTiddlers.length; i++)
			if (_GTD.tiddlerHasTag(specialTiddlers[i], "gtd")) {		// only update GTD review tiddlers, as an optimization
				// as a further optimization, we don't refresh tiddlers that aren't actually displayed, and make sure that
				// if they are displayed, they are in view mode, not edit mode
				var el = _GTD.getTiddlerElement(specialTiddlers[i]);
				if (el && el.getAttribute("template") == "reviewViewTemplate")
					story.refreshTiddler(specialTiddlers[i].title, null, true);
			}

	},
	
	appendProjectActionMarkup: function(projectTiddler, actionTitle, actionContext)
	{
		var actionInsertionPoint = -1, actionLeadin = "";
		
		var reActionWikitext = "^\\.{2}([^|\\n]+)(?:\\|?)(.*).*$";
		var reActionMacro = "(.*)<<gtdAction ((?:[^>]|(?:>(?!>)))*)>>.*$";
		var actionRe = new RegExp("(" + reActionWikitext + ")|(" + reActionMacro + ")", "mg");
		do {
			var formatMatch = actionRe.exec(projectTiddler.text);
			if (formatMatch) {
				actionLeadin = (formatMatch[1] ? "" : formatMatch[5]);
				actionInsertionPoint = actionRe.lastIndex;
			}
		} while(formatMatch);
		
		var actionProto = "\n" + actionLeadin + "<<gtdAction \"" + actionTitle + "\" \"" + actionContext + "\">>";
		if (actionInsertionPoint == -1)
			projectTiddler.text += actionProto;
		else
			projectTiddler.text = projectTiddler.text.substring(0, actionInsertionPoint) + actionProto + projectTiddler.text.substr(actionInsertionPoint);
		
		this.tiddlerHasChanged(projectTiddler);
		this.refreshActionViews(projectTiddler);
	},
	
	removeProjectAction: function(projectTiddler, actionTitle)
	{
		var reActionWikitext = "^(\\.{2})[ \\t]*(" + actionTitle + ")[ \\t]*((\\|.*\\n?)|(.*\\n?))";
		var reActionMacro = "(.*<<gtdAction [\"\']?)(" + actionTitle + ")([\"\']?\\s+(?:[^>]|(?:>(?!>)))*>>.*\\n?)";
		projectTiddler.text = projectTiddler.text.replace(new RegExp(reActionWikitext, "mg"), "");
		projectTiddler.text = projectTiddler.text.replace(new RegExp(reActionMacro, "mg"), "");
		projectTiddler.changed();
		story.refreshTiddler(projectTiddler.title, null, true);
	},
	
	setNextAction: function(project)
	{
		if (project.gtdActions == undefined) project.gtdActions = [];
		project.gtdNextAction = null;
		for (var i = 0; i < project.gtdActions.length; i++)
			if (!project.gtdActions[i].gtdActionDone) {
				project.gtdNextAction = project.gtdActions[i];
				project.gtdProjectDone = false;
				this.toggleTag(project, "done", project.gtdProjectDone);
				return;
			}
		// if we get here, project is currently complete
		if (project.gtdActions.length > 0) project.gtdProjectDone = true;
		this.toggleTag(project, "done", project.gtdProjectDone);
	},
	
	clearContextCache: function()
	{
		this.contextCache = null;
	},
	
	getCachedContexts: function()
	{
		if (!this.contextCache) this.contextCache = store.getTaggedTiddlers("context");
		return this.contextCache;
	},
	
	renameCachedContext: function(oldName, newName)
	{
		if (this.contextCache) {
			var index = this.contextCache.indexOf(oldName);
			if (index > -1) this.contextCache[index] = newName;
		}
	},
	
	findActionContext: function(action)
	{
		var context = null;
		
		var contexts = this.getCachedContexts();
		for (var i = 0; i < contexts.length; i++)
			if (_GTD.tiddlerHasTag(action, contexts[i].title)) {
				context = contexts[i].title;
				break;
			}
		
		return context;
	},
	
	refreshAllContexts: function()
	{
		var contexts = this.getCachedContexts();
		for (var i = 0; i < contexts.length; i++)
			story.refreshTiddler(contexts[i].title, null, true);
	},
	
	saveWithForcedBackup: function()
	{
		var saveBackups = config.options.chkSaveBackups;
		config.options.chkSaveBackups = true;
		saveChanges();
		config.options.chkSaveBackups = saveBackups;
	},
	
	isNextAction: function(actionTiddler)
	{
		if (actionTiddler.gtdProject && actionTiddler == actionTiddler.gtdProject.gtdNextAction)
			return true;
		return !actionTiddler.gtdActionDone && this.tiddlerHasTag(actionTiddler, "floating");
	},
	
	setReviewUpdate: function()
	{
		window._GTD = this;
		// having a subminute review update is overkill, but it would be nice to have semi-accurate
		// clock, so we can't have it be longer than a minute between updates
		//window.setTimeout('window._GTD.doReviewUpdate()', 60 * 1000);
		var d = new Date();
		window.setTimeout('window._GTD.doReviewUpdate()', (3600 - 60*d.getMinutes() - d.getSeconds()) * 1000);
	},
	
	doReviewUpdate: function()
	{
		this.refreshActionViews(null);
		this.setReviewUpdate();
	},
	
	setLazyAutoSave: function()
	{
		window._GTD = this;
		var interval = parseInt(config.options.txtGTDLazyAutoSaveInterval, 10);
		interval = isNaN(interval) ? 60 : interval.clamp(0, Number.MAX_VALUE);
		window.setTimeout('window._GTD.doLazyAutoSave()', interval * 1000);
	},
	
	doLazyAutoSave: function()
	{
		if (config.options.chkGTDLazyAutoSave && !config.options.chkAutoSave && (this.lazyAutoSave > 0 || store.isDirty())) {
			this.lazyAutoSave = 0;
			displayMessage('Autosaving changes...');
			saveChanges();
			if (typeof(gtdAutoSaveHook) == "function")
				gtdAutoSaveHook();
			window.setTimeout('clearMessage()', 5 * 1000);
		}
		this.setLazyAutoSave();
	},
	
	projectPriority: function(p)
	{
		var maxPriority = _GTD.projectPriorities.length;
		for (var i = 0; i < maxPriority; i++)
			if (_GTD.tiddlerHasTag(p, _GTD.projectPriorities[i])) return (maxPriority - i);
		return 0;
	},
	
	actionSorter: function(a,b)
	{
		// we now have an extended sort function to try and provide a more useful list of actions, esp. in a context view
		// ... the rule now is that project actions appear before non-project actions
		// ... if two actions have projects, and either project is tagged "important", it will appear first, otherwise actions are alphabetical by project
		// ... if two actions are from the same project, they appear in project action sequence, not alphabetically
		// ... all non-project actions continue to be sorted alphabetically
		
		if (a.gtdProject && b.gtdProject) {
			var aImportance = _GTD.projectPriority(a.gtdProject), bImportance = _GTD.projectPriority(b.gtdProject);
			if (a.gtdProject == b.gtdProject)
				return (a.gtdProject.gtdActions.indexOf(a) < b.gtdProject.gtdActions.indexOf(b)) ? -1 : +1;
			else if (aImportance != bImportance)
				return (aImportance > bImportance) ? -1 : +1;
			else
				return (a.gtdProject.title < b.gtdProject.title) ? -1 : +1;
		}
		else if (a.gtdProject)
			return -1;	// "a" has a project, "b" doesn't, so "a" comes first
		else if (b.gtdProject)
			return +1;	// "b" has a project, "a" doesn't, so "b" comes first
		else {
			var aImportance = _GTD.tiddlerHasTag(a, "important"), bImportance = _GTD.tiddlerHasTag(b, "important");
			if (aImportance && !bImportance)
				return -1;	// "a" is important, "b" is not, so "a" comes first
			else if (bImportance && !aImportance)
				return +1;	// "b" is important, "a" is not, so "a" comes first
			else
				return (a.title < b.title) ? -1 : +1;
		}
	},
	
	projectSorter: function(a,b) 
	{
		
		var aImportance = _GTD.projectPriority(a), bImportance = _GTD.projectPriority(b);
		if (aImportance != bImportance)
			return (aImportance > bImportance) ? -1 : +1;
		else
			return (a.title < b.title) ? -1 : +1;
	}
};

config.macros.gtdVersion = {}
config.macros.gtdVersion.handler = function(place)
{
	var v = version.extensions.GTDPlugins;
	createTiddlyElement(place, "span", null, null, v.major + "." + v.minor + "." + v.revision + (v.patch ? "." + v.patch : "") + (v.beta ? " (beta " + v.beta + ")" : ""));
}

config.macros.list.tagged = {}
config.macros.list.tagged.innerHandler = function(tagList, allTags)
{
	var tiddlers = store.getTaggedTiddlers(tagList[0]);

	if (allTags) {
		var results = [];
		for (var i = 0; i < tiddlers.length; i++) {
			var tiddler = tiddlers[i], hasAllTags = true;
			for (var j = 1; hasAllTags && j < tagList.length; j++) {
				// hasAllTags &= _GTD.tiddlerHasTag(tiddler, tagList[j]);
				hasAllTags &= (tagList[j].charAt(0) == '-') ? !_GTD.tiddlerHasTag(tiddler, tagList[j].substr(1)) : _GTD.tiddlerHasTag(tiddler, tagList[j])
			}
			if (hasAllTags) results.push(tiddlers[i]);
		}
		return results;
	}
	else {
		for (var i = 1; i < tagList.length; i++) {
			var more = store.getTaggedTiddlers(tagList[i]);
			for (var j = 0; j < more.length; j++)
				tiddlers.pushUnique(more[j]);
		}
		return tiddlers;
	}
}
config.macros.list.tagged.handler = function(params) 
{
	var tags = params[1].readBracketedList();
	if (tags.length == 1) {
		if (config.options[tags[0]] == undefined)
			return store.getTaggedTiddlers(tags[0]);
		else
			return store.getTaggedTiddlers(config.options[tags[0]]);
	}
	else if (tags.length > 1) {
		var allTags = (params[2] == undefined || params[2] == 'all');
		var tiddlers = this.innerHandler(tags, allTags);
		tiddlers.sort(function (a,b) {if(a.title == b.title) return(0); else return (a.title < b.title) ? -1 : +1; });
		return tiddlers;
	}
}

config.macros.gtdActionList = {}
config.macros.gtdActionList.handler = function(place,macroName,params)
{
	var theList = createTiddlyElement(place, "ul", null, "gtdActionList");
	var parentTiddlerName = story.findContainingTiddler(place).getAttribute("tiddler");
	
	var allActions = (params[1] == "all");
	var noProjectActions = (params[1] == "noproject");
	var justProjectActions = (params[1] == "projectonly");
	var aging = parseInt(config.options.txtGTDActionAging, 10);
	aging = isNaN(aging) ? 0 : aging.clamp(0, Number.MAX_VALUE);
	
	if (params[0] == "*") {		// review actions for all projects
		var projects = store.getTaggedTiddlers("project");
		// do an importance sort on project list first, so they bubble to the top
		projects.sort(_GTD.projectSorter);
		for (var i = 0; i < projects.length; i++) {
			var project = projects[i];
			// filter projects that have been deferred
			if (_GTD.tiddlerHasTag(project, config.options.txtGTDSomedayContext)) continue;
			if (!allActions) {
				//var skipEmptyProject = true;
				//if (project.gtdActions != undefined && project.gtdActions.length > 0)
				//	for (var k = 0; skipEmptyProject && k < project.gtdActions.length; k++)
				//		skipEmptyProject = project.gtdActions[k].gtdActionDone;
				//if (skipEmptyProject) continue;
				if (project.gtdActions == undefined || project.gtdActions.length == 0 || project.gtdProjectDone) continue;
			}
			// this will present the actions in the same order as they appear in the project
			var theListItem = createTiddlyElement(theList, "li", null, "gtdActionListProject");
			createTiddlyLink(theListItem, project.title, true);
			if (project.gtdActions != undefined && project.gtdActions.length > 0) {
				var subList = createTiddlyElement(theList, "ul", null, "gtdActionList");
				for (var j = 0; j < project.gtdActions.length; j++) {
					var action = project.gtdActions[j];
					// if we are not displaying all actions, filter old completed actions (if specified)
					// if (!allActions && action.gtdActionDone && aging > 0 && _GTD.tiddlerAgeInDays(action) > aging) continue;
					// NEW! we are now filtering all completed actions unless we are displaying all actions
					if (!allActions && action.gtdActionDone) continue;
					var subListItem = createTiddlyElement(subList, "li");
					var el = config.macros.gtdAction.createActionElement(subListItem, action, project.title, action.tags);
				}
			}
		}
	}
	
	else if (params[0] == "@") {	// review actions for all contexts
		var contexts = _GTD.getCachedContexts();
		for (var i = 0; i < contexts.length; i++) {
			var context = contexts[i];
			var actions = config.macros.list.tagged.innerHandler([context.title, "action"], true);
			if (actions.length > 0) {
				var firstAction = true, theListItem, subList;
				actions.sort(_GTD.actionSorter);
				for (var j = 0; j < actions.length; j++) {
					var currentAction = actions[j];
					// special filtering by request...
					if (noProjectActions && currentAction.gtdProject) continue;
					if (justProjectActions && typeof(currentAction.gtdProject) == 'undefined') continue;
					// if we are not displaying all actions, filter completed actions and non-next project actions
					if (!allActions && (currentAction.gtdActionDone || (currentAction.gtdProject && !_GTD.isNextAction(currentAction)))) continue;
					// filter actions for projects that have been deferred
					if (currentAction.gtdProject && _GTD.tiddlerHasTag(currentAction.gtdProject, config.options.txtGTDSomedayContext)) continue;
					if (firstAction) {
						theListItem = createTiddlyElement(theList, "li", null, "gtdActionListContext");
						createTiddlyLink(theListItem, context.title, true);
						subList = createTiddlyElement(theList, "ul", null, "gtdActionList");
						firstAction = false;
					}
					var subListItem = createTiddlyElement(subList, "li");
					var el = config.macros.gtdAction.createActionElement(subListItem, currentAction, context.title, currentAction.tags);
				}
			}
		}
	}
	
	else {		// actions tagged by current tiddler name, or specified tag list as parameter
		var reviewMode = config.options['chkGTDActionListReviewMode' + escape(parentTiddlerName)];
		if (typeof(reviewMode) == 'undefined') reviewMode = false;
		
		// chain to our "tagged" list macro to get the tiddlers first
		var tags = (params.length == 0 || params[0] == "." ? [ parentTiddlerName ] : params[0].readBracketedList());
		tags.push("action");
		var results = config.macros.list.tagged.innerHandler(tags, true);
		results.sort(_GTD.actionSorter);
		for (var t = 0; t < results.length; t++) {
			var action = results[t];
			// special filtering by request...
			if (noProjectActions && action.gtdProject) continue;
			if (justProjectActions && typeof(action.gtdProject) == 'undefined') continue;
			if (action.gtdProject && _GTD.tiddlerHasTag(action.gtdProject, config.options.txtGTDSomedayContext)) continue;
			// if we are not displaying all actions, filter completed actions and non-next project actions
			if (reviewMode && !allActions && (action.gtdActionDone || (action.gtdProject && !_GTD.isNextAction(action)))) continue;
			// if we are not displaying all actions, filter old completed actions (if specified)
			if (!allActions && action.gtdActionDone && aging > 0 && _GTD.tiddlerAgeInDays(action) > aging) continue;
			var theListItem = createTiddlyElement(theList, "li");
			var el = config.macros.gtdAction.createActionElement(theListItem, action, parentTiddlerName, action.tags);
		}
	}
}

config.macros.gtdAction = {}
config.macros.gtdAction.createActionElement = function(place, actionTiddler, filterName, tags)
{
	if (typeof(actionTiddler) == "string") actionTiddler = store.getTiddler(actionTiddler);
	
	var actionElement = createTiddlyElement(place, "span", null, "gtdActionItem");
	
	// oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...
	var cb = document.createElement("input");
	cb.setAttribute("type", "checkbox");
	cb.setAttribute("actionTiddler", actionTiddler.title);
	cb.onclick = this.onClickDone;
	actionElement.appendChild(cb);
	cb.checked = actionTiddler.gtdActionDone;
	createTiddlyLink(actionElement, actionTiddler.title, true);
	actionElement.className = (actionTiddler.text ? "gtdActionWithContent" : "gtdActionWithoutContent");
	if (actionTiddler.gtdActionDone) actionElement.className += " gtdCompletedActionItem";
	if (_GTD.isNextAction(actionTiddler)) actionElement.className += " gtdNextActionItem";
	
	var filterTags = [], actionTags = [];
	if (actionTiddler.gtdProjectName && actionTiddler.gtdProjectName.length > 0)
		actionTags.push(actionTiddler.gtdProjectName);
	if (actionTiddler.gtdContextName && actionTiddler.gtdContextName.length > 0)
		actionTags.push(actionTiddler.gtdContextName);
	for (var i = 0; i < tags.length; i++) actionTags.pushUnique(tags[i]);
	if (filterName && filterName.length > 0) filterTags.pushUnique(filterName);
	
	actionTags = _GTD.filteredActionTags(actionTags, filterTags);
	if (actionTags.length > 0) {
		createTiddlyText(actionElement, " [ ");
		for (var i = 0; i < actionTags.length; i++) {
			if (i > 0) createTiddlyText(actionElement, ", ");
			createTiddlyLink(actionElement, actionTags[i], true, "actionCrossReference");
		}
		createTiddlyText(actionElement, " ]");
	}
	
	return actionElement;
}

config.macros.gtdAction.onClickDone = function(e)
{
	var tiddler = store.getTiddler(this.getAttribute("actionTiddler"));
	if (tiddler) {
		_GTD.toggleTag(tiddler, "done", this.checked);
		tiddler.gtdActionDone = this.checked;
		_GTD.tiddlerHasChanged(tiddler);
		_GTD.refreshActionViews(tiddler);
		if (this.checked && typeof(gtdActionDoneHook) == "function")
			gtdActionDoneHook(tiddler);
		if (tiddler.gtdActionDone && tiddler.gtdProject == undefined && confirm("This action is not a part of a project. Would you just like to delete it?")) {
			story.closeTiddler(tiddler.title, false, false);
			store.removeTiddler(tiddler.title);
		}
	}
	return true;
}

config.macros.gtdAction.handler = function(place,macroName,params)
{
	var title = params[0], tags;
	var parentTiddlerName = story.findContainingTiddler(place).getAttribute("tiddler");
	var tiddler = store.getTiddler(title);
	if (!tiddler) {
		// we should *never* get here now for project actions, but keep code in case project code
		// trips up, or we use this macro somewhere else
		this.createAction(title, parentTiddlerName, params[1]);
	}
	else
		// use actual tiddler tags, not macro param, in case context changed!
		tags = tiddler.tags;
	var action = this.createActionElement(place, title, parentTiddlerName, tags);
}

config.macros.gtdAction.createAction = function(title, projectTiddlerName, tagParams, extraTags)
{
	// var tags = ["action", parentTiddler];
	var action, tags = ["action"], fields = {};
	if (_GTD.usingProjectTags)
		tags.push(projectTiddlerName);
	if (typeof(tagParams) == "string") tags = tags.concat(tagParams.readBracketedList());
	if (typeof(extraTags) == "string") tags = tags.concat(extraTags.readBracketedList());
	var templateText = store.getTiddlerText("NewActionTemplate", config.views.wikified.defaultText.format([title]));
	if (_GTD.usingProjectTags)
		action = store.saveTiddler(title, title, templateText, config.options.txtUserName, new Date(), tags);
	else {
		fields["gtd.project"] = projectTiddlerName;
		action = store.saveTiddler(title, title, templateText, config.options.txtUserName, new Date(), tags, fields);
	}
	return action;
}

config.macros.gtdActionCompleted = {}
config.macros.gtdActionCompleted.handler = function(place,macroName,params)
{
	if (!readOnly) {
		var title = story.findContainingTiddler(place).getAttribute("tiddler");
		var tiddler = store.getTiddler(title);
		// oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...
		var cb = document.createElement("input");
		cb.setAttribute("type", "checkbox");
		cb.setAttribute("actionTiddler", title);
		cb.onclick = this.onClickDone;
		place.appendChild(cb);
		cb.checked = tiddler.gtdActionDone;
	}
}

config.macros.gtdActionCompleted.onClickDone = function(e)
{
	var tiddler = store.getTiddler(this.getAttribute("actionTiddler"));
	if (tiddler) {
		_GTD.toggleTag(tiddler, "done", this.checked);
		tiddler.gtdActionDone = this.checked;
		_GTD.tiddlerHasChanged(tiddler);
		_GTD.refreshActionViews(tiddler);
		if (this.checked && typeof(gtdActionDoneHook) == "function")
			gtdActionDoneHook(tiddler);
		if (tiddler.gtdActionDone && tiddler.gtdProject == undefined && confirm("This action is not a part of a project. Would you just like to delete it?")) {
			story.closeTiddler(tiddler.title, false, false);
			store.removeTiddler(tiddler.title);
		}
	}
	return true;
}

config.macros.gtdToggleTag = {}
config.macros.gtdToggleTag.handler = function(place,macroName,params)
{
	if (!readOnly) {
		var title = story.findContainingTiddler(place).getAttribute("tiddler");
		var tiddler = store.getTiddler(title);
		// oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...
		var cb = document.createElement("input");
		cb.setAttribute("type", "checkbox");
		cb.setAttribute("tiddler", title);
		cb.setAttribute("toggledTag", params[0]);
		cb.onclick = this.onClickDone;
		place.appendChild(cb);
		cb.checked = _GTD.tiddlerHasTag(tiddler, params[0]);
	}
}

config.macros.gtdToggleTag.onClickDone = function(e)
{
	var tiddler = store.getTiddler(this.getAttribute("tiddler"));
	if (tiddler) {
		_GTD.toggleTag(tiddler, this.getAttribute("toggledTag"), this.checked);
		_GTD.tiddlerHasChanged(tiddler);
		if (_GTD.tiddlerHasTag(tiddler, "action"))
			_GTD.refreshActionViews(tiddler);
		else
			// we need a broad notification here, not just refreshActionViews
			store.notify(tiddler.title, true);
	}
	return true;
}

config.macros.gtdToggleState = {}
config.macros.gtdToggleState.handler = function(place,macroName,params)
{
	var title = story.findContainingTiddler(place).getAttribute("tiddler");
	var tiddler = store.getTiddler(title);
	// oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...
	var cb = document.createElement("input");
	cb.setAttribute("type", "checkbox");
	cb.setAttribute("tiddler", title);
	var state = params[0] + escape(title);
	cb.setAttribute("stateName", state);
	cb.onclick = this.onClickDone;
	place.appendChild(cb);
	cb.checked = config.options[state];
}

config.macros.gtdToggleState.onClickDone = function(e)
{
	var tiddler = store.getTiddler(this.getAttribute("tiddler"));
	if (tiddler) {
		var state = this.getAttribute("stateName");
		config.options[state] = this.checked;
		saveOptionCookie(state);
		story.refreshTiddler(tiddler.title, null, true);
	}
	return true;
}

config.macros.importUpdates = { 
	importMode: "updates",
	buttonTitle: "Update", 
	buttonHelp: "Click here to update the application",
	missingHelperMessage: "This functionality depends on the LoadTiddlersPlugin, which is missing. Please import the plugin from TiddlyTools.",
	preUpdateMessage: "Once the download is finished, you will need to reload your document to complete the update. In order to allow you to review the update tiddlers, this will not be done automatically. \n\nClick \"OK\" start the update.",
	postUpdateMessage: "Please remember, you will need to save and reload your document to complete the update. In order to allow you to review the update tiddlers, this will not be done automatically."
}
config.macros.importUpdates.handler = function(place, macroName, params)
{
	var mode = params[1] ? params[1] : this.importMode;
	var title = params[2] ? params[2] : this.buttonTitle;
	var prompt = params[3] ? params[3] : this.buttonHelp;
	var button = createTiddlyButton(place, title, prompt, this.onClickUpdate);
	button.setAttribute("updateSource", params[0]);
	button.setAttribute("importMode", mode);
	if (params.length > 4) button.setAttribute("importExtras", params.slice(4).join(" "));
}

config.macros.importUpdates.onClickUpdate = function(e)
{
	if (config.macros.loadTiddlers == undefined || version.extensions.LoadTiddlersPlugin == undefined) {
		alert(config.macros.importUpdates.missingHelperMessage);
		return;
	}
	if (!confirm(config.macros.importUpdates.preUpdateMessage))
		return;
	var importParams = [ this.getAttribute("importMode"), this.getAttribute("updateSource") ];
	var importExtras = this.getAttribute("importExtras");
	if (importExtras) importParams = importParams.concat(importExtras.split(" "));
	// force a saveChanges with backup before the update
	_GTD.saveWithForcedBackup();
	// chain to the loadTiddlers macro
	config.macros.loadTiddlers.handler(this, "loadTiddlers", importParams);
	// ensure that relevant release notes are displayed on first launch
	config.options.chkGTDReleaseNotes = true;
	saveOptionCookie("chkGTDReleaseNotes");
	// do *not* cause a browser navigation
	return false;
}

config.macros.gtdArchive = {}
config.macros.gtdArchive.handler = function(place, macroName, params)
{
	var archiveAction = params.length > 0 ? params[0] : "archive"
	var btn = createTiddlyButton(place, archiveAction, "", this.onClick);
	btn.setAttribute("archiveAction", archiveAction);
}

config.macros.gtdArchive.onClick = function(e)
{
	var warning = "Are you sure you want to %0 all %1 projects and actions?";
	var status = "There were %0 project(s) and %1 action(s) %2d.";
	var archiveAction = this.getAttribute("archiveAction");
	
	var projectCount = 0, actionCount = 0;
	
	if (archiveAction == "archive") {
		if (confirm(warning.format([archiveAction, "completed"]))) {
			clearMessage();
			var projects = store.getTaggedTiddlers("project");
			for (var i = 0; i < projects.length; i++) {
				var project = projects[i];
				if (project.gtdActions == undefined || project.gtdActions.length == 0) continue;
				var projectComplete = true;
				for (var j = 0; projectComplete && j < project.gtdActions.length; j++)
					projectComplete = project.gtdActions[j].gtdActionDone;
				if (!projectComplete) continue;
				// if we get here, all project actions are done, so archive project
				story.closeTiddler(project.title, false, false);
				_GTD.tiddlerSwapTag(project, "project", "project-archive");
				_GTD.tiddlerHasChanged(project, false);
				projectCount++;
				for (j = 0; j < project.gtdActions.length; j++) {
					story.closeTiddler(project.gtdActions[j].title, false, false);
					_GTD.tiddlerSwapTag(project.gtdActions[j], "action", "action-archive");
					_GTD.tiddlerHasChanged(project.gtdActions[j], false);
					actionCount++;
				}
			}
			var actions = store.getTaggedTiddlers("action");
			for (i = 0; i < actions.length; i++) {
				var action = actions[i];
				if (action.gtdActionDone && !action.gtdProject) {
					story.closeTiddler(action.title, false, false);
					_GTD.tiddlerSwapTag(action, "action", "action-archive");
					_GTD.tiddlerHasChanged(action, false);
					actionCount++;
				}
			}
			displayMessage(status.format([projectCount, actionCount, archiveAction]));
			var saveClearMessage = clearMessage;
			clearMessage = function() {};
			if (config.options.chkAutoSave) saveChanges();
			clearMessage = saveClearMessage;
			store.notify(null, true);
		}
	}
	
	else if (archiveAction == "unarchive") {
		if (confirm(warning.format([archiveAction, "archived"]))) {
			clearMessage();
			var projects = store.getTaggedTiddlers("project-archive");
			for (var i = 0; i < projects.length; i++) {
				var project = projects[i];
				story.closeTiddler(project.title, false, false);
				_GTD.tiddlerSwapTag(project, "project-archive", "project");
				_GTD.tiddlerHasChanged(project, false);
				projectCount++;
			}
			var actions = store.getTaggedTiddlers("action-archive");
			for (i = 0; i < actions.length; i++) {
				var action = actions[i];
				story.closeTiddler(action.title, false, false);
				_GTD.tiddlerSwapTag(action, "action-archive", "action");
				_GTD.tiddlerHasChanged(action, false);
				actionCount++;
			}
			displayMessage(status.format([projectCount, actionCount, archiveAction]));
			var saveClearMessage = clearMessage;
			clearMessage = function() {};
			if (config.options.chkAutoSave) saveChanges();
			clearMessage = saveClearMessage;
			store.notify(null, true);
		}
	}
	
	else if (archiveAction == "purge") {
		if (confirm(warning.format([archiveAction, "archived"]))) {
			clearMessage();
			_GTD.saveWithForcedBackup();
			var projects = store.getTaggedTiddlers("project-archive");
			for (var i = 0; i < projects.length; i++) {
				var project = projects[i];
				story.closeTiddler(project.title, false, false);
				store.removeTiddler(project.title);
				projectCount++;
			}
			var actions = store.getTaggedTiddlers("action-archive");
			for (i = 0; i < actions.length; i++) {
				var action = actions[i];
				story.closeTiddler(action.title, false, false);
				store.removeTiddler(action.title);
				actionCount++;
			}
			displayMessage(status.format([projectCount, actionCount, archiveAction]));
			var saveClearMessage = clearMessage;
			clearMessage = function() {};
			if (config.options.chkAutoSave) saveChanges();
			clearMessage = saveClearMessage;
			store.notify(null, true);
		}
	}
	else
		alert("That archiving action is not supported");
}

config.formatters.push(
	{
	name: "gtdAction",
	match: "^\\.{2}.*",
	lookahead: "^\\.{2}([^|]*)(?:\\|?)(.*)",
	handler: function(w)
		{
			var lookaheadRegExp = new RegExp(this.lookahead,"g");
			var lookaheadMatch = lookaheadRegExp.exec(w.matchText)
			if (lookaheadMatch) {
				var params = [ lookaheadMatch[1].trim() ];
				if (lookaheadMatch[2].trim().length > 0) params.push(lookaheadMatch[2].trim());
				config.macros.gtdAction.handler(w.output, "gtdAction", params);
			}
		}
	}
);

config.commands.newAction = { text: "action", tooltip: "Create a new action for this context", hideReadOnly: true };
config.commands.newAction.handler = function(event, src, context)
{
	var d = new Date();
	var newActionTitle = d.formatString("New Action hh:0mm:0ss");
	if (!store.tiddlerExists(newActionTitle)) {
		var tiddler = store.createTiddler(newActionTitle);
		var templateText = store.getTiddlerText("NewActionTemplate", config.views.wikified.defaultText.format([newActionTitle]));
		tiddler.assign(newActionTitle, templateText, config.options.txtUserName, new Date(), [ "action", context ]);
		
		story.displayTiddler(null, newActionTitle, DEFAULT_EDIT_TEMPLATE);
		story.focusTiddler(newActionTitle, "title");
	}
	return false;
}

config.commands.newProjectAction = { text: "action", tooltip: "Create a new action for this project", hideReadOnly: true };
config.commands.newProjectAction.handler = function(event, src, project)
{
	var d = new Date();
	var newActionTitle = d.formatString("New Action hh:0mm:0ss");
	if (!store.tiddlerExists(newActionTitle)) {
		var defaultContext = config.options.txtGTDUnfiledContext;
		_GTD.appendProjectActionMarkup(store.getTiddler(project), newActionTitle, defaultContext);
		
		var tiddler = store.createTiddler(newActionTitle);
		var templateText = store.getTiddlerText("NewActionTemplate", config.views.wikified.defaultText.format([newActionTitle]));
		var tags = ["action"], fields = {};
		if (_GTD.usingProjectTags)
			tags.push(project);
		tags.push(defaultContext);
		if (_GTD.usingProjectTags)
			tiddler.assign(newActionTitle, templateText, config.options.txtUserName, new Date(), tags);
		else {
			fields["gtd.project"] = project;
			tiddler.assign(newActionTitle, templateText, config.options.txtUserName, new Date(), tags, new Date(), fields);
		}
		
		story.displayTiddler(null, newActionTitle, DEFAULT_EDIT_TEMPLATE);
		story.focusTiddler(newActionTitle, "title");
	}
	return false;
}

config.commands.changeContext = { text: "context", tooltip: "Change context of this action", hideReadOnly: true, popupNone: "There are no contexts" };
config.commands.changeContext.handler = function(event,src,title)
{
	var popup = Popup.create(src);
	if (popup) {
		var contexts = _GTD.getCachedContexts();
		var tiddler = store.getTiddler(title);
		var currentContext = _GTD.findActionContext(tiddler);
		if (!currentContext) currentContext = '';
		
		var c = false;
		for (var i = 0; i < contexts.length; i++)
			if (contexts[i].title != currentContext) {
				var button = createTiddlyButton(createTiddlyElement(popup, "li"), contexts[i].title, '', this.onClickContext);
				button.setAttribute("actionTiddler", title);
				button.setAttribute("oldContext", currentContext);
				button.setAttribute("newContext", contexts[i].title);
				c = true;
			}
			
		if (!c)
			createTiddlyText(createTiddlyElement(popup, "li", null, "disabled"), this.popupNone);
	}
	
	Popup.show(popup, false);
	event.cancelBubble = true;
	if (event.stopPropagation) event.stopPropagation();
	// do *not* cause a browser navigation
	return false;
}

config.commands.changeContext.onClickContext = function(e)
{
	var tiddler = store.getTiddler(this.getAttribute("actionTiddler"));
	if (tiddler) {
		var contextChanged = false;
		var oldContext = this.getAttribute("oldContext");
		var newContext = this.getAttribute("newContext");
		if (oldContext.length == 0)
			contextChanged = (tiddler.tags.push(newContext) > 0);
		else
			contextChanged = _GTD.tiddlerSwapTag(tiddler, oldContext, newContext);
		
		if (contextChanged) {
			tiddler.gtdContextName = newContext;
			_GTD.setExtendedValue(tiddler, "gtd.context", newContext);
			_GTD.tiddlerHasChanged(tiddler);
			_GTD.refreshActionViews(tiddler);
			// be sure to refresh old context as well...
			story.refreshTiddler(oldContext, null, true);
		}
	}
	// do *not* cause a browser navigation
	return false;
}

config.commands.changeProject = { text: "project", tooltip: "Change project of this action", hideReadOnly: true, popupNone: "There are no projects" };
config.commands.changeProject.handler = function(event,src,title)
{
	var popup = Popup.create(src);
	if (popup) {
		var projects = store.getTaggedTiddlers("project");
		var tiddler = store.getTiddler(title);
		var currentProject = (tiddler.gtdProject ? tiddler.gtdProject.title : '');
		
		var c = false;
		for (var i = 0; i < projects.length; i++)
			if (projects[i].title != currentProject) {
				var button = createTiddlyButton(createTiddlyElement(popup, "li"), projects[i].title, '', this.onClickProject);
				button.setAttribute("actionTiddler", title);
				button.setAttribute("oldProject", currentProject);
				button.setAttribute("newProject", projects[i].title);
				c = true;
			}
			
		if (!c)
			createTiddlyText(createTiddlyElement(popup, "li", null, "disabled"), this.popupNone);
	}
	
	Popup.show(popup, false);
	event.cancelBubble = true;
	if (event.stopPropagation) event.stopPropagation();
	// do *not* cause a browser navigation
	return false;
}

config.commands.changeProject.onClickProject = function(e)
{
	var tiddler = store.getTiddler(this.getAttribute("actionTiddler"));
	if (tiddler) {
		var oldProject = this.getAttribute("oldProject");
		var newProject = this.getAttribute("newProject");
		
		if (oldProject.length > 0)
			_GTD.removeProjectAction(tiddler.gtdProject, tiddler.title)
		if (_GTD.usingProjectTags)
			_GTD.tiddlerSwapTag(tiddler, oldProject, newProject);
		else
			_GTD.setExtendedValue(tiddler, "gtd.project", newProject);
		_GTD.appendProjectActionMarkup(store.getTiddler(newProject), tiddler.title, tiddler.gtdContextName);
		
		_GTD.tiddlerHasChanged(tiddler);
		_GTD.refreshActionViews(tiddler);
	}
	// do *not* cause a browser navigation
	return false;
}

config.commands.deleteAction = { text: "delete", tooltip: "Delete this action", hideReadOnly: true, warning: "Are you sure you want to delete '%0'?", altwarning: "Are you sure you want to delete '%0'? The action will also be removed from project '%1'." };
config.commands.deleteAction.handler = function(event, src, title)
{
	var tiddler = store.getTiddler(title);
	var ok = (tiddler.gtdProject ? confirm(this.altwarning.format([title, tiddler.gtdProject.title])) : confirm(this.warning.format([title])));
	if (ok) {
		if (tiddler.gtdProject) _GTD.removeProjectAction(tiddler.gtdProject, title);
		store.removeTiddler(title);
		story.closeTiddler(title,true,event.shiftKey || event.altKey);
		if (config.options.chkAutoSave)
			saveChanges();
	}
	
	return false;
}

config.commands.deleteContext = { text: "delete", tooltip: "Delete this context", hideReadOnly: true, warning: "Are you sure you want to delete '%0'? All associated actions will be tagged as 'unfiled'." };
config.commands.deleteContext.handler = function(event, src, title)
{
	if (confirm(this.warning.format([title]))) {
		store.suspendNotifications();
		this.unlinkActions(title);
		// force a rebuild of our context cache
		_GTD.clearContextCache();
		store.resumeNotifications();
		store.removeTiddler(title);
		story.closeTiddler(title,true,event.shiftKey || event.altKey);
		if (config.options.chkAutoSave)
			saveChanges();
	}
	
	return false;
}

config.commands.deleteContext.unlinkActions = function(contextTitle)
{
	var tiddlers = config.macros.list.tagged.innerHandler([contextTitle, "action"], true);
	for (var i = 0; i < tiddlers.length; i++) {
		var tiddler = tiddlers[i];
		_GTD.tiddlerSwapTag(tiddler, contextTitle, config.options.txtGTDUnfiledContext);
		_GTD.tiddlerHasChanged(tiddler, false);
		// context removal will do view notification...
	}
}

config.commands.archiveProject = { text: "archive", tooltip: "Archive this project", hideReadOnly: true, warning: "Are you sure you want to archive '%0'?", noarchive: "This project is %0 and will not be archived." };
config.commands.archiveProject.handler = function(event, src, title)
{
	if (confirm(this.warning.format([title]))) {
		var project = store.getTiddler(title);
		if (project.gtdActions == undefined || project.gtdActions.length == 0) {
			alert(this.noarchive.format(["empty"]));
			return;
		}
		var projectComplete = true;
		for (var j = 0; projectComplete && j < project.gtdActions.length; j++)
			projectComplete = project.gtdActions[j].gtdActionDone;
		if (!projectComplete) {
			alert(this.noarchive.format(["incomplete"]));
			return;
		}
		// if we get here, all project actions are done, so archive project
		story.closeTiddler(project.title, false, false);
		_GTD.tiddlerSwapTag(project, "project", "project-archive");
		_GTD.tiddlerHasChanged(project, false);
		for (j = 0; j < project.gtdActions.length; j++) {
			story.closeTiddler(project.gtdActions[j].title, false, false);
			_GTD.tiddlerSwapTag(project.gtdActions[j], "action", "action-archive");
			_GTD.tiddlerHasChanged(project.gtdActions[j], false);
		}
		store.notify(null, true);
		if (config.options.chkAutoSave)
			saveChanges();
	}

	return false;
}

config.commands.deleteProject = { text: "delete", tooltip: "Delete this project", hideReadOnly: true, warning: "Are you sure you want to delete '%0'? All associated actions will no longer be bound to this (or any) project." };
config.commands.deleteProject.handler = function(event, src, title)
{
	if (confirm(this.warning.format([title]))) {
		store.suspendNotifications();
		this.unlinkActions(title);
		store.resumeNotifications();
		store.removeTiddler(title);
		story.closeTiddler(title,true,event.shiftKey || event.altKey);
		if (config.options.chkAutoSave)
			saveChanges();
	}
	
	return false;
}

config.commands.deleteProject.unlinkActions = function(projectTitle)
{
	// var tiddlers = config.macros.list.tagged.innerHandler([projectTitle, "action"], true);
	var project = store.getTiddler(projectTitle);
	for (var i = 0; i < project.gtdActions.length; i++) {
		var tiddler = project.gtdActions[i];
		tiddler.gtdProject = null;
		tiddler.gtdProjectName = null;
		if (_GTD.usingProjectTags)
			tiddler.tags.splice(tiddler.tags.indexOf(projectTitle), 1);
		else {
			_GTD.setExtendedValue(tiddler, "gtd.project", null);
			_GTD.setExtendedValue(tiddler, "gtd.projectindex", null);
		}
		_GTD.tiddlerHasChanged(tiddler, false);
		// project removal will do view notification...
	}
}

config.commands.deleteProjectAll = { text: "delete all", tooltip: "Delete this project and its actions", hideReadOnly: true, warning: "Are you sure you want to delete '%0' and all its associated actions?" };
config.commands.deleteProjectAll.handler = function(event, src, title)
{
	if (confirm(this.warning.format([title]))) {
		store.suspendNotifications();
		this.deleteActions(title);
		store.resumeNotifications();
		store.removeTiddler(title);
		story.closeTiddler(title,true,event.shiftKey || event.altKey);
		if (config.options.chkAutoSave)
			saveChanges();
	}
	
	return false;
}

config.commands.deleteProjectAll.deleteActions = function(projectTitle)
{
	// var tiddlers = config.macros.list.tagged.innerHandler([projectTitle, "action"], true);
	var project = store.getTiddler(projectTitle);
	for (var i = 0; i < project.gtdActions.length; i++) {
		var tiddler = project.gtdActions[i].title;
		store.removeTiddler(tiddler);
		story.closeTiddler(tiddler, true, false);
		// project removal will do view notification...
	}
}

config.commands.projectify = { text: "projectify", tooltip: "Convert this action to a project", hideReadOnly: true, warning: "Are you sure you want to convert '%0' to a project?" };
config.commands.projectify.handler = function(event, src, title)
{
	if (confirm(this.warning.format([title]))) {
		var tiddler = store.getTiddler(title);
		if (tiddler.gtdProject) _GTD.removeProjectAction(tiddler.gtdProject, title);
		tiddler.tags = [ "project" ];
		_GTD.tiddlerHasChanged(tiddler, true);
		// we need a broad notification here, not just refreshActionViews
		store.notify(title, true);
	}
	
	return false;
}

// *** ***/
// *** These are overrides to core TiddlyWiki functionality ***
// *** ***/

Tiddler.prototype._GTDInheritedChanged = Tiddler.prototype.changed;
Tiddler.prototype.changed = function()
{
	this._GTDInheritedChanged();
	
	// Note that this is called both as part of normal tiddler changes AND as a part
	// of the initial TW loading process from DIVs...
	
	if (_GTD.tiddlerHasTag(this, "project")) {
		// (re)build the in-memory ordered action list
		this.gtdActions = [];
		this.gtdNextAction = null;
		if (this.text) {
			var reActionWikitext = "^\\.{2}([^|\\n]+)(?:\\|?)(.*)";
			var reActionMacro = "<<gtdAction ((?:[^>]|(?:>(?!>)))*)>>";
			var actionRe = new RegExp("(" + reActionWikitext + ")|(" + reActionMacro + ")", "mg");
			do {
				var formatMatch = actionRe.exec(this.text);
				if (formatMatch) {
					var macroParams = (formatMatch[1] ? null : formatMatch[5].readMacroParams());
					// note that for the ".." notation, we are trimming up action titles and contexts
					var actionTiddlerName = (formatMatch[1] ? formatMatch[2].trim() : macroParams[0]);
					var actionTiddler = store.getTiddler(actionTiddlerName);
					if (!actionTiddler) {
						var actionTags = (formatMatch[1] ? formatMatch[3].trim() : macroParams[1]);
						var extraTags = (formatMatch[1] ? '' : macroParams[2]);
						actionTiddler = config.macros.gtdAction.createAction(actionTiddlerName, this.title, actionTags, extraTags);
					}
					if (actionTiddler) {
						actionTiddler.gtdProject = this;
						if (this.gtdNextAction == null && !_GTD.tiddlerHasTag(actionTiddler, "done"))
							this.gtdNextAction = actionTiddler;
						this.gtdActions.push(actionTiddler);
						_GTD.setExtendedValue(actionTiddler, "gtd.projectindex", this.gtdActions.length - 1);
						// handle project renaming in action
						if (actionTiddler.gtdProjectName && actionTiddler.gtdProjectName != this.title) {
							if (_GTD.usingProjectTags)
								_GTD.tiddlerSwapTag(actionTiddler, actionTiddler.gtdProjectName, this.title);
							else
								_GTD.setExtendedValue(actionTiddler, "gtd.project", this.title);
							// action view won't get updated through any other refresh mechanism, so
							story.refreshTiddler(actionTiddler.title, null, true);
						}
						actionTiddler.gtdProjectName = this.title;
					}
				}
			} while(formatMatch);
		}
	}
	
	else if (_GTD.tiddlerHasTag(this, "context")) {
		if (this.gtdContextName == undefined)
			this.gtdContextName = this.title;
		else if (this.gtdContextName != this.title) {
			// propagate renamed context to affected actions
			store.suspendNotifications();
			var results = config.macros.list.tagged.innerHandler([ this.gtdContextName, "action"], true);
			for (var t = 0; t < results.length; t++) {
				_GTD.tiddlerSwapTag(results[t], this.gtdContextName, this.title);
				results[t].gtdContextName = this.title;
				_GTD.setExtendedValue(results[t], "gtd.context", this.title);
				// action view won't get updated through any other refresh mechanism, so
				//story.refreshTiddler(results[t].title, null, true);
			}
			// because the store is not yet updated, we need to manipulate the context cache directly
			_GTD.renameCachedContext(this.gtdContextName, this.title);
			this.gtdContextName = this.title;
			// we need a broad notification here, not just refreshActionViews
			store.resumeNotifications();
			store.notify(null, true);
		}
	}
	
	else if (_GTD.tiddlerHasTag(this, "action")) {
		if (this.gtdActionName == undefined)
			this.gtdActionName = this.title;
		else if (this.gtdActionName != this.title && this.gtdProject) {
			// ugh...dig into related project and update the wiki code to use new action name
			var reActionWikitext = "^(\\.{2}[ \\t]*)(" + this.gtdActionName + ")(([ \\t]*\\|.*\\n?)|(\\n?))";
			var reActionMacro = "(<<gtdAction [\"\']?)(" + this.gtdActionName + ")([\"\']?\\s+(?:[^>]|(?:>(?!>)))*>>)";
			this.gtdProject.text = this.gtdProject.text.replace(new RegExp(reActionWikitext, "mg"), "$1" + this.title + "$3");
			this.gtdProject.text = this.gtdProject.text.replace(new RegExp(reActionMacro, "mg"), "$1" + this.title + "$3");
			this.gtdActionName = this.title;
		}
		this.gtdActionDone = _GTD.tiddlerHasTag(this, "done");
		this.gtdContextName = _GTD.findActionContext(this);
		_GTD.setExtendedValue(this, "gtd.context", this.gtdContextName);
		// reset the next action on the associated project
		if (this.gtdProject) _GTD.setNextAction(this.gtdProject);
	}
}

Story.prototype.chooseTemplateForTiddler = function(title,template)
{
	// This override to core TW functionality is used to provide tag-based view and edit templates. The
	// basic idea is that the tiddler is scanned for its tags and, depending on whether we are opening a
	// tiddler in "view" or "edit" mode, a corresponding 'tag + "ViewTemplate"' or 'tag + "EditTemplate"'
	// tiddler is searched for. If it exists, it is used instead of the default templates.
	
	if (!template)
		template = DEFAULT_VIEW_TEMPLATE;

	// before reverting to default behaviour, check to see if a tag-based template exists
	if (template == DEFAULT_VIEW_TEMPLATE || template == DEFAULT_EDIT_TEMPLATE) {
		if (this.tagBasedTemplateCache == undefined) this.tagBasedTemplateCache = new Array();
		var templateRoot = (template == DEFAULT_VIEW_TEMPLATE ? "ViewTemplate" : "EditTemplate");
		var tiddler = store.getTiddler(title);
		if (tiddler) {
			for (var i = 0; i < tiddler.tags.length; i++) {
				var tag = tiddler.tags[i];
				var tagTemplate = tag + templateRoot;
				var tagCacheId = tag + template;
				// first check our cache to see if we have seen this template before
				if (this.tagBasedTemplateCache[tagCacheId] != undefined) {
					// make sure template still exists
					if (store.tiddlerExists(this.tagBasedTemplateCache[tagCacheId])) {
						template = this.tagBasedTemplateCache[tagCacheId];
						break;
					}
					else
						delete this.tagBasedTemplateCache[tagCacheId];
				}
				// go to the store to see if template exists
				if (store.tiddlerExists(tagTemplate)) {
					template = tagTemplate;
					this.tagBasedTemplateCache[tagCacheId] = tagTemplate;
					break;
				}
			}
		}
	}
	
	if (template == DEFAULT_VIEW_TEMPLATE || template == DEFAULT_EDIT_TEMPLATE)
		template = config.tiddlerTemplates[template];
	return template;
}

// Clint Checketts' IE first-child patch, version 1.1, http://www.checkettsweb.com/tw/gtd_tiddlywiki.htm#GiveFirstTiddlerClassPatch

Story.prototype.closeTiddlerIEFirstChild = Story.prototype.closeTiddler;
Story.prototype.closeTiddler = function(title,animate,slowly) {
	var tiddler = document.getElementById(this.idPrefix + title);
	// we need to test to ensure tiddler is actually open
	if (tiddler) {
		var storyArea = tiddler.parentNode;
		if ((this.idPrefix + title) == storyArea.firstChild.id){
			removeClass(storyArea.firstChild,"IEFirstChild");
			// this next line is redundant, since it is looked after at the end of this function
			// if (storyArea.firstChild.nextSibling) addClass(storyArea.firstChild.nextSibling,"IEFirstChild");
		}
		story.closeTiddlerIEFirstChild(title,animate,slowly);
		if (storyArea.firstChild) addClass(storyArea.firstChild,"IEFirstChild");
	}
}

Story.prototype.displayTiddlerIEFirstChild = Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle,animationSrc) {
	var storyArea = document.getElementById(this.container);
	if (storyArea.firstChild) removeClass(storyArea.firstChild,"IEFirstChild");
	story.displayTiddlerIEFirstChild(srcElement,tiddler,template,animate,unused,customFields,toggle,animationSrc);
	addClass(storyArea.firstChild,"IEFirstChild");
}

_GTD.initialize();

//}}}
/***
!GTD specific styles
***/

/*{{{*/
/* how annoying is that big header anyway?! */
.headerForeground, .headerShadow {
 padding-top: 1em;
}

/* the tagging popup really gets in the way so push it off to the side */
.tagging { float: right; }

/* this unbullets actions in the actionList macro */
ul.gtdActionList { list-style-type: none; }
li.gtdActionListProject, li.gtdActionListContext { margin-top: 1.0em; }

.gtdCompletedActionItem { text-decoration: line-through; }
.gtdNextActionItem { border-bottom: 1px solid red; }
.gtdActionWithContent a { font-weight: bold; }
.gtdActionWithoutContent a { font-weight: normal; }

a.actionCrossReference { color: #228B22; }
a.actionCrossReference:hover { color: white; }

/* necessary bits copied from enhanced stylesheet to render properly without it */
#mainMenu {
 font-size: 1em;
 text-align: left;
 width: 12em;
}

#mainMenu * {
 font-size: 1em;
 font-weight: normal;
 padding: 0; margin: 0; border: 0;
}

#mainMenu ul {
 list-style: none;
 margin-bottom: 10px;
}

#mainMenu li {
 text-indent: 1em;
}

#mainMenu li li {
 text-indent: 1.5em;
}

#mainMenu li li li {
 text-indent: 2em;
}

#mainMenu li li li li {
 text-indent: 2.5em;
}

#mainMenu a.button, #mainMenu a.tiddlyLink, #mainMenu a.externalLink {
 display: block; margin: 0;
}

table.review { width: 98%; }
.review tr { vertical-align: top; }

/*}}}*/

/***
!Imported 3x5 printing styles
//adapted from the work of Clint Checketts, http://www.checkettsweb.com/tw/gtd_tiddlywiki.htm //
***/

/*{{{*/

@media print {
#mainMenu, #sidebar, #messageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em 1em;}


/* LAYOUT ELEMENTS ========================================================== */
*
{
 margin: 0;
 padding: 0;
}

#contentWrapper
{
 margin: 0;
 width: 100%;
 position: static;
}

body {
 background: #fff;
 color: #000;
 font-size: 6.2pt;
 font-family: "Lucida Grande", "Bitstream Vera Sans", Helvetica, Verdana, Arial, sans-serif;
 /* we don't want any unnecessary output */
 border: none;
}

img {
 max-width: 2.2in;
 max-height: 4.3in;
}

#header, #side_container, #storeArea, #copyright, #floater, #messageArea, .save_accesskey, .site_description, #saveTest, .toolbar, .header, .footer, .tagging, .tagged
{
 display: none;
}

#tiddlerDisplay, #displayArea
{
 display: inline;
}

.tiddler {
 margin: 0 0 2em 0;
 border: none;
 page-break-before: always;
 font-size: 200%;
 /* IF YOU DO NOT USE INDEX CARDS, USE THIS */
 font-size: 100%;
}

.tiddler:first-child {
 page-break-before: avoid;
}

/* this relies on Clint's IE first-child patch */
.IEFirstChild {
 page-break-before: auto;
}

.title {
 font-size: 1.6em;
 font-weight: bold;
 margin-bottom: .3em;
 padding: .2em 0;
 border-bottom: 1px dotted #000;
}

p, blockquote, ul, li, ol, dt, dd, dl, table
{
 margin: 0 0 .3em 0;
}

h1, h2, h3, h4, h5, h6
{
 margin: .2em 0;
} 

h1
{
 font-size: 1.5em;
}

h2
{
 font-size: 1.3em;
}

h3
{
 font-size: 1.25em;
}

h4
{
 font-size: 1.15em;
}

h5
{
 font-size: 1.1em;
}

blockquote
{
 margin: .6em;
 padding-left: .6em;
 border-left: 1px solid #ccc;
}

ul
{
 list-style-type: circle;
}

li
{
 margin: .1em 0 .1em 2em;
 line-height: 1.4em; 
}

table
{
 border-collapse: collapse;
 font-size: 1em;
}

td, th
{
 border: 1px solid #999;
 padding: .2em;
}

hr {
 border: none;
 border-top: dotted 1px #777;
 height: 1px;
 color: #777;
 margin: .6em 0;
}
}
/*}}}*/

/***
!Imported styles for calendar plugin
***/

/*{{{*/

#mainMenu .calendar {
 width: 100%;
 background-color: transparent !important;
}

#mainMenu .calendar, #mainMenu .calendar tr, #mainMenu .calendar td, #mainMenu .calendar a {
}


/*}}}*/
/***
!Layout Rules /%==============================================%/
***/
/*{{{*/

body {
 /* this is required for proper layout on IE, for some reason... */
 _position: static;
}

.tagClear {
 /* this, too, is a necessary IE hack... */
 _margin-top: 10em; 
 _clear: both;
}

.headerForeground, .headerShadow {
 padding-top: 1em;
}

.tiddler {
 margin: 0 0 0.9em 0;
 padding-bottom: 1em;
}

#mainMenu {
 width: 16em;
 font-size: 1em;
 text-align: left;
 padding-top: 0.5em;
}

#mainMenu * {
 font-size: 1em;
 font-weight: normal;
 padding: 0; margin: 0; border: 0;
}

#mainMenu ul {
 list-style: none;
 margin-bottom: 10px;
}

#mainMenu li {
 text-indent: 1em;
}

#mainMenu a.button, #mainMenu a.tiddlyLink, #mainMenu a.externalLink {
 display: block; margin: 0;
}

#displayArea {
 margin-left: 19em; margin-top: 0;
}

.toolbar .button {
 margin-left: 4px;
}

/*}}}*/

/***
!Generic Rules /%==============================================%/
***/
/*{{{*/
body {
 background: #464646;
 color: #000;
}

h1,h2,h3,h4,h5 {
 color: #000;
 background: #eee;
}

/*}}}*/
/***
!Header /%==================================================%/
***/
/*{{{*/
.header {
 background: #000;
}

.headerForeground {
 color: #cf6;
}

.headerForeground a {
 font-weight: normal;
 color: #cf6;
}

/* ??? what is up when you specify a site title colour in IE ??? */
/* .siteTitle { color: red; } */

/*}}}*/
/***
!General tabs /%=================================================%/
***/
/*{{{*/

.tabSelected {
 color: #fff;
 background: #960;
 border: none;
}

.tabUnselected {
 color: #fff;
 background: #660;
}

.tabContents {
 color: #004;
 background: #960;
 border: none;
}

.tabContents .button, .tabContents a {
 border: none;
 color: #fff;
}

.tabContents a:hover, .tabset a:hover {
 background: #000;
}

/* make nested tab areas look different */
.tabContents .tabSelected, .tabContents .tabContents {
 background: #700;
 color: #fff;
}

.tabContents .tabContents {
 color: #eeb;
}

/*}}}*/
/***
!Main Menu /%=================================================%/
***/
/*{{{*/
#mainMenu {
 background: #700;
 color: #fff;
 border-right: 3px solid #500;
}

#mainMenu * {
 color: #fff;
}

#mainMenu a.button, #mainMenu a.tiddlyLink, #mainMenu a.externalLink {
 border: none;
 border-bottom: 1px solid #500;
 border-top: 1px solid #900;
}

#mainMenu a:hover,
#mainMenu a.button:hover {
 background-color: #b00;
 color: #fff;
}

/*}}}*/
/***
!Sidebar options /%=================================================%/
~TiddlyLinks and buttons are treated identically in the sidebar and slider panel
***/
/*{{{*/
#sidebar {
 color: #000;
 background: #eeb;
 border-right: 3px solid #bb8;
 border-bottom: 3px solid #520;
}

#sidebarOptions .sliderPanel {
 background: #fff;
}

#sidebarOptions .sliderPanel a {
 border: none;
 color: #700;
}

#sidebarOptions .sliderPanel a:hover {
 color: #fff;
 background: #700;
}

#sidebarOptions .sliderPanel a:active {
 color: #700;
 background: #fff;
}

#sidebarOptions a {
 color: #700;
 border: none;
}

#sidebarOptions a:hover, #sidebarOptions a:active {
 color: #fff;
 background: #700;
}

/*}}}*/
/***
!Message Area /%=================================================%/
***/
/*{{{*/
#messageArea {
 border-right: 3px solid #da1;
 border-bottom: 3px solid #a80;
 background: #ffe72f;
 color: #014;
}

/*}}}*/
/***
!Popup /%=================================================%/
***/
/*{{{*/
.popup {
 background: #cf6;
 border: none;
}

.popup hr {
 color: #000;
}

.popup li.disabled {
 color: #666;
 background: #cf6;
}

.popup li a, .popup li a:visited {
 color: #000;
 border: 1px outset #cf6;
 background: #cf6;
}

.popup li a:hover {
 color: #000;
 border: 1px outset #cf6;
 background: #ef9;
}
/*}}}*/
/***
!Tiddler Display /%=================================================%/
***/
/*{{{*/
.tiddler {
 background: #fff;
 border-right: 3px solid #aaa;
 border-bottom: 3px solid #555;
}

.title {
 color: #900;
}

.selected .toolbar a {
 color: #000;
}

.toolbar .button {
 background: #eeb /*#cf6*/;
 border: 1px outset #eeb /*#cf6*/;
}

.selected .toolbar .button:hover {
 background: #700 /*#ef9*/;
 color: #fff;
}

#mainMenu .calendar { border: 1px solid white; }
#mainMenu .calendar, #mainMenu .calendar tr, #mainMenu .calendar td, #mainMenu .calendar a {
}

/*}}}*/

/***
!Additional print overrides for fancy style /%==============================================%/
***/
/*{{{*/

@media print {

.tiddler {
 /* get rid of our fancy tiddler outline */
 border: none;
}

}
/*}}}*/
|!Vorname|!Nachname|!Geburtstag|!Geburtsjahr|!Bemerkung|h
|~Anna-Karina|~Hölzle-Stäble|08.12.|?|-|
|Ulf|Bäcker|19.02.|1953|-|

<<reminder month:12 day:8 leadtime:100 title:"Geburtstag A.-K. Hölzle" >>
<<reminder month:2 day:19 leadtime:10 title:"Geburtstag Ulf B." >>
!!Projects, contexts, actions, and tiddlers
Before getting into the meat of how to use this system, it is important to clearly understand the relationship between projects, contexts, and actions, and how they relate to tiddlers. Throughout this discussion, it is assumed that the basic TW and GTD terminology is already understood. If you are new to TW, then please start [[here|TiddlyWiki]].

At the lowest level, we have ''actions'', which are simply " physical things to do". In this implementation, actions are first-class tiddlers, tagged as {{{action}}}. This is both good and bad. On the plus side, it makes action management very easy since we can use the full complement of tiddler-based functionality inside of TW and related plug-ins, and it allows you to save as much or as little extra information with the action as you like. On the minus side, it means that actions must have reasonably descriptive titles to avoid tiddler collision, because tiddler names inside a TW document must be unique: for example, you cannot have two projects with a "Kill Bill" action in the system. Also, without frequent archiving of completed actions, performance may be affected adversely as the system builds up action tiddlers.

''Contexts'' are groups of related actions all intended to be doable in a particular location or, well, context. Contexts are also tiddlers, tagged as {{{context}}}, and for the most part the content of a context tiddler will simply be a dynamically generated list of actions that need to be done. An action should have precisely one context in GTD, although presently this implementation does not enforce that in any way since actions related to a context are simply tagged to the context.

''Projects'' are groups of two or more actions which, when they are all completed, produce some desired outcome. Projects are tiddlers, tagged as {{{project}}}. The main distinguishing feature between a list of actions for a project and a list of actions for a context is that the project actions are ''ordered'', and at any point in time, there will only be a single ''next action''.

Note that in this implementation, there is //no special naming// requirement for actions, contexts, and projects -- just tag them appropriately. By convention, you probably want to name your contexts "@computer", "@homedepot", etc., but you are not required to do so. Also, since project actions are directly tagged by the project name, you probably don't want to have super long project names -- it works, but doesn't look as nice when looking at tiddler and tag lists.

!!Interface
If we now focus our attention on the MainMenu at left, you will see that it starts with two important menu items in which you will probably spend a lot of your time: Projects and Actions. These are //dynamically// populated lists that show active projects and action contexts, respectively. Both menu items use a slider interface to show/hide the lists, and they simply list all tiddlers that are tagged as {{{project}}} or {{{context}}}. Selecting an individual project or action context will, of course, then open the appropriate tiddler with its action list and other content. Note that these menu items are truly dynamic: updates to projects and contexts will immediately be reflected in these menus.

Next in the menu are the equally important "review" tiddlers: [[Project Review]], [[Action Review]], [[Reminders]], and [[Summary Review]]. The [[Project Review]] is a quick summary of all projects and their current and completed actions. Similarly, the [[Action Review]] shows all //incomplete// actions by context, and highlighting the "next action" per project appropriately. And the [[Reminders]] is a single page for viewing important reminders including: overdue (incomplete) actions, actions for today and tomorrow, and all action and non-action items that are coming up in the next week. Finally, the [[Summary Review]] is an at-a-glance summary of the previously mentioned reviews.

The "Create new project" and "Create new context" menu items allow you to easily create new projects and context tiddlers, tagged correctly. They rely on "template" tiddlers to provide their default content: [[NewProjectTemplate]] and [[NewContextTemplate]]. You can edit those tiddlers to change the way a new project or context looks if you don't like the default.

For completeness, the main menu also includes tiddlers for [[Reference]] and [[Someday-Maybe]] items. Both these tiddlers display lists of tiddlers tagged with certain keywords (that you can change using the [[Configuration Options]]). Of the two, the [[Reference]] tiddler it probably the least useful since you could consider the whole wiki a reference system and anything that is not a project, context, or action should be fair game as reference material. But it does illustrate how to create custom tiddlers with simple tag-based selection of items.

The Calendar menu item uses the popular TW [[CalendarPlugin]] to show a calendar, create date-based tiddlers and, in conjunction with the [[ReminderMacros]], show dates that have reminders on them. And the [[Configuration|Configuration Options]] menu item allows you to set a number of operational parameters in the system. [[Check for Updates|UpdateApplication]] enables you to always stay current with the core code that makes up this system (including ~TiddlyWiki itself). And finally [[Archives]] enables you to manage the archiving of completed projects and actions. 

!!Getting things done
So, how do we really "get things done"? At a minimum, create one or more contexts by clicking on "Create new context", giving it an appropriate name, and saving it. Then, while viewing a context, click on the ''action'' menu item in the context's tiddler menu. This creates a new action for that context. Name it, possibly add a description, save it and, bingo, it shows up in the context action list. Later, when you finish the action, check it off either from the context's action list, or using the checkbox next to the action title when you are viewing the action tiddler. That's it.

Working with project action lists is only slightly more involved since we want to describe the order in which actions are to be done a project. First, create a new project by clicking on "Create new project". Then, while ''editing'' the project tiddler, add the actions directly to the project using one of two wiki-text syntaxes:
{{{
<<gtdAction "action title" "action context">>
}}}
or
{{{
..action title|action context
}}}

Saving the project will create new action tiddlers if they don't already exist and present a nice action list for you that you can then work from. Of course, any new actions will also be cross-posted to the appropriate context action lists and, if you happen to have the context list open, you would see the change immediately. It probably goes without saying, but if you want to change the order of actions or add new actions, simply edit the project and move things around as you see fit. Also, once the actions are created, you can always edit the action directly to add more information, rename it, or change its context (more on that later).

//The major benefit to ensuring that project action list ordering is respected (by explicitly listing the actions) is that "next action" processing becomes automatic. You do ''not'' need to tag an action as "next" to make it next. It is next simply because all the other actions before it are done.// In all action lists, the "next action" is displayed (by the default StyleSheet) with a @@color(red):__red underline__@@. Note that starting with version 1.0.9, d-cubed supports the concept of "floating" actions, which are simply actions that do not have to be strictly next in the list to show up in the various action lists. While not strictly true to the GTD gospel, this is a popular feature in real-world use. To mark an action as floating, simply add the word "floating" after the action context in the {{{gtdAction}}} macro (you currently cannot use floating actions with the ".." notation).

When entering project actions, the ".." notation is faster and easier to type but the catch is that the ".." must be the first characters on a line. This means you cannot use it in conjuction with other wiki notation, like "*" or "#". Ordinarily, this is not a problem because the actions will get rendered in a nice list but if you wanted to do your own list to, for example, use numbering or provide indentation for subproject actions, then you will need to use the {{{gtdAction}}} macro instead. The sample projects show examples of each.

Now since you already know that actions are just tiddlers tagged with project and context, you might be tempted to create an action using the "new tiddler" command. This will, in fact, work if you want to create an action for a context without a project. But as you can probably guess, it will not work for a project action because the action must be listed in the project tiddler for the system to correctly maintain the ordering of actions. So it is probably best to get in the habit of not ever using "new tiddler" to create actions at all.

!!More useful stuff
When viewing actions, two additional menu items appear in the action's tiddler menu: ''context'' and ''projectify''. Clicking on ''context'' will allow you to select an alternate context for that action, which is useful if you have, for example, an @waiting context and an action has been partially done but you are now waiting for something or someone. Of course, changing the context on an action will immediately be reflected in all other tiddlers that are displaying that action. Note, however, that in project tiddlers where actions are explicitly listed out, the context in the wiki-text (the ".." or {{{gtdAction}}} macro) are not updated. This context can be considered //initial context// for the action when it is first created. While that may be confusing when you are editing a project, rest assured knowing that the system it correctly tracking the action context.

The ''projectify'' command in an action's tiddler menu will convert an existing action to a new project. This is very useful when you are refactoring your action list and decide that an action needs to be split into multiple steps.

In working with projects, contexts, and actions, you may occasionally want to rename or delete things. This, generally, works as you would expect. If you want to rename a project, context, or action, just edit the appropriate tiddler and the change will propagate throughout the system. Note, in particular, that if you rename an action that is part of a project, the underlying wiki text in the project tiddler will be updated with the new name!

To delete projects or contexts, simply select "delete" from the tiddler menu when editing the project or context. In the case of contexts, associated actions in the context will be marked with a special "unfiled" context. You should review actions tagged with "unfiled" and assign them to new contexts appropriately. In the case of projects, associated actions will be "unfiled" so that they will only be associated with their current context. The project tiddler menu has an additional "delete all" command that allows for a "deep" delete of a project. If you select this, the project //and all associated actions// will be deleted.

Deleting action tiddlers just works. If the action is associated with a project, the project tiddler will be modified automatically and the action entry will be removed.

!!TW customizations
In addition to the macros and wiki-syntax modifiers defined in GTDPlugins and the other external plug-ins, the GTDPlugins make a couple of key customizations to the way TW behaves to make for a more usable GTD system. While you don't need to //know// this to use the system, it might be of interest to more experienced TW users.

First, we define an override to the way tiddlers are displayed to allow "tag-based templates". What this means, simply, is that when a tiddler is opened for viewing or editing, the tags of the tiddler are enumerated and, if a corresponding tiddler -- tag + "ViewTemplate" or tag + "EditTemplate" -- is found, it is used as a layout for the tiddler. In this implementation, the [[contextViewTemplate]] is used to add an additional "action" menu item when viewing (not editing) a context tiddler. This template and the [[projectViewTemplate]] also remove the "tagging" div because it is completely redundant to the main context and project content. Other templates provide additional commands where appropriate.

Second, because the MainMenu utilizes macros that create dynamic content, we need to do an important customization to the PageTemplate: the MainMenu DIV element needs to always update when tiddlers get saved, by adding a {{{force='true'}}} attribute on the element. This way, new projects and contexts show up in the menu immediately, as opposed to requiring the wiki to be reloaded. This is important to know if you are integrating this application into an existing TW document, since the PageTemplate tiddler is not a part of the application updates in order to preserve any other PageTemplate customizations you may already have in place (such as changing the header colour scheme).

And third, we override the {{{changed}}} method of the {{{Tiddler}}} class to enable us to hook into tiddler saving...in particular, //project// tiddler saving...to allow the project action lists to be accurately maintained. This hook is also used to detect and process action and context renaming.

There are probably a few other tricks buried in the system, but we can't reveal //everything//!
Wenn ich irgendwann mal Zeit habe, will ich meinen Hof neu pflastern.

Was ich dazu brauche und in die Wege leiten muss (Schotter kaufen, osteuropäischen Bauarbeiter engagieren, etc.), schreibe ich in ein Projekt, wenns soweit ist.

/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.3|
|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||
|Options|##Configuration|
|Description|macro for automated updates or one-click installations of tiddlers from remote sources|
!!!!!Documentation
>see [[LoadTiddlersPluginInfo]]
!!!!!Configuration
<<<
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2008.10.27 [3.6.3] in doImport(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
|please see [[LoadTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.LoadTiddlersPlugin= {major: 3, minor: 6, revision: 3, date: new Date(2008,10,27)};

config.macros.loadTiddlers = {
	label: "",
	tip: "add/update tiddlers from '%0'",
	lockedTag: "noReload",	// if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
	askMsg: "Please enter a local path/filename or a remote URL",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	nochangeMsg: "'%0' is up-to-date... skipped.",
	lockedMsg: "'%0' is tagged '%1'... skipped.",
	skippedMsg: "skipped (cancelled by user)",
	loadedMsg: "Loaded %0 of %1 tiddlers from %2",
	reportTitle: "ImportedTiddlers",
	warning: "Warning!!  Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	handler: function(place,macroName,params) {
		var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
		var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
		var filter="updates";
		if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
			|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
			filter=params.shift();
		var src=params.shift(); if (!src || !src.length) return; // filename is required
		var quiet=(params[0]=="quiet"); if (quiet) params.shift();
		var ask=(params[0]=="confirm"); if (ask) params.shift();
		var force=(params[0]=="force"); if (force) params.shift();
		var init=(params[0]=="init"); if (init) params.shift();
		var noreport=(params[0]=="noreport"); if (noreport) params.shift();
		this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as "autotags"
		if (label.trim().length) {
			// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
			createTiddlyButton(place,label.format([src.replace(/%20/g," ")]),tip.format([src.replace(/%20/g," ")]), function() {
				if (src=="ask") src=prompt(this.askMsg);
				config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
			})
		}
		else {
			// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
			if (src=="ask") src=prompt(this.askMsg);
			config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
		}
	},
	loadFile: function(src,callback,params) {
		var quiet=params.quiet;
		if (src==undefined || !src.length) return null; // filename is required
		if (!quiet) clearMessage();
		if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
		if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
			var txt=loadFile(src);
			if (!txt) { // file didn't load, might be relative path.. try fixup
				var pathPrefix=document.location.href;  // get current document path and trim off filename
				var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
				if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
				src=pathPrefix+src;
				if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
				var txt=loadFile(src);
			}
			if (!txt) { // file still didn't load, report error
				if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g," "),"(unknown)"]));
			} else {
				if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g," ")]));
				if (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
			}
		} else {
			var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
			var x=doHttp("GET",src,null,null,name,pass,callback,params,null);
		}
	},
	readTiddlersFromHTML: function(html) {
		// for TW2.2+
		if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
			var remoteStore=new TiddlyWiki();
			remoteStore.importTiddlyWiki(html);
			return remoteStore.getTiddlers("title");	
		}
	},
	doImport: function(status,params,html,src,xhr) {
		var quiet=params.quiet;
		var ask=params.ask;
		var filter=params.filter;
		var force=params.force;
		var init=params.init;
		var noreport=params.noreport;
		var tiddlers = config.macros.loadTiddlers.readTiddlersFromHTML(html);
		var count=tiddlers?tiddlers.length:0;
		var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
		if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src.replace(/%20/g," ")]));
		store.suspendNotifications();
		var count=0;
		if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
			var inbound = tiddlers[t];
			var theExisting = store.getTiddler(inbound.title);
			if (inbound.title==config.macros.loadTiddlers.reportTitle)
				continue; // skip "ImportedTiddlers" history from the other document...
			if (theExisting && theExisting.tags.contains(config.macros.loadTiddlers.lockedTag)) {
				if (!quiet) displayMessage(config.macros.loadTiddlers.lockedMsg.format([theExisting.title,config.macros.loadTiddlers.lockedTag]));
				continue; // skip existing tiddler if tagged with 'noReload'
			}
			// apply the all/new/changes/updates filter (if any)
			if (filter && filter!="all") {
				if ((filter=="new") && theExisting) // skip existing tiddlers
					continue;
				if ((filter=="changes") && !theExisting) // skip new tiddlers
					continue;
				if ((filter.substr(0,4)=="tag:") && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
					continue;
				if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name
					continue;
				if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0)) {
					var msg=config.macros.loadTiddlers.nochangeMsg;
					if (!quiet&&msg.length) displayMessage(msg.format([inbound.title]));
					continue;
				}
			}
			// get confirmation if required
			if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\nfrom "+src.replace(/%20/g," ")+"\n\nOK to proceed?"))
				{ tiddlers[t].status=config.macros.loadTiddlers.skippedMsg; continue; }
			// DO IT!
			var tags=new Array().concat(inbound.tags,config.macros.loadTiddlers.newTags);
	                store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, tags, inbound.fields, true, inbound.created);
	                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value - needed for TW2.1.3 or earlier
			tiddlers[t].status=theExisting?"updated":"added"
			if (init && tags.contains("systemConfig") && !tags.contains("systemConfigDisable")) {
				var ok=true;
				if (ask||!quiet) ok=confirm(config.macros.loadTiddlers.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound); tiddlers[t].status+=" (plugin initialized)"; }
					catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
				}
			}
			count++;
		}
		store.resumeNotifications();
		if (count) {
			// refresh display
			store.setDirty(true); store.notifyAll();
			// generate a report
			if (!noreport) config.macros.loadTiddlers.report(src,tiddlers,count,quiet);
		}
		// always show final message when tiddlers were actually loaded
		if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g," ")]));
	},
	report: function(src,tiddlers,count,quiet) {
		// format the new report content
		var newText = "On "+(new Date()).toLocaleString()+", ";
		newText += config.options.txtUserName+" loaded "+count+" tiddlers ";
		newText += "from\n[["+src+"|"+src+"]]:\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++)
			if (tiddlers[t].status)
				newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// get current report (if any)
		var title=config.macros.loadTiddlers.reportTitle;
		var currText="";
		var theReport = store.getTiddler(title);
		if (theReport) currText=((theReport.text!="")?'\n----\n':"")+theReport.text;
		// update the ImportedTiddlers content and show the tiddler
		store.saveTiddler(title, title, newText+currText, config.options.txtUserName, new Date(), theReport?theReport.tags:null, theReport?theReport.fields:null);
		if (!quiet) { story.displayTiddler(null,title,1,null,null,false); story.refreshTiddler(title,1,true); }
	}
}
//}}}
/***
|Name|LoadTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.3|
|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|documentation|
|Requires||
|Overrides||
|Description|documentation for LoadTiddlersPlugin|
!!!!!Usage
<<<
Syntax:
{{{<<loadTiddlers label:text prompt:text filter source quiet confirm force init noreport tag tag tag...>>}}}

Example:
{{{<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>}}}
<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>

Where:
''"""label:text"""'' and ''"""prompt:text"""''
>defines link text and tooltip (prompt) that can be clicked to trigger the load tiddler processing.  If a label is NOT provided, then no link is created and the loadTiddlers function is performed whenever the containing tiddler is rendered.
''filter'' (optional) determines which tiddlers will be automatically selected for importing.  Use one of the following keywords:
>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler
>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)
>''""""tiddler:TiddlerName""""'' retrieves only the specific tiddler named in the parameter.
>''""""tag:text""""'' retrieves only the tiddlers tagged with the indicated text.
>> Note: ''if an existing tiddler is tagged with 'noReload', then it will not be overwritten'', even if the inbound tiddler has been selected by the filtering process.  This allows you to make local changes to imported tiddlers while ensuring that those changes won't be lost due to automatic tiddler updates retrieved from the import source document.
''source'' (required) is the location of the imported document.  It can be either a local document path/filename in whatever format your system requires, or a remote web location (starting with "http://" or "https://")
>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked
''"quiet"'' (optional)
>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc).  Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified.  This ensures that changes to your document cannot occur without any visible indication at all.
''"confirm"'' (optional)
>adds interactive confirmation.  A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.
''"init"'' (optional)
>invoke tiddlers tagged with <<tag systemConfig>> as plugins as soon as they are imported, without requiring a save-and-reload action first.  For safety, a browser message box (OK/Cancel) is displayed for each imported plugin, so that you can manually bypass any plugins that you do not want to invoke.  Note, however, that those tiddlers are still //imported// into your document and therefore will still take effect the next time you save-and-reload the document.
''"force"'' (optional)
>import all matching tiddlers, even if unchanged
''"noreport"'' (optional)
>suppress generation of [[ImportedTiddlers]] report
''"tag tag tag..."'' (optional)
>any remaining parameters are used as tag values to be added to each imported tiddler (i.e., "tag-on-import")
<<<
!!!!!Configuration
<<<
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2008.10.27 [3.6.3] in doImport(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
2008.08.05 [3.6.2] rewrote loadFile() to eliminate use of platform-specific fileExists() test
2008.08.03 [3.6.1] in handler(), changed variable 'prompt' to 'tip' to avoid conflict with prompt() function
2008.01.07 [3.6.0] added 'init' option to automatically invoke plugin tiddlers as soon as they are loaded (without needing save/reload)
2008.01.03 [3.5.0] in loadFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.27 [3.4.8] added missing 'fields' params to saveTiddler() call. Fixes problem where importing tiddlers would lose the custom fields.
2007.06.25 [3.4.7] add calls to store.suspendNotifications() and store.resumeNotifications() to eliminate redisplay overhead DURING import activities.
2007.05.27 [3.4.6] in handler(),  loadRemoteFile() and doImport(), added 'noreport' flag to suppress generation of ImportedTiddlers
2007.05.27 [3.4.5] in handler(),  initialize 'newTags' to [] (empty array) instead of null... fixes fatal error when loading tiddler without autotagging.
2007.04.22 [3.4.4] in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content.  Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.04.05 [3.4.3] in doImport(), changed this.readTiddlersFromHTML(html) to config.macros.loadTiddlers.readTiddlersFromHTML(html).  Fixes error caused when ImportTiddlersPlugin has NOT been installed along side this plugin.
2007.03.26 [3.4.2] renamed import() to doImport() to fix IE load-time error ("identifier expected").  This may also cause a problem with FF1.5.0.x.... Apparently, "import" is a reserved word in some browsers...
2007.03.22 [3.4.1] code cleanup: moved all functions inside object def'n, re-wrote report function
2007.03.21 [3.4.0] split ImportTiddlersPlugin and LoadTiddlersPlugin functionality into separate plugins
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
<<tiddler GTDMenu>>
[[Über dieses Notizbuch|About]]
<<calendar thismonth>>
!Thema
Kurzcharakterisierung des Inhalts als Überschrift.
Stichworte, Schlagworte, [[Tags]] (auch für das Wiederfinden wichtig!)
!Geschichte
Knappe Schilderung des Sachverhalts.
!Einsichten
Erfahrungen, die man gewonnen hat, Lösungsansätze oder Lösungen, Vorgehensweisen.
!Folgerungen (optional)
Schlüsse aus den Erfahrungen.
!Anschlussfragen (optional)
Fragen, die offen geblieben sind, als Denkanstösse.
Jeden verdammten Mittwoch: Nerviges Gemache

Dieser Tiddler steht als Beispiel für allen nervigen Kram, den man dauernd vergisst.

<<reminder dayofweek:3 title:"Jeden verdammten Mittwoch" leadtime:1 >>
/***
|Name|NestedSlidersPlugin|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.4.5|
|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||
|Options|##Configuration|
|Description|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
!!!!!Documentation
>see [[NestedSlidersPluginInfo]]
!!!!!Configuration
<<<
<<option chkFloatingSlidersAnimate>> allow floating sliders to animate when opening/closing
>Note: This setting can cause 'clipping' problems in some versions of InternetExplorer.
>In addition, for floating slider animation to occur you must also allow animation in general (see [[AdvancedOptions]]).
<<<
!!!!!Revisions
<<<
2008.06.07 - 2.4.5 in 'onmouseover' handler for 'open on hover' slider buttons,<br>use call() method when invoking document.onclick function (avoids error in IE)
|please see [[NestedSlidersPluginInfo]] for additional revision details|
2005.11.03 - 1.0.0 initial public release.  Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
<<<
!!!!!Code
***/
//{{{
version.extensions.nestedSliders = {major: 2, minor: 4, revision: 5, date: new Date(2008,6,7)};

// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkFloatingSlidersAnimate===undefined)
	config.options.chkFloatingSlidersAnimate=false; // avoid clipping problems in IE

// default styles for 'floating' class
setStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
	background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");

config.formatters.push( {
	name: "nestedSliders",
	match: "\\n?\\+{3}",
	terminator: "\\s*\\={3}\\n?",
	lookahead: "\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\@\\[\\>]*\\^)?)?(\\*)?(\\@)?(?:\\{\\{([\\w]+[\\s\\w]*)\\{)?(\\[[^\\]]*\\])?(\\[[^\\]]*\\])?(?:\\}{3})?(\\#[^:]*\\:)?(\\>)?(\\.\\.\\.)?\\s*",
	handler: function(w)
		{
			lookaheadRegExp = new RegExp(this.lookahead,"mg");
			lookaheadRegExp.lastIndex = w.matchStart;
			var lookaheadMatch = lookaheadRegExp.exec(w.source)
			if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
			{
				var defopen=lookaheadMatch[1];
				var cookiename=lookaheadMatch[2];
				var header=lookaheadMatch[3];
				var panelwidth=lookaheadMatch[4];
				var transient=lookaheadMatch[5];
				var hover=lookaheadMatch[6];
				var buttonClass=lookaheadMatch[7];
				var label=lookaheadMatch[8];
				var openlabel=lookaheadMatch[9];
				var panelID=lookaheadMatch[10];
				var blockquote=lookaheadMatch[11];
				var deferred=lookaheadMatch[12];

				// location for rendering button and panel
				var place=w.output;

				// default to closed, no cookie, no accesskey, no alternate text/tip
				var show="none"; var cookie=""; var key="";
				var closedtext=">"; var closedtip="";
				var openedtext="<"; var openedtip="";

				// extra "+", default to open
				if (defopen) show="block";

				// cookie, use saved open/closed state
				if (cookiename) {
					cookie=cookiename.trim().slice(1,-1);
					cookie="chkSlider"+cookie;
					if (config.options[cookie]==undefined)
						{ config.options[cookie] = (show=="block") }
					show=config.options[cookie]?"block":"none";
				}

				// parse label/tooltip/accesskey: [label=X|tooltip]
				if (label) {
					var parts=label.trim().slice(1,-1).split("|");
					closedtext=parts.shift();
					if (closedtext.substr(closedtext.length-2,1)=="=")	
						{ key=closedtext.substr(closedtext.length-1,1); closedtext=closedtext.slice(0,-2); }
					openedtext=closedtext;
					if (parts.length) closedtip=openedtip=parts.join("|");
					else { closedtip="show "+closedtext; openedtip="hide "+closedtext; }
				}

				// parse alternate label/tooltip: [label|tooltip]
				if (openlabel) {
					var parts=openlabel.trim().slice(1,-1).split("|");
					openedtext=parts.shift();
					if (parts.length) openedtip=parts.join("|");
					else openedtip="hide "+openedtext;
				}

				var title=show=='block'?openedtext:closedtext;
				var tooltip=show=='block'?openedtip:closedtip;

				// create the button
				if (header) { // use "Hn" header format instead of button/link
					var lvl=(header.length>5)?5:header.length;
					var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,buttonClass,title);
					btn.onclick=onClickNestedSlider;
					btn.setAttribute("href","javascript:;");
					btn.setAttribute("title",tooltip);
				}
				else
					var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,buttonClass);
				btn.innerHTML=title; // enables use of HTML entities in label

				// set extra button attributes
				btn.setAttribute("closedtext",closedtext);
				btn.setAttribute("closedtip",closedtip);
				btn.setAttribute("openedtext",openedtext);
				btn.setAttribute("openedtip",openedtip);
				btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
				btn.defOpen=defopen!=null; // save default open/closed state (boolean)
				btn.keyparam=key; // save the access key letter ("" if none)
				if (key.length) {
					btn.setAttribute("accessKey",key); // init access key
					btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus
				}
				btn.setAttribute("hover",hover?"true":"false");
				btn.onmouseover=function(ev) {
					// optional 'open on hover' handling
					if (this.getAttribute("hover")=="true" && this.sliderPanel.style.display=='none') {
						document.onclick.call(document,ev); // close transients
						onClickNestedSlider(ev); // open this slider
					}
					// mouseover on button aligns floater position with button
					if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this,this.sliderPanel);
				}

				// create slider panel
				var panelClass=panelwidth?"floatingPanel":"sliderPanel";
				if (panelID) panelID=panelID.slice(1,-1); // trim off delimiters
				var panel=createTiddlyElement(place,"div",panelID,panelClass,null);
				panel.button = btn; // so the slider panel know which button it belongs to
				btn.sliderPanel=panel; // so the button knows which slider panel it belongs to
				panel.defaultPanelWidth=(panelwidth && panelwidth.length>2)?panelwidth.slice(1,-1):"";
				panel.setAttribute("transient",transient=="*"?"true":"false");
				panel.style.display = show;
				panel.style.width=panel.defaultPanelWidth;
				panel.onmouseover=function(event) // mouseover on panel aligns floater position with button
					{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this.button,this); }

				// render slider (or defer until shown) 
				w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
				if ((show=="block")||!deferred) {
					// render now if panel is supposed to be shown or NOT deferred rendering
					w.subWikify(blockquote?createTiddlyElement(panel,"blockquote"):panel,this.terminator);
					// align floater position with button
					if (window.adjustSliderPos) window.adjustSliderPos(place,btn,panel);
				}
				else {
					var src = w.source.substr(w.nextMatch);
					var endpos=findMatchingDelimiter(src,"+++","===");
					panel.setAttribute("raw",src.substr(0,endpos));
					panel.setAttribute("blockquote",blockquote?"true":"false");
					panel.setAttribute("rendered","false");
					w.nextMatch += endpos+3;
					if (w.source.substr(w.nextMatch,1)=="\n") w.nextMatch++;
				}
			}
		}
	}
)

function findMatchingDelimiter(src,starttext,endtext) {
	var startpos = 0;
	var endpos = src.indexOf(endtext);
	// check for nested delimiters
	while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
		// count number of nested 'starts'
		var startcount=0;
		var temp = src.substring(startpos,endpos-1);
		var pos=temp.indexOf(starttext);
		while (pos!=-1)  { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
		// set up to check for additional 'starts' after adjusting endpos
		startpos=endpos+endtext.length;
		// find endpos for corresponding number of matching 'ends'
		while (startcount && endpos!=-1) {
			endpos = src.indexOf(endtext,endpos+endtext.length);
			startcount--;
		}
	}
	return (endpos==-1)?src.length:endpos;
}
//}}}
//{{{
window.onClickNestedSlider=function(e)
{
	if (!e) var e = window.event;
	var theTarget = resolveTarget(e);
	while (theTarget && theTarget.sliderPanel==undefined) theTarget=theTarget.parentNode;
	if (!theTarget) return false;
	var theSlider = theTarget.sliderPanel;
	var isOpen = theSlider.style.display!="none";

	// toggle label
	theTarget.innerHTML=isOpen?theTarget.getAttribute("closedText"):theTarget.getAttribute("openedText");
	// toggle tooltip
	theTarget.setAttribute("title",isOpen?theTarget.getAttribute("closedTip"):theTarget.getAttribute("openedTip"));

	// deferred rendering (if needed)
	if (theSlider.getAttribute("rendered")=="false") {
		var place=theSlider;
		if (theSlider.getAttribute("blockquote")=="true")
			place=createTiddlyElement(place,"blockquote");
		wikify(theSlider.getAttribute("raw"),place);
		theSlider.setAttribute("rendered","true");
	}
	// show/hide the slider
	if(config.options.chkAnimate && (!hasClass(theSlider,'floatingPanel') || config.options.chkFloatingSlidersAnimate))
		anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		theSlider.style.display = isOpen ? "none" : "block";
	// reset to default width (might have been changed via plugin code)
	theSlider.style.width=theSlider.defaultPanelWidth;
	// align floater panel position with target button
	if (!isOpen && window.adjustSliderPos) window.adjustSliderPos(theSlider.parentNode,theTarget,theSlider);
	// if showing panel, set focus to first 'focus-able' element in panel
	if (theSlider.style.display!="none") {
		var ctrls=theSlider.getElementsByTagName("*");
		for (var c=0; c<ctrls.length; c++) {
			var t=ctrls[c].tagName.toLowerCase();
			if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")
				{ ctrls[c].focus(); break; }
		}
	}
	var cookie=theTarget.sliderCookie;
	if (cookie && cookie.length) {
		config.options[cookie]=!isOpen;
		if (config.options[cookie]!=theTarget.defOpen)
			saveOptionCookie(cookie);
		else { // remove cookie if slider is in default display state
			var ex=new Date(); ex.setTime(ex.getTime()-1000);
			document.cookie = cookie+"=novalue; path=/; expires="+ex.toGMTString();
		}
	}

	// prevent SHIFT-CLICK from being processed by browser (opens blank window... yuck!)
	// prevent clicks *within* a slider button from being processed by browser
	// but allow plain click to bubble up to page background (to close transients, if any)
	if (e.shiftKey || theTarget!=resolveTarget(e))
		{ e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); }
	Popup.remove(); // close open popup (if any)
	return false;
}
//}}}
//{{{
// click in document background closes transient panels 
document.nestedSliders_savedOnClick=document.onclick;
document.onclick=function(ev) { if (!ev) var ev=window.event; var target=resolveTarget(ev);

	if (document.nestedSliders_savedOnClick)
		var retval=document.nestedSliders_savedOnClick.apply(this,arguments);
	// if click was inside a popup... leave transient panels alone
	var p=target; while (p) if (hasClass(p,"popup")) break; else p=p.parentNode;
	if (p) return retval;
	// if click was inside transient panel (or something contained by a transient panel), leave it alone
	var p=target; while (p) {
		if ((hasClass(p,"floatingPanel")||hasClass(p,"sliderPanel"))&&p.getAttribute("transient")=="true") break;
		p=p.parentNode;
	}
	if (p) return retval;
	// otherwise, find and close all transient panels...
	var all=document.all?document.all:document.getElementsByTagName("DIV");
	for (var i=0; i<all.length; i++) {
		 // if it is not a transient panel, or the click was on the button that opened this panel, don't close it.
		if (all[i].getAttribute("transient")!="true" || all[i].button==target) continue;
		// otherwise, if the panel is currently visible, close it by clicking it's button
		if (all[i].style.display!="none") window.onClickNestedSlider({target:all[i].button}) 
	}
	return retval;
};
//}}}
//{{{
// adjust floating panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel) {
	if (hasClass(panel,"floatingPanel")) {
		var rightEdge=document.body.offsetWidth-1;
		var panelWidth=panel.offsetWidth;
		var left=0;
		var top=btn.offsetHeight; 
		if (place.style.position=="relative" && findPosX(btn)+panelWidth>rightEdge) {
			left-=findPosX(btn)+panelWidth-rightEdge; // shift panel relative to button
			if (findPosX(btn)+left<0) left=-findPosX(btn); // stay within left edge
		}
		if (place.style.position!="relative") {
			var left=findPosX(btn);
			var top=findPosY(btn)+btn.offsetHeight;
			var p=place; while (p && !hasClass(p,'floatingPanel')) p=p.parentNode;
			if (p) { left-=findPosX(p); top-=findPosY(p); }
			if (left+panelWidth>rightEdge) left=rightEdge-panelWidth;
			if (left<0) left=0;
		}
		panel.style.left=left+"px"; panel.style.top=top+"px";
	}
}
//}}}
//{{{
// TW2.1 and earlier:
// hijack Slider stop handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function()
	{ this.coreStop.apply(this,arguments); this.element.style.overflow = "visible"; }

// TW2.2+
// hijack Morpher stop handler so sliderPanel/floatingPanel overflow is visible after animation has completed
if (version.major+.1*version.minor+.01*version.revision>=2.2) {
	Morpher.prototype.coreStop = Morpher.prototype.stop;
	Morpher.prototype.stop = function() {
		this.coreStop.apply(this,arguments);
		var e=this.element;
		if (hasClass(e,"sliderPanel")||hasClass(e,"floatingPanel")) {
			// adjust panel overflow and position after animation
			e.style.overflow = "visible";
			if (window.adjustSliderPos) window.adjustSliderPos(e.parentNode,e.button,e);
		}
	};
}
//}}}

<<gtdActionList>>
Das Ziel dieses Projekts soll sein ...

"""
# <<gtdAction "Tätigkeit 1" "@kontext1" "tag1">> optionale Bemerkung
"""
"""
# <<gtdAction "Tätigkeit 2" "@kontext2" "tag2">> optionale Bemerkung
"""

Weitere Bemerkungen ...
|''URL:''|http://dcubed.ca/d3-update-13.html|
|''Description:''|Official d-cubed feed|
|''Author:''|Tom Otvos|
<div class='header' macro='gradient vert #000 #464646'>
<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' force='true'></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>
! Projekte _mit_ anstehenden Tätigkeiten
<<gtdActionList *>>
! Projekte _ohne_ anstehende Tätigkeiten
<<list tagged "project done -someday">>
*+++(gtdImportantProjectsSliderState)[Important:] <<list tagged "project important -someday" all>>===
+++(gtdOtherProjectsSliderState)[Other:] <<list tagged "project -syntora -important -someday" all>>===
<<list tagged txtGTDReferenceContext any>>
/***
|''Name:''|ReminderPlugin|
|''Version:''|2.3.8.3 (Nov 28, 2006)|
|''Source:''|http://www.geocities.com/allredfaq/reminderMacros.html|
|''Author:''|Jeremy Sheeley(pop1280 [at] excite [dot] com)|
|''Modified by:''|Tom Otvos|
|''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.

''This version contains a fix by Tom Otvos that modifies tag filtering when tiddlers contain no tags. In this version, if you are filtering showReminders by tag, and a tiddler has no tags, the filter will //not// match the tiddler. There are also a number of small UI-related changes to make the reminder interface a bit nicer. Do not copy this into your own TW documents unless you accept these changes.''

!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 [[Simple examples]], [[Holidays]], [[showReminders]] and [[Personal Reminders]]

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

!Revision history
* 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://www.geocities.com/allredfaq/reminderMacros.html"};

//============================================================================
// 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,365];
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"] = "Es steht nichts an.";


//============================================================================
//  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 line is to preserve 1.2 compatibility
// if (!story) var story=window; 
//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 (!window.story) 
   {
      window.story=window; 
   }
   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)
{
	// tomo - cleaned up the form layout a bit
	var today=new Date().getMidnight();
	var formstring = '<html><br/><form>';
	
	formstring += '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;&nbsp;&nbsp;Reminder Title: <input type="text" size="40" name="title" value="" onfocus="this.select();">&nbsp;&nbsp;<input type="button" value="Add reminder" onclick="addReminderToTiddler(this.form)">';
	formstring += '</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 (!window.story) 
	{
		window.story=window; 
	}
	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);
	// tomo - make sure to save if required
	if(config.options.chkAutoSave)
		saveChanges();
};

function hasTag(tiddlerTags, tagFilters)
{
	// tomo - this has been updated to work better with tag-less tiddlers
	
	//Make sure we respond well to empty tagFilterlists
	if (tagFilters.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++)
	{
		var negTest = tagFilters[t3].length > 1 && tagFilters[t3].charAt(0) == '!';
		// do the positive filter test outside of the tag loop, in case there are no tags!
		if (bNoPos && !negTest) bNoPos = false;
		
		for(var t2=0; t2<tiddlerTags.length; t2++)
		{
			if (negTest) 
			{
				if (tiddlerTags[t2] == tagFilters[t3].substring(1))
				{
					//If at any time a negative filter is matched, we return false
					return false;
				}
			}
			else 
			{
				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(" ");
   }
   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;
};

//}}}
!Überfällige Tätigkeiten
<<showReminders leadtime:-365...-1 tag:"action !done" format:"DATE: @@color:red;TITLE@@ [ TIDDLER ]">>
!Tätigkeiten für heute und morgen
<<showReminders leadtime:0...1 tag:"action !done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>
!Alle Erinnerungen für die kommenden 7 Tage
<<showReminders leadtime:0...7 tag:"!done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>
~TiddlyWiki-Notizbuch - privat
Erwin Lottemann
<<list tagged txtGTDSomedayContext any>>
{{{
//--
//-- TiddlyWiki German Translation - r6082 for TiddlyWiki 2.4.1 - GermanTranslation2.4b
//-- Maintainer: Besim Karadeniz <besim(at)karadeniz.de>
//-- Web: www.karadeniz.de/tiddlywiki/
//--

if (config.options.txtUserName == "YourName")
	merge(config.options,{txtUserName: "IhrName"});

merge(config.tasks,{
	save: {text: "speichern", tooltip: "Änderungen in dieses TiddlyWiki speichern", action: saveChanges},
	sync: {text: "synchronisieren", tooltip: "Änderungen mit anderen TiddlyWiki-Dateien und Servern synchronisieren", content: '<<sync>>'},
	importTask: {text: "importieren", tooltip: "Tiddler und Plugins aus anderen TiddlyWiki-Dateien und Servern importieren", content: '<<importTiddlers>>'},
	tweak: {text: "optimieren", tooltip: "Erscheinungsbild und Reaktion des TiddlyWiki optimieren", content: '<<options>>'},
	upgrade: {text: "upgraden", tooltip: "Upgraden des Kerncodes von TiddlyWiki", content: '<<upgrade>>'},
	plugins: {text: "Plugins", tooltip: "Installierte Plugins verwalten", content: '<<plugins>>'}
});

// Optionen, die im Options-Panel oder/in Cookies eingestellt werden koennen
merge(config.optionsDesc,{
	txtUserName: "Ihr Benutzername zum Unterzeichnen Ihrer Einträge",
	chkRegExpSearch: "Reguläre Ausdrücke in der Suche aktivieren",
	chkCaseSensitiveSearch: "Groß-/Kleinschreibung in der Suche aktivieren",
	chkIncrementalSearch: "Inkrementelle Zeichen-für-Zeichen-Suche",
	chkAnimate: "Animationen aktivieren",
	chkSaveBackups: "Beim Speichern ein Backup erstellen",
	chkAutoSave: "Automatisch speichern",
	chkGenerateAnRssFeed: "RSS-Feed beim Speichern generieren",
	chkSaveEmptyTemplate: "Leere Vorlage beim Speichern generieren",
	chkOpenInNewWindow: "Externe Links in einem neuen Fenster öffnen",
	chkToggleLinks: "Klick auf geöffnete Tiddler lässt diese schließen",
	chkHttpReadOnly: "Bearbeitungsfunktionen ausblenden, wenn Zugriff via HTTP",
	chkForceMinorUpdate: "Bearbeitungen als kleine Änderungen mit Beibehaltung von Datum und Zeit behandeln",
	chkConfirmDelete: "Löschbestätigung vor dem Löschen von Tiddlern",
	chkInsertTabs: "Benutzen Sie die Tabulatortaste um Tabulatorzeichen einzufügen anstelle jeweils zum nächsten Feld zu springen",
	txtBackupFolder: "Verzeichnisname für Backup Dateien:",
	txtMaxEditRows: "Maximale Zahl von Zeilen in einer Textbox eines Tiddlers:",
	txtFileSystemCharSet: "Standard-Zeichensatz beim Speichern von Änderungen (nur Firefox/Mozilla)"});

merge(config.messages,{
	customConfigError: "Beim Laden von Plugins sind Fehler aufgetreten. Siehe PluginManager für Details",
	pluginError: "Fehler: %0",
	pluginDisabled: "Nicht ausgeführt, da durch 'systemConfigDisable'-Tag deaktiviert",
	pluginForced: "Ausgeführt, da durch 'systemConfigForce'-Tag erzwungen",
	pluginVersionError: "Nicht ausgeführt, da dieses Plugin eine neuere Version von TiddlyWiki erfordert",
	nothingSelected: "Nichts ausgewählt. Sie müssen zuerst ein oder mehrere Elemente auswählen",
	savedSnapshotError: "Es scheint, dass dieses TiddlyWiki inkorrekt gespeichert wurde. Bitte besuchen Sie http://www.tiddlywiki.com/#DownloadSoftware für Details",
	subtitleUnknown: "(unbekannt)",
	undefinedTiddlerToolTip: "Der Tiddler '%0' existiert noch nicht",
	shadowedTiddlerToolTip: "Der Tiddler '%0' existiert noch nicht, hat aber einen vordefinierten Schatteneintrag",
	tiddlerLinkTooltip: "%0 - %1, %2",
	externalLinkTooltip: "Externer Link zu %0",
	noTags: "Es gibt keine getaggten Tiddler",
	notFileUrlError: "Sie müssen zunächst dieses TiddlyWiki in eine Datei speichern, bevor Änderungen gespeichert werden können",
	cantSaveError: "Änderungen können nicht gespeichert werden. Mögliche Gründe:\n- Ihr Browser unterstützt das Abspeichern nicht (Firefox, Internet Explorer, Safari und Opera können dies mit richtiger Konfiguration)\n- Der Pfadname zu Ihrem TiddlyWiki enthält ungültige Zeichen\n- Die TiddlyWiki-HTML-Datei wurde verschoben oder umbenannt",
	invalidFileError: "Die originale Datei '%0' scheint kein gültiges TiddlyWiki zu sein",
	backupSaved: "Backup gespeichert",
	backupFailed: "Fehler beim Speichern des Backup",
	rssSaved: "RSS-Feed gespeichert",
	rssFailed: "Fehler beim Speichern des RSS-Feed",
	emptySaved: "Leere Vorlage gespeichert",
	emptyFailed: "Fehler beim Speichern der leeren Vorlage",
	mainSaved: "Haupt-TiddlyWiki-Datei gespeichert",
	mainFailed: "Fehler beim Speichern der Haupt-TiddlyWiki-Datei. Ihre Änderungen wurden nicht gespeichert",
	macroError: "Fehler im Makro <<\%0>>",
	macroErrorDetails: "Fehler beim Ausführen von Makro <<\%0>>:\n%1",
	missingMacro: "Kein entsprechendes Makro vorhanden",
	overwriteWarning: "Ein Tiddler namens '%0' existiert bereits. Wählen Sie OK zum Überschreiben",
	unsavedChangesWarning: "WARNUNG! Ungespeicherte Änderungen im TiddlyWiki vorhanden\n\nWählen Sie OK zum Speichern\nWählen Sie ABBRECHEN/CANCEL zum Verwerfen",
	confirmExit: "--------------------------------\n\nUngespeicherte Änderungen im TiddlyWiki vorhanden. Wenn Sie fortfahren, werden Sie diese Änderungen verlieren\n\n--------------------------------",
	saveInstructions: "SaveChanges",
	unsupportedTWFormat: "Nicht unterstütztes TiddlyWiki-Format '%0'",
	tiddlerSaveError: "Fehler beim Speichern von Tiddler '%0'",
	tiddlerLoadError: "Fehler beim Laden von Tiddler '%0'",
	wrongSaveFormat: "Speichern im Speicherformat '%0' nicht möglich. Standardformat zum Speichern wird verwendet.",
	invalidFieldName: "Ungültiger Dateiname %0",
	fieldCannotBeChanged: "Feld '%0' kann nicht geändert werden",
	loadingMissingTiddler: "Es wird versucht, den Tiddler '%0' vom Server '%1' bei\n\n'%2' im Workspace '%3' abzurufen",
	upgradeDone: "Das Upgrade auf Version %0 ist komplett\n\nKlicken Sie auf 'OK' zum Neuladen des aktualisierten TiddlyWiki"});

merge(config.messages.messageClose,{
	text: "schließen",
	tooltip: "diesen Textbereich schließen"});

config.messages.backstage = {
	open: {text: "Backstage", tooltip: "Öffnen Sie den Backstage-Bereich für Arbeiten an Entwicklungs- und Bearbeitungsaufgaben"},
	close: {text: "schließen", tooltip: "Backstage-Bereich schließen"},
	prompt: "Backstage: ",
	decal: {
		edit: {text: "bearbeiten", tooltip: "Den Tiddler '%0' bearbeiten"}
	}
};

config.messages.listView = {
	tiddlerTooltip: "Klick für den vollen Text dieses Tiddlers",
	previewUnavailable: "(Vorschau nicht vorhanden)"
};

config.messages.dates.months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November","Dezember"];
config.messages.dates.days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];
config.messages.dates.shortMonths = ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
config.messages.dates.shortDays = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
// Suffixe für Datum (englischsprachig), z.B. "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
	"th","th","th","th","th","th","th","th","th","th",
	"st","nd","rd","th","th","th","th","th","th","th",
	"st"];
config.messages.dates.am = "am";
config.messages.dates.pm = "pm";

merge(config.messages.tiddlerPopup,{
	});

merge(config.views.wikified.tag,{
	labelNoTags: "keine Tags",
	labelTags: "Tags: ",
	openTag: "Öffne Tag '%0'",
	tooltip: "Zeige Tiddlers mit Tags '%0'",
	openAllText: "Öffne alle",
	openAllTooltip: "Alle diese Tiddler öffnen",
	popupNone: "Keine anderen Tiddler mit '%0' getaggt"});

merge(config.views.wikified,{
	defaultText: "Der Tiddler '%0' existiert noch nicht. Doppelklicken zum Erstellen",
	defaultModifier: "(fehlt)",
	shadowModifier: "(vordefinierter Schatten-Tiddler)",
	dateFormat: "DD. MMM YYYY",
	createdPrompt: "erstellt"});

merge(config.views.editor,{
	tagPrompt: "Geben Sie die Tags durch Leerstellen getrennt ein, [[benutzen Sie doppelte eckige Klammern]] falls nötig, oder wählen Sie vorhandene",
	defaultText: "Geben Sie den Text für '%0' ein"});

merge(config.views.editor.tagChooser,{
	text: "Tags",
	tooltip: "Wählen Sie vorhandene Tags zum Hinzufügen zu diesem Tiddler aus",
	popupNone: "Es sind keine Tags definiert",
	tagTooltip: "Tag '%0' hinzufügen"});

merge(config.messages,{
	sizeTemplates:
		[
		{unit: 1024*1024*1024, template: "%0\u00a0GB"},
		{unit: 1024*1024, template: "%0\u00a0MB"},
		{unit: 1024, template: "%0\u00a0KB"},
		{unit: 1, template: "%0\u00a0B"}
		]});

merge(config.macros.search,{
	label: "suchen",
	prompt: "Dieses TiddlyWiki durchsuchen",
	accessKey: "F",
	successMsg: "%0 Tiddler gefunden, die %1 enthalten",
	failureMsg: "Keine Tiddler gefunden, die %0 enthalten"});

merge(config.macros.tagging,{
	label: "Tagging: ",
	labelNotTag: "kein Tagging",
	tooltip: "Liste der Tiddler, die mit '%0' getaggt sind"});

merge(config.macros.timeline,{
	dateFormat: "DD. MMM YYYY"});

merge(config.macros.allTags,{
	tooltip: "Tiddler, die mit '%0' getagged sind, anzeigen",
	noTags: "Keine getaggten Tiddler vorhanden"});

config.macros.list.all.prompt = "Alle Tiddler in alphabetischer Reihenfolge";
config.macros.list.missing.prompt = "Tiddler, auf die verwiesen wird, die aber nicht existieren";
config.macros.list.orphans.prompt = "Tiddler, auf die nicht von anderen Tiddlern verwiesen wird";
config.macros.list.shadowed.prompt = "Tiddler, für die Standardeinträge existieren";
config.macros.list.touched.prompt = "Tiddlers, die lokal verändert wurden";

merge(config.macros.closeAll,{
	label: "alle schließen",
	prompt: "Alle angezeigten Tiddler schließen (außer denen, die gerade bearbeitet werden)"});

merge(config.macros.permaview,{
	label: "Permaview",
	prompt: "Erzeugt einen URL, mit dem auf alle gerade geöffneten Tiddler verwiesen werden kann"});

merge(config.macros.saveChanges,{
	label: "Änderungen speichern",
	prompt: "Alle Änderungen speichern",
	accessKey: "S"});

merge(config.macros.newTiddler,{
	label: "Neuer Tiddler",
	prompt: "Neuen Tiddler erstellen",
	title: "Neuer Tiddler",
	accessKey: "N"});

merge(config.macros.newJournal,{
	label: "Neues Journal",
	prompt: "Neuen Tiddler mit aktuellem Datum und aktueller Zeit erstellen",
	accessKey: "J"});

merge(config.macros.options,{
	wizardTitle: "Erweiterte Optionen verändern",
	step1Title: "Diese Optionen werden mit Cookies in Ihrem Browser gespeichert",
	step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>Unbekannte Optionen anzeigen</input>",
	unknownDescription: "//(unbekannt)//",
	listViewTemplate: {
		columns: [
			{name: 'Option', field: 'option', title: "Option", type: 'String'},
			{name: 'Description', field: 'description', title: "Beschreibung", type: 'WikiText'},
			{name: 'Name', field: 'name', title: "Name", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'}
			]}
	});

merge(config.macros.plugins,{
	wizardTitle: "Plugins verwalten",
	step1Title: "Aktuell geladene Plugins",
	step1Html: "<input type='hidden' name='markList'></input>",
	skippedText: "(Dieses Plugin wurde nicht ausgeführt, da es nach dem Start hinzugefügt wurde)",
	noPluginText: "Es sind keine Plugins installiert",
	confirmDeleteText: "Wollen Sie wirklich folgende Plugins löschen:\n\n%0",
	removeLabel: "systemConfig-Tag entfernen",
	removePrompt: "systemConfig-Tag entfernen",
	deleteLabel: "löschen",
	deletePrompt: "Diese Tiddler endgültig löschen",
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Grösse", type: 'Size'},
			{name: 'Forced', field: 'forced', title: "Erzwungen", tag: 'systemConfigForce', type: 'TagCheckbox'},
			{name: 'Disabled', field: 'disabled', title: "Deaktiviert", tag: 'systemConfigDisable', type: 'TagCheckbox'},
			{name: 'Executed', field: 'executed', title: "Geladen", type: 'Boolean', trueText: "Ja", falseText: "Nein"},
			{name: 'Startup Time', field: 'startupTime', title: "Startzeit", type: 'String'},
			{name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Fehler", falseText: "OK"},
			{name: 'Log', field: 'log', title: "Log", type: 'StringList'}
			],
		rowClasses: [
			{className: 'error', field: 'error'},
			{className: 'warning', field: 'warning'}
			]}
	});

merge(config.macros.toolbar,{
	moreLabel: "mehr",
	morePrompt: "Weitere Funktionen anzeigen"
	});

merge(config.macros.refreshDisplay,{
	label: "aktualisieren",
	prompt: "Gesamte TiddlyWiki-Ansicht aktualisieren"
	});

merge(config.macros.importTiddlers,{
	readOnlyWarning: "Sie können nicht in eine schreibgeschützte TiddlyWiki-Datei importieren. Versuchen Sie diese über eine file:// URL zu öffnen",
	wizardTitle: "Tiddler aus anderer Datei oder anderem Server importieren",
	step1Title: "Schritt 1: Server oder TiddlyWiki-Datei ausfindig machen",
	step1Html: "Typ des Servers auswählen: <select name='selTypes'><option value=''>Wählen...</option></select><br>URL oder Pfadnamen eingeben: <input type='text' size=50 name='txtPath'><br>...oder nach einer Datei browsen: <input type='file' size=50 name='txtBrowse'><br><hr>...oder einen vordefinierten Feed auswählen: <select name='selFeeds'><option value=''>Wählen...</option></select>",
	openLabel: "öffnen",
	openPrompt: "Verbindung zu dieser Datei oder Server starten",
	openError: "Beim Versuch, die TiddlyWiki-Datei zu öffnen, gab es Probleme",
	statusOpenHost: "Verbindung zum Host starten",
	statusGetWorkspaceList: "Liste von vorhandenen Workspaces abrufen",
	step2Title: "Schritt 2: Workspace auswählen",
	step2Html: "Einen Workspace-Namen eingeben: <input type='text' size=50 name='txtWorkspace'><br>...oder ein Workspace auswählen: <select name='selWorkspace'><option value=''>Wählen...</option></select>",
	cancelLabel: "abbrechen",
	cancelPrompt: "Diesen Import abbrechen",
	statusOpenWorkspace: "Workspace wird geöffnet",
	statusGetTiddlerList: "Abrufen der Liste von vorhandenen Workspaces",
	errorGettingTiddlerList: "Fehler beim Abrufen der Liste der Tiddler, klicken Sie auf ABBRECHEN/CANCEL, um es nochmal zu probieren",
	step3Title: "Schritt 3: Zu importierende Tiddler auswählen",
	step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>Links dieser Tiddler zum Server erhalten, um nachfolgende Änderungen synchronisieren zu können</input><br><input type='checkbox' checked='false' name='chkSave'>Speichern der Details dieses Servers in einem 'systemServer'Tiddler namens:</input> <input type='text' size=25 name='txtSaveTiddler'>",
	importLabel: "importieren",
	importPrompt: "Diese Tiddler importieren",
	confirmOverwriteText: "Wollen Sie wirklich folgende Tiddler überschreiben:\n\n%0",
	step4Title: "Schritt 4: Importieren von %0 Tiddler",
	step4Html: "<input type='hidden' name='markReport'></input>",
	doneLabel: "Erledigt",
	donePrompt: "Diesen Assistenten schliessen",
	statusDoingImport: "Tiddler werden importiert",
	statusDoneImport: "Alle Tiddler importiert",
	systemServerNamePattern: "%2 auf %1",
	systemServerNamePatternNoWorkspace: "%1",
	confirmOverwriteSaveTiddler: "Der Tiddler '%0' existiert bereits. Klicken Sie auf 'OK' um ihn mit den Details dieses Servers zu überschreiben, oder 'Abbrechen', um ihn unverändert zu lassen",
	serverSaveTemplate: "|''Eingabe:''|%0|\n|''URL:''|%1|\n|''Workspace:''|%2|\n\nDieser Tiddler wurde automatisch erstellt, um Details dieses Servers aufzuzeichnen",
	serverSaveModifier: "(System)",
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Grösse", type: 'Size'},
			{name: 'Tags', field: 'tags', title: "Tags", type: 'Tags'}
			],
		rowClasses: [
			]}
	});

merge(config.macros.upgrade,{
	wizardTitle: "Upgraden des Kerncodes von TiddlyWiki",
	step1Title: "Update oder Reparatur dieses TiddlyWiki auf die aktuellste Version",
	step1Html: "Sie sind dabei, auf die aktuellste Version des TiddlyWiki-Kerncodes upzugraden (von <a href='%0' class='externalLink' target='_blank'>%1</a>). Ihre Inhalte werden während dem Upgrade erhalten bleiben.<br><br>Bitte beachten Sie, dass Kerncode-Updates mit älteren Plugins kollidieren können. Wenn Sie Probleme mit der aktualisierten Datei beobachten, besuchen Sie bitte <a href='http://www.tiddlywiki.org/wiki/CoreUpgrades' class='externalLink' target='_blank'>http://www.tiddlywiki.org/wiki/CoreUpgrades</a>",
	errorCantUpgrade: "Upgrade dieses TiddlyWiki nicht möglich. Sie können nur lokal abgespeicherte TiddlyWiki-Dateien upgraden",
	errorNotSaved: "Sie müssen zunächst Änderungen speichern, bevor Sie ein Upgrade starten können",
	step2Title: "Upgrade-Details bestätigen",
	step2Html_downgrade: "Sie sind dabei, von der TiddlyWiki-Version %0 auf die Version %1 downzugraden.<br><br>Der Downgrade auf eine frühere Version von TiddlyWiki wird nicht empfohlen",
	step2Html_restore: "Dieses TiddlyWiki scheint bereits die aktuellste Version des Kerncodes (%0) einzusetzen.<br><br>Sie können mit dem Upgrade fortsetzen, um sicherzustellen, dass der Kerncode nicht korrumpiert oder beschädigt wurde",
	step2Html_upgrade: "Sie sind dabei, von der TiddlyWiki-Version %0 auf die Version %1 upzugraden",
	upgradeLabel: "upgraden",
	upgradePrompt: "Vorbereiten des Upgrade-Prozesses",
	statusPreparingBackup: "Backup vorbereiten",
	statusSavingBackup: "Backup-Datei speichern",
	errorSavingBackup: "Ein Problem mit dem Speichern der Backup-Datei ist aufgetreten",
	statusLoadingCore: "Kerncode laden",
	errorLoadingCore: "Fehler beim Laden des Kerncodes",
	errorCoreFormat: "Fehler im neuen Kerncode",
	statusSavingCore: "Neuen Kerncode speichern",
	statusReloadingCore: "Neuen Kerncode neu laden",
	startLabel: "starten",
	startPrompt: "Upgrade-Prozess starten",
	cancelLabel: "abbrechen",
	cancelPrompt: "Upgrade-Prozess abbrechen",
	step3Title: "Upgrade abgebrochen",
	step3Html: "Sie haben den Upgrade-Prozess abgebrochen"
	});

merge(config.macros.sync,{
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Server Type', field: 'serverType', title: "Server-Typ", type: 'String'},
			{name: 'Server Host', field: 'serverHost', title: "Server-Host", type: 'String'},
			{name: 'Server Workspace', field: 'serverWorkspace', title: "Server-Workspace", type: 'String'},
			{name: 'Status', field: 'status', title: "Status der Synchronisation", type: 'String'},
			{name: 'Server URL', field: 'serverUrl', title: "Server-URL", text: "View", type: 'Link'}
			],
		rowClasses: [
			],
		buttons: [
			{caption: "Diese Tiddler synchronisieren", name: 'sync'}
			]},
	wizardTitle: "Mit externen Servern oder Dateien synchronisieren",
	step1Title: "Wählen Sie die Tiddler aus, die Sie synchronisieren möchten",
	step1Html: '<input type="hidden" name="markList"></input>',
	syncLabel: "synchronisieren",
	syncPrompt: "Diese Tiddler synchronisieren",
	hasChanged: "Verändert während Trennung",
	hasNotChanged: "Unverändert während Trennung",
	syncStatusList: {
		none: {text: "...", display:null, className:'notChanged'},
		changedServer: {text: "Auf dem Server geändert", display:null, className:'changedServer'},
		changedLocally: {text: "Im ausgesteckten Zustand geändert", display:null, className:'changedLocally'},
		changedBoth: {text: "Im ausgesteckten Zustand und auf dem Server geändert", display:null, className:'changedBoth'},
		notFound: {text: "Auf dem Server nicht gefunden", display:null, className:'notFound'},
		putToServer: {text: "Aktualisierung auf dem Server gespeichert", display:null, className:'putToServer'},
		gotFromServer: {text: "Aktualisierung vom Server abgerufen", display:null, className:'gotFromServer'}
		}
	});

merge(config.macros.annotations,{
	});

merge(config.commands.closeTiddler,{
	text: "schließen",
	tooltip: "Diesen Tiddler schließen"});

merge(config.commands.closeOthers,{
	text: "andere schließen",
	tooltip: "Alle anderen Tiddler schließen"});

merge(config.commands.editTiddler,{
	text: "bearbeiten",
	tooltip: "Diesen Tiddler bearbeiten",
	readOnlyText: "betrachten",
	readOnlyTooltip: "Quellcode dieses Tiddlers betrachten"});

merge(config.commands.saveTiddler,{
	text: "fertig",
	tooltip: "Änderungen an diesem Tiddler speichern"});

merge(config.commands.cancelTiddler,{
	text: "abbrechen",
	tooltip: "Änderungen an diesem Tiddler verwerfen",
	warning: "Wollen Sie wirklich Änderungen in '%0' verwerfen?",
	readOnlyText: "fertig",
	readOnlyTooltip: "Diesen Tiddler normal anzeigen"});

merge(config.commands.deleteTiddler,{
	text: "löschen",
	tooltip: "Diesen Tiddler löschen",
	warning: "Wollen Sie '%0' wirklich löschen?"});

merge(config.commands.permalink,{
	text: "Permalink",
	tooltip: "Permalink für diesen Tiddler"});

merge(config.commands.references,{
	text: "Referenzen",
	tooltip: "Alle Tiddler zeigen, die auf diesen verweisen",
	popupNone: "Keine Referenzen"});

merge(config.commands.jump,{
	text: "springen",
	tooltip: "Zu anderem, geöffneten Tiddler springen"});

merge(config.commands.syncing,{
	text: "Synchronisierung läuft",
	tooltip: "Synchronisation dieses Tiddlers mit einem Server oder einer externen Datei kontrollieren",
	currentlySyncing: "<div>Aktuell am Synchronisieren mit <span class='popupHighlight'>'%0'</span> zu:</"+"div><div>Host: <span class='popupHighlight'>%1</span></"+"div><div>Workspace: <span class='popupHighlight'>%2</span></"+"div>", // Hinweis - Das Schliessen des <div>-Tag verlassen
	notCurrentlySyncing: "Derzeit keine Synchronisierung",
	captionUnSync: "Synchronisierung dieses Tiddlers stoppen",
	chooseServer: "Diesen Tiddler mit anderem Server synchronisieren:",
	currServerMarker: "\u25cf ",
	notCurrServerMarker: "  "});

merge(config.commands.fields,{
	text: "Felder",
	tooltip: "Erweiterte Felder dieses Tiddlers anzeigen",
	emptyText: "Keine erweiterten Felder für diesen Tiddler vorhanden",
	listViewTemplate: {
		columns: [
			{name: 'Field', field: 'field', title: "Feld", type: 'String'},
			{name: 'Value', field: 'value', title: "Wert", type: 'String'}
			],
		rowClasses: [
			],
		buttons: [
			]}});

merge(config.shadowTiddlers,{
	DefaultTiddlers: "[[GettingStarted]]",
	MainMenu: "[[GettingStarted]]",
	SiteTitle: "Mein TiddlyWiki",
	SiteSubtitle: "ein wiederverwendbares nichtlineares, persönliches ~Web-Notizbuch",
	SiteUrl: "http://www.tiddlywiki.com/",
	SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD. MMM YYYY" "Journal">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "Optionen \u00bb" "Optionen von TiddlyWiki ändern">>',
	SideBarTabs: '<<tabs txtMainTab "Zeitachse" "Zeitachse" TabTimeline "Alles" "Alle Tiddler" TabAll "Tags" "Alle Tags" TabTags "Mehr" "Weitere Listen" TabMore>>',
	TabMore: '<<tabs txtMoreTab "Fehlend" "Fehlende Tiddler" TabMoreMissing "Waisen" "Verwaiste Tiddler" TabMoreOrphans "Schatten" "Tiddler mit Schatteneinträgen" TabMoreShadowed>>'
	});

merge(config.annotations,{
	AdvancedOptions: "Dieser Schatten-Tiddler bietet Zugang zu diversen erweiterten Optionen",
	ColorPalette: "Diese Werte in diesem Schatten-Tiddler legen das Farbschema der Benutzerschnittstelle des TiddlyWiki fest",
	DefaultTiddlers: "Die in diesem Schatten-Tiddler aufgelisteten Tiddler werden automatisch beim Start des TiddlyWiki angezeigt",
	EditTemplate: "Die HTML-Vorlage in diesem Schatten-Tiddler legt das Aussehen von Tiddler während ihrer Bearbeitung fest",
	GettingStarted: "Dieser Schatten-Tiddler bietet eine einfache Bedienungsanleitung",
	ImportTiddlers: "Dieser Schatten-Tiddler bietet Zugang zum Import von Tiddler",
	MainMenu: "Dieser Schatten-Tiddler dient als Container für das Hauptmenü in der linksseitigen Spalte des Bildschirms",
	MarkupPreHead: "Dieser Tiddler wird an der Spitze der <head>-Sektion der HTML-Datei des TiddlyWiki eingefügt",
	MarkupPostHead: "Dieser Tiddler wird am Ende der <head>-Sektion der HTML-Datei des TiddlyWiki eingefügt",
	MarkupPreBody: "Dieser Tiddler wird an der Spitze der <body>-Sektion der HTML-Datei des TiddlyWiki eingefügt",
	MarkupPostBody: "Dieser Tiddler wird am Ende der <body>-Sektion der HTML-Datei des TiddlyWiki unmittelbar nach dem Scriptblock eingefügt",
	OptionsPanel: "Dieser Schatten-Tiddler dient als Container für das einblendbare Optionsfeld in der rechtsseitigen Seitenleiste",
	PageTemplate: "Die HTML-Vorlage in diesem Schatten-Tiddler legt das allgemeine Aussehen des TiddlyWiki fest",
	PluginManager: "Dieser Schatten-Tiddler bietet Zugang zum Plugin-Manager",
	SideBarOptions: "Dieser Schatten-Tiddler dient als Container für das Optionsfeld in der rechtsseitigen Seitenleiste",
	SideBarTabs: "Dieser Schatten-Tiddler dient als Container für das Tab-Panel in der rechtsseitigen Seitenleiste",
	SiteSubtitle: "Dieser Schatten-Tiddler enthält den zweiten Teil der Seitenüberschrift",
	SiteTitle: "Dieser Schatten-Tiddler enthält den ersten Teil der Seitenüberschrift",
	SiteUrl: "Dieser Schatten-Tiddler sollte den vollständigen Ziel-URL der Veröffentlichung enthalten",
	StyleSheetColors: "Dieser Schatten-Tiddler enthält CSS-Definitionen bezüglich der Farbe von Seitenelementen. ''DIESEN TIDDLER NICHT BEARBEITEN'', fügen Sie Ihre Änderungen stattdessen in den StyleSheet-Schatten-Tiddler ein",
	StyleSheet: "Dieser Tiddler kann benutzerspezifische CSS-Definitionen enthalten",
	StyleSheetLayout: "Dieser Schatten-Tiddler enthält CSS-Definitionen bezüglich dem Aussehen von Seitenelementen. ''DIESEN TIDDLER NICHT BEARBEITEN'', fügen Sie Ihre Änderungen stattdessen in den StyleSheet-Schatten-Tiddler ein",
	StyleSheetLocale: "Dieser Schatten-Tiddler enthält CSS-Definitionen bezüglich lokale Übersetzungen",
	StyleSheetPrint: "Dieser Schatten-Tiddler enthält CSS-Definitionen zum Drucken",
	TabAll: "Dieser Schatten-Tiddler enthält den Inhalt des 'Alles'-Tab in der rechtsseitigen Seitenleiste",
	TabMore: "Dieser Schatten-Tiddler enthält den Inhalt des 'Mehr'-Tab in der rechtsseitigen Seitenleiste",
	TabMoreMissing: "Dieser Schatten-Tiddler enthält den Inhalt des 'Fehlend'-Tab in der rechtsseitigen Seitenleiste",
	TabMoreOrphans: "Dieser Schatten-Tiddler enthält den Inhalt des 'Waisen'-Tab in der rechtsseitigen Seitenleiste",
	TabMoreShadowed: "Dieser Schatten-Tiddler enthält den Inhalt des 'Schatten'-Tab in der rechtsseitigen Seitenleiste",
	TabTags: "Dieser Schatten-Tiddler enthält den Inhalt des 'Tags'-Tab in der rechtsseitigen Seitenleiste",
	TabTimeline: "Dieser Schatten-Tiddler enthält den Inhalt des 'Zeitachse'-Tab in der rechtsseitigen Seitenleiste",
	ToolbarCommands: "Dieser Schatten-Tiddler legt fest, welche Befehle in Tiddler-Toolbars angezeigt werden",
	ViewTemplate: "Die HTML-Vorlage in diesem Schatten-Tiddler legt das Aussehen der Tiddler fest"
	});

// Weitere Uebersetzungen des Interface

merge(config.shadowTiddlers,{
	OptionsPanel: "Diese [[Interface-Einstellungen|InterfaceOptions]] zur Anpassung von TiddlyWiki werden in Ihrem Browser gespeichert\n\nIhr Benutzername zum Unterzeichnen Ihrer Einträge. Bitte als WikiWord (z.B. KlausBrandmüller) schreiben\n\n<<option txtUserName>>\n<<option chkSaveBackups>> [[Backups speichern|SaveBackups]]\n<<option chkAutoSave>> [[Automatisch speichern|AutoSave]]\n<<option chkRegExpSearch>> [[RegExp Suche|RegExpSearch]]\n<<option chkCaseSensitiveSearch>> [[Groß-/Kleinschreibung in Suche|CaseSensitiveSearch]]\n<<option chkAnimate>> [[Animationen aktivieren|EnableAnimations]]\n\n----\[[Erweiterte Optionen|AdvancedOptions]]\nPluginManager\nImportTiddlers",
	GettingStarted: "Um mit diesem TiddlyWiki zu starten, sollten Sie folgende Tiddler modifizieren:\n* SiteTitle & SiteSubtitle: Den [[Titel|SiteTitle]] und [[Untertitel|SiteSubtitle]] der Site, wie oben angezeigt (nach dem Speichern werden diese auch in der Titelzeile des Browsers angezeigt)\n* MainMenu: Ihr Inhaltsverzeichnis (für gewöhnlich Links)\n* DefaultTiddlers: Beinhaltet die Namen der Tiddler, die Sie angezeigt haben möchten, wenn das TiddlyWiki geöffnet wird.\nSie sollten zudem Ihren Benutzernamen zum Unterzeichnen Ihrer Bearbeitungen eingeben: <<option txtUserName>>",
	ViewTemplate: "<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (erstellt am <span macro='view created date'></span>)</div>\n<div class='tagging' macro='tagging'></div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div>",
	InterfaceOptions: "Die [[Interface-Einstellungen|InterfaceOptions]] werden angezeigt, wenn Sie rechts auf 'Optionen' klicken. Sie werden mit einem Cookie in Ihrem Browser gespeichert, um sie zwischen den Aufrufen zu sichern. Nähere Informationen zu den einzelnen Funktionen finden Sie, wenn Sie die Funktion selbst anklicken.",
	WikiWord: "Ein WikiWord ist ein Wort, das aus mehreren einzelnen Wörtern zusammengesetzt ist, in dem jedes Wort mit einem Grossbuchstaben beginnt und eine individuelle Seite bezeichnet.",
	SaveBackups: "[[Backups speichern|SaveBackups]] ist eine Funktion, mit der automatisch bei jedem Abspeichern ein Backup erstellt wird.",
	AutoSave: "[[Automatisches Speichern|AutoSave]] speichert automatisch Änderungen jedes Mal, wenn Sie einen Tiddler bearbeiten. Damit sinken die Chancen, dass Sie Daten verlieren. Beachten Sie jedoch, dass bei aktivierter [[Backup-Funktion|SaveBackups]] natürlich auch eine Menge Backup-Dateien erstellt werden. Entscheiden Sie sich deshalb für die eine oder andere Funktion.",
	RegExpSearch: "Mit der [[RegExp Suche|RegExpSearch]] können Sie mit regulären Suchausdrücken flexible Suchanfragen vornehmen.",
	CaseSensitiveSearch: "Die Unterscheidung der [[Groß-/Kleinschreibung in Suche|CaseSensitiveSearch]] tut genau dies.",
	EnableAnimations: "Diese Funktion aktiviert Animationen, wenn Sie einen Tiddler öffnen oder schliessen.",
	GenerateAnRssFeed: "Wenn Sie [[RSS-Feed generieren|GenerateAnRssFeed]] aktivieren, speichert TiddlyWiki automatisch einen RSS-2.0-gültigen Feed, so bald Ihr TiddlyWiki gespeichert wird. Der Feed hat den gleichen Dateinamen wie das TiddlyWiki, lediglich jedoch mit der Endung '.xml'.",
	OpenLinksInNewWindow: "Diese Funktion öffnet externe Links in einem neuen ~Browser-Fenster.",
	SaveEmptyTemplate: "Diese Funktion erwirkt, dass beim Abspeichern von Änderungen eine leere Vorlage von TiddlyWiki erzeugt wird. Dies ist als Hilfe gedacht für Entwickler, die Adaptionen von TiddlyWiki bereitstellen. Die Funktion ist nicht erforderlich, wenn Sie ein normaler Benutzer sind.",
	HideEditingFeatures: "Ist diese Funktion aktiviert, werden die Bearbeitungsfunktionen ausgeblendet, wenn das TiddlyWiki über HTTP aufgerufen wird. Der Benutzer hat dann die Möglichkeit, den Tiddler zwar betrachten zu können, aber nicht zu bearbeiten.",
	MinorChanged: "Manchmal ist es sinnvoll, dass bei kleinen Änderungen der Tiddler in der Zeitachse nicht automatisch an den Anfang gesetzt wird. Mit Aktivierung dieser Funktion werden alle Bearbeitungen von Tiddlern als kleine Änderungen betrachtet und das Änderungsdatum nicht geändert.",
	ConfirmBeforeDeleting: "Bei Aktivierung dieser Funktion fordert TiddlyWiki eine Bestätigung des Benutzers an, wenn ein Tiddler gelöscht werden soll."});
}}}
~Standard-Einkaufszettel für Dinge, die immer wieder gekauft werden müssen

* Kaffee
* Tee
* Schrotpatronen Kal. 12/70, 3,5 mm
Steuer 2009
s.a. SteuerUnterlagen

# <<gtdAction "Unterlagen zusammenstellen" "@formalkram">>
# <<gtdAction "Termin vereinbaren" "@formalkram">> Steuerberater, Telefonliste
# <<gtdAction "Termin wahrnehmen" "@formalkram">> inkl. "Nacharbeiten"
# <<gtdAction "Steuerbescheid prüfen" "@formalkram">>

Besonderheiten Steuer 2009:
* bis jetzt keine

<<reminder year:2010 month:5 day:3 title:"Steuer 2009" >>
Steuerunterlagen (... alle Jahre wieder)

* Lohnsteuerbescheinigung Arbeitgeber
* Bescheinigung Zinseinkünfte
* Versicherungen
** Unfallversicherung
** Privathaftpflicht
* ...

[[GTDStyleSheet]]
[[GTDTWStyleSheet]]

/***
!Personal preferences
***/

/*{{{*/
/* make input fields in viewer (options) show up in correct size */
.viewer input { font-size: 0.9em; }

.editor { font-family: monospace; font-size: 10pt; }

/*}}}*/

/*{{{*/

@media print {
#mainMenu, #sidebar, #messageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em 1em;}


/* LAYOUT ELEMENTS ========================================================== */
*
{
 margin: 0;
 padding: 0;
}

body {
 background: #fff;
 color: #000;
 font-size: 6.2pt;
 font-family: "Lucida Grande", "Bitstream Vera Sans", Helvetica, Verdana, Arial, sans-serif;
}

img {
 max-width: 2.2in;
 max-height: 4.3in;
}

#header, #side_container, #storeArea, #copyright, #floater, #messageArea, .save_accesskey, .site_description, #saveTest, .toolbar, .footer
{
 display: none;
}

#tiddlerDisplay, #displayArea
{
 display: inline;
}

.tiddler {
 margin: 0 0 2em 0;
 border-top: 1px solid #000;
 page-break-before: always;
}

.tiddler:first-child {
 page-break-before: avoid;
}

.title {
 font-size: 1.6em;
 font-weight: bold;
 margin-bottom: .3em;
 padding: .2em 0;
 border-bottom: 1px dotted #000;
}

p, blockquote, ul, li, ol, dt, dd, dl, table
{
 margin: 0 0 .3em 0;
}

h1, h2, h3, h4, h5, h6
{
 margin: .2em 0;
} 

h1
{
 font-size: 1.5em;
}

h2
{
 font-size: 1.3em;
}

h3
{
 font-size: 1.25em;
}

h4
{
 font-size: 1.15em;
}

h5
{
 font-size: 1.1em;
}

blockquote
{
 margin: .6em;
 padding-left: .6em;
 border-left: 1px solid #ccc;
}

ul
{
 list-style-type: circle;
}

li
{
 margin: .1em 0 .1em 2em;
 line-height: 1.4em; 
}

table
{
 border-collapse: collapse;
 font-size: 1em;
}

td, th
{
 border: 1px solid #999;
 padding: .2em;
}

hr {
 border: none;
 border-top: dotted 1px #777;
 height: 1px;
 color: #777;
 margin: .6em 0;
}
}
/*}}}*/
|review|k
|!Überfällige Tätigkeiten|!Alle Erinnerungen nächste 7 Tage|
|<<showReminders leadtime:-365...-1 tag:"action !done" format:"DATE: @@color:red;TITLE@@ [ TIDDLER ]">>|<<showReminders leadtime:0...7 tag:"!done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>|
|!Tätigkeiten für heute/morgen|~|
|<<showReminders leadtime:0...1 tag:"action !done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>|~|
|!~Projekt-Übersicht|!~Tätigkeits-Übersicht|
|<<tiddler "Project Review">>|<<tiddler "Action Review">>|
~TW-Artikel für Homepage

# <<gtdAction "Leeres TW erstellen" "@soziales">> mit ~Beispiel-Tätigkeiten und -Projekten
# <<gtdAction "Artikel schreiben" "@soziales">>
# <<gtdAction "Artikel hochladen" "@soziales">>
!! Personen - geschäftlich

|!Person|!Festnetz|!Mobil|!Bemerkung|h
|Heinz Mustermann|123456|+49-170-7654321|Firma XYZ|
|Hannelore Nix|654321|+49-172-3333333|Firma XYZ|

!! Freunde und Bekannte
|!Person|!Festnetz|!Mobil|!Bemerkung|h
|Sigrid Laberbacke|-|+49-172-4444444||


|''URL:''|http://www.tiddlytools.com/|
|''Description:''|TiddlyTools - Small Tools for Big Ideas|
|''Author:''|Eric Shulman|
TiddlyWiki is a free, completely self-contained micro-publishing open source application, wrapped up in a single HTML file. You can find out all about it [[here|http://www.tiddlywiki.com/]].

Being self-contained, the most surprising thing is that, by looking at this site, you have actually downloaded the entire code for TiddlyWiki! Just view the source and see. While viewing a TW application on a web server, you typically cannot make any changes, but by simply saving [[this file|gtd-sample.html]] locally, you now have full control over the content.

Read on for a quick-and-dirty synopsis of the way TiddlyWiki works, but for detailed usage information, please go to the TiddlyWiki site, and browse these useful items:
* [[MainFeatures|http://www.tiddlywiki.com/#MainFeatures]]
* [[Formatting|http://www.tiddlywiki.com/#ExtendedFormatting]]
* [[Downloading|http://www.tiddlywiki.com/#DownloadSoftware]]
* [[SaveChanges|http://www.tiddlywiki.com/#SaveChanges]]

!!TiddlyWiki in ten seconds...
10...TiddlyWiki is a web-based [[wiki|http://en.wikipedia.org/wiki/Wiki]] that has a very rich Javascript runtime built into every page. If you are reading a TiddlyWiki document, you have the //entire// TiddlyWiki application, in addition to all the "articles" that make up the wiki itself.
 9...The "articles" within a TiddlyWiki are called ''tiddlers'', and they are saved with the main HTML page used to view the document. If you open a TW document, you can see all the tiddlers saved at the bottom of the file.
 8...When you view a TW document over the web, you are usually prohibited from making changes. For interactive, modifiable documents like this one, you typically need to save the document locally to your machine and work with it there.
 7...Tiddlers can be referenced by their name but, more importantly, they can be arbitrarily ''tagged'' to categorize them. Tags may be freely modifed, and there are numerous interface widgets within TW to list or find tiddlers by their tags.
 6...When you click on an internal hyperlink to a tiddler (which looks [[like this|TiddlyWiki]]), it will usually open up directly above or below the tiddler you are currently reading and should scroll immediately into view.
 5...When you hover your mouse over a tiddler, a small context-sensitive ''tiddler menu'' appears above and to the right of the tiddler. One of the important items in this menu is ''edit'' (or ''view''), which allows you to view and modify the source for a tiddler.
 4...Tiddler source is a combination of just plain text, plus special formatting commands in ''wiki-text'' that allow you to express style and layout for tiddlers without knowing any HTML.It is important to know that the formatting commands, tiddler menus, and just about everything else can be arbitrarily extended by third-party ''plug-ins'' to create custom solutions like this one.
 3...2...1 That is it in a nutshell, but if you are still feeling a little lost, try this [[tutorial|http://www.blogjones.com/TiddlyWikiTutorial.html]]. Otherwise, dig in to [[GettingStarted]]!
!!Bugs
* printing stylesheet creates an extra blank page before first tiddler
* editing project/context contents should not always force menu to redraw (this closes slider)
** slider state fixed by simply using cookie in nested slider plugin, but still not optimal since menu only needs to be redrawn when context/project is added, renamed, or deleted

!!Past changes
* April 7, 2006
** fixed dirty tiddler bug that prevented recently completed actions from being edited
** added support for optionally hiding old completed actions from action lists
** added support for quick-append of action to a project
* March 30, 2006
** officially converted to TW 2.0.7
** added support for project/action archiving
** [[Someday-Maybe]] was not correctly identified in [[GTDMenu]]
** project review should only display open projects (with incomplete actions) by default
** import/export interface move to [[UpdateApplication]]
** deleted action no longer reappears if it is the last action in project and there is no linefeed after it
** revert to stock ImportTiddlersPlugin as necessary changes have been put into release
* March 28, 2006
** updated GTDStyleSheet to support 3x5 printing
** patched ImportTiddlersPlugin to behave nicely on IE and support application updates
** added support for single-click application updates
* March 24, 2006
** added "projectify" command to action menu, to allow action to be converted to project
** Action Review, by default, now only shows "next" project actions with all non-project actions
** Patched ReminderMacros to correctly filter tiddlers with no tags
* March 22, 2006
** new actions in a project do not show up in project review initially
** renaming an action associated with a project does not work as expected
** abstracted GTD styles to enable easier updates
** [[Reminders]] now filters out completed actions
** missing notification on GTDStyleSheet to get immediate updates of styles
** deleting an action now updates project correctly
* March 20, 2006
** renaming project or context does not update correctly in matching "review" pages
** general sluggishness improved with removal of many unnecessary internal notifications
* March 18, 2006
** Reminders now displays ''all'' events in next 7 days, not just non-actions
** Added DatePlugin to allow integration between reminders and calendar
** fixed closures as potential leak points
** unfile actions for deleted contexts and projects
** support "delete all" for deep delete of projects
** mark an action as done from action view template
** added "new reminder" to footer of action view template
* March 15, 2006
** new project with actions barfs with a Javascript error
** action review should not show empty contexts
** externalize GTD menu items to allow it to be integrated into existing TW

!!Thoughts and "nice to haves"
* should the "single page mode" plugin be installed by default?
* should new project/context menu items be in sidebar menu?
* integration with an external calendar using iCal standard
* should the "Project Review" be a single tiddler, or a dynamically created one that is timestamped?
* extend new action syntax to allow "due date" reminder
* is it necessary for context view to display user name, create/modify dates?
* provide alternate, timed, autosave mechanism to improve performance

If you are connected to the Internet, you can always get the latest version of this application. While it is possible to upgrade using the standard TiddlyWiki import using the backstage area (for which there is an official d-cubed feed, but see the caveats for upgrading using backstage, below), there are ''three better'' ways you can do this:

Click the following button if you simply want to get the latest changes to any of the core tiddlers that make up this application. These tiddlers are tagged "gtd", and updating in this way will not overwrite any of the core tiddlers that you may have changed unless the core tiddlers are even newer than your changes. This is the recommended way to get updates:
**<<importUpdates "http://www.dcubed.ca/d3-update-13.html">>

Click the following button if you would like to get the latest changes to any of the core tiddlers, but to interactively approve each and every updated tiddler as it is loaded into your system. If there are no updated tiddlers, you will not be prompted and the update will exit quietly:
**<<importUpdates "http://www.dcubed.ca/d3-update-13.html" updates "Update interactively" "Click here to interactively update the application" confirm>>

Click the following button if you want to download all of the core tiddlers, regardless of their modification date. Use this to absolutely ensure that you are running with the core application as it was originally written:
**<<importUpdates "http://www.dcubed.ca/d3-update-13.html" all "Update everything" force>>

''For your safety, your file will be saved and a backup file will be automatically generated before any update is performed.''

!!Updating using backstage

There is a feed defined to enable you to update from "backstage". Just select "Official d-cubed feed" from the feed selection list, and import all tiddlers. Be sure to uncheck the "Keep these tiddlers linked..." checkbox before importing.

Also, unless you are importing into an empty d-cubed document, always save a copy before importing into a document that has important stuff.
This system attempts to capture the essence of a [["kinkless" GTD system|http://www.kinkless.com]] using TiddlyWiki. The most important aspect of this effort is to ''minimally'' introduce important "Getting Things Done" features with an interface that is streamlined, intuitive, and clean, without going overboard on "nice to have" plug-ins and experimental features. This application currently assumes that you are familiar with TiddlyWiki, so if you are completely new to this environment, then please click [[here|TiddlyWiki]]. 

While every effort has been made to make this system usable right "out of the box", please understand that it is a work-in-progress. Feedback is very welcome at [[GTD Tiddly Wiki|http://groups.google.com/group/GTD-TiddlyWiki]].

Now on to getting started.
/***
|''Name:''|YourSearchPlugin|
|''Version:''|2.1.3 (2008-04-16)|
|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2008 [[abego Software|http://www.abego-software.de]]|
|''~CoreVersion:''|2.1.0|
|''Community:''|[[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23YourSearchPlugin]]|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; ~InternetExplorer 6.0|
!About YourSearch
YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!

For more information see [[Help|YourSearch Help]].
!Compatibility
This plugin requires TiddlyWiki 2.1. 
Check the [[archive|http://tiddlywiki.abego-software.de/archive]] for ~YourSearchPlugins supporting older versions of TiddlyWiki.
!Source Code
***/
/***
This plugin's source code is compressed (and hidden). Use this [[link|http://tiddlywiki.abego-software.de/archive/YourSearchPlugin/Plugin-YourSearch-src.2.1.3.js]] to get the readable source code.
***/
///%
if(!version.extensions.YourSearchPlugin){version.extensions.YourSearchPlugin={major:2,minor:1,revision:3,source:"http://tiddlywiki.abego-software.de/#YourSearchPlugin",licence:"[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",copyright:"Copyright (c) abego Software GmbH, 2005-2008 (www.abego-software.de)"};if(!window.abego){window.abego={};}
if(!Array.forEach){Array.forEach=function(_1,_2,_3){for(var i=0,len=_1.length;i<len;i++){_2.call(_3,_1[i],i,_1);}};Array.prototype.forEach=function(_5,_6){for(var i=0,len=this.length;i<len;i++){_5.call(_6,this[i],i,this);}};}
abego.toInt=function(s,_9){if(!s){return _9;}
var n=parseInt(s);return(n==NaN)?_9:n;};abego.createEllipsis=function(_b){var e=createTiddlyElement(_b,"span");e.innerHTML="&hellip;";};abego.shallowCopy=function(_d){if(!_d){return _d;}
var _e={};for(var n in _d){_e[n]=_d[n];}
return _e;};abego.copyOptions=function(_10){return!_10?{}:abego.shallowCopy(_10);};abego.countStrings=function(_11,s){if(!s){return 0;}
var len=s.length;var n=0;var _15=0;while(1){var i=_11.indexOf(s,_15);if(i<0){return n;}
n++;_15=i+len;}
return n;};abego.getBracedText=function(_17,_18,_19){if(!_18){_18=0;}
var re=/\{([^\}]*)\}/gm;re.lastIndex=_18;var m=re.exec(_17);if(m){var s=m[1];var _1d=abego.countStrings(s,"{");if(!_1d){if(_19){_19.lastIndex=re.lastIndex;}
return s;}
var len=_17.length;for(var i=re.lastIndex;i<len&&_1d;i++){var c=_17.charAt(i);if(c=="{"){_1d++;}else{if(c=="}"){_1d--;}}}
if(!_1d){if(_19){_19.lastIndex=i-1;}
return _17.substring(m.index+1,i-1);}}};abego.select=function(_21,_22,_23,_24){if(!_24){_24=[];}
_21.forEach(function(t){if(_22.call(_23,t)){_24.push(t);}});return _24;};abego.consumeEvent=function(e){if(e.stopPropagation){e.stopPropagation();}
if(e.preventDefault){e.preventDefault();}
e.cancelBubble=true;e.returnValue=true;};abego.TiddlerFilterTerm=function(_27,_28){if(!_28){_28={};}
var _29=_27;if(!_28.textIsRegExp){_29=_27.escapeRegExp();if(_28.fullWordMatch){_29="\\b"+_29+"\\b";}}
var _2a=new RegExp(_29,"m"+(_28.caseSensitive?"":"i"));this.tester=new abego.MultiFieldRegExpTester(_2a,_28.fields,_28.withExtendedFields);};abego.TiddlerFilterTerm.prototype.test=function(_2b){return this.tester.test(_2b);};abego.parseNewTiddlerCommandLine=function(s){var m=/(.*?)\.(?:\s+|$)([^#]*)(#.*)?/.exec(s);if(!m){m=/([^#]*)()(#.*)?/.exec(s);}
if(m){var r;if(m[3]){var s2=m[3].replace(/#/g,"");r=s2.parseParams("tag");}else{r=[[]];}
var _30=m[2]?m[2].trim():"";r.push({name:"text",value:_30});r[0].text=[_30];return{title:m[1].trim(),params:r};}else{return{title:s.trim(),params:[[]]};}};abego.parseTiddlerFilterTerm=function(_31,_32,_33){var re=/\s*(?:(?:\{([^\}]*)\})|(?:(=)|([#%!])|(?:(\w+)\s*\:(?!\/\/))|(?:(?:("(?:(?:\\")|[^"])+")|(?:\/((?:(?:\\\/)|[^\/])+)\/)|(\w+\:\/\/[^\s]+)|([^\s\)\-\"]+)))))/mg;var _35={"!":"title","%":"text","#":"tags"};var _36={};var _37;re.lastIndex=_32;while(1){var i=re.lastIndex;var m=re.exec(_31);if(!m||m.index!=i){throw"Word or String literal expected";}
if(m[1]){var _3a={};var _3b=abego.getBracedText(_31,0,_3a);if(!_3b){throw"Invalid {...} syntax";}
var f=Function("tiddler","return ("+_3b+");");return{func:f,lastIndex:_3a.lastIndex,markRE:null};}
if(m[2]){_37=true;}else{if(m[3]){_36[_35[m[3]]]=1;}else{if(m[4]){_36[m[4]]=1;}else{var _3d=m[6];var _3e=m[5]?window.eval(m[5]):m[6]?m[6]:m[7]?m[7]:m[8];var _33=abego.copyOptions(_33);_33.fullWordMatch=_37;_33.textIsRegExp=_3d;var _3f=[];for(var n in _36){_3f.push(n);}
if(_3f.length==0){_33.fields=_33.defaultFields;}else{_33.fields=_3f;_33.withExtendedFields=false;}
var _41=new abego.TiddlerFilterTerm(_3e,_33);var _42=_3d?_3e:_3e.escapeRegExp();if(_42&&_37){_42="\\b"+_42+"\\b";}
return{func:function(_43){return _41.test(_43);},lastIndex:re.lastIndex,markRE:_42?"(?:"+_42+")":null};}}}}};abego.BoolExp=function(s,_45,_46){this.s=s;var _47=_46&&_46.defaultOperationIs_OR;var _48=/\s*(?:(\-|not)|(\())/gi;var _49=/\s*\)/g;var _4a=/\s*(?:(and|\&\&)|(or|\|\|))/gi;var _4b=/\s*[^\)\s]/g;var _4c=/\s*(\-|not)?(\s*\()?/gi;var _4d;var _4e=function(_4f){_4c.lastIndex=_4f;var m=_4c.exec(s);var _51;var _52;if(m&&m.index==_4f){_4f+=m[0].length;_51=m[1];if(m[2]){var e=_4d(_4f);_49.lastIndex=e.lastIndex;if(!_49.exec(s)){throw"Missing ')'";}
_52={func:e.func,lastIndex:_49.lastIndex,markRE:e.markRE};}}
if(!_52){_52=_45(s,_4f,_46);}
if(_51){_52.func=(function(f){return function(_55){return!f(_55);};})(_52.func);_52.markRE=null;}
return _52;};_4d=function(_56){var _57=_4e(_56);while(1){var l=_57.lastIndex;_4a.lastIndex=l;var m=_4a.exec(s);var _5a;var _5b;if(m&&m.index==l){_5a=!m[1];_5b=_4e(_4a.lastIndex);}else{try{_5b=_4e(l);}
catch(e){return _57;}
_5a=_47;}
_57.func=(function(_5c,_5d,_5e){return _5e?function(_5f){return _5c(_5f)||_5d(_5f);}:function(_60){return _5c(_60)&&_5d(_60);};})(_57.func,_5b.func,_5a);_57.lastIndex=_5b.lastIndex;if(!_57.markRE){_57.markRE=_5b.markRE;}else{if(_5b.markRE){_57.markRE=_57.markRE+"|"+_5b.markRE;}}}};var _61=_4d(0);this.evalFunc=_61.func;if(_61.markRE){this.markRegExp=new RegExp(_61.markRE,_46.caseSensitive?"mg":"img");}};abego.BoolExp.prototype.exec=function(){return this.evalFunc.apply(this,arguments);};abego.BoolExp.prototype.getMarkRegExp=function(){return this.markRegExp;};abego.BoolExp.prototype.toString=function(){return this.s;};abego.MultiFieldRegExpTester=function(re,_63,_64){this.re=re;this.fields=_63?_63:["title","text","tags"];this.withExtendedFields=_64;};abego.MultiFieldRegExpTester.prototype.test=function(_65){var re=this.re;for(var i=0;i<this.fields.length;i++){var s=store.getValue(_65,this.fields[i]);if(typeof s=="string"&&re.test(s)){return this.fields[i];}}
if(this.withExtendedFields){return store.forEachField(_65,function(_69,_6a,_6b){return typeof _6b=="string"&&re.test(_6b)?_6a:null;},true);}
return null;};abego.TiddlerQuery=function(_6c,_6d,_6e,_6f,_70){if(_6e){this.regExp=new RegExp(_6c,_6d?"mg":"img");this.tester=new abego.MultiFieldRegExpTester(this.regExp,_6f,_70);}else{this.expr=new abego.BoolExp(_6c,abego.parseTiddlerFilterTerm,{defaultFields:_6f,caseSensitive:_6d,withExtendedFields:_70});}
this.getQueryText=function(){return _6c;};this.getUseRegExp=function(){return _6e;};this.getCaseSensitive=function(){return _6d;};this.getDefaultFields=function(){return _6f;};this.getWithExtendedFields=function(){return _70;};};abego.TiddlerQuery.prototype.test=function(_71){if(!_71){return false;}
if(this.regExp){return this.tester.test(_71);}
return this.expr.exec(_71);};abego.TiddlerQuery.prototype.filter=function(_72){return abego.select(_72,this.test,this);};abego.TiddlerQuery.prototype.getMarkRegExp=function(){if(this.regExp){return"".search(this.regExp)>=0?null:this.regExp;}
return this.expr.getMarkRegExp();};abego.TiddlerQuery.prototype.toString=function(){return(this.regExp?this.regExp:this.expr).toString();};abego.PageWiseRenderer=function(){this.firstIndexOnPage=0;};merge(abego.PageWiseRenderer.prototype,{setItems:function(_73){this.items=_73;this.setFirstIndexOnPage(0);},getMaxPagesInNavigation:function(){return 10;},getItemsCount:function(_74){return this.items?this.items.length:0;},getCurrentPageIndex:function(){return Math.floor(this.firstIndexOnPage/this.getItemsPerPage());},getLastPageIndex:function(){return Math.floor((this.getItemsCount()-1)/this.getItemsPerPage());},setFirstIndexOnPage:function(_75){this.firstIndexOnPage=Math.min(Math.max(0,_75),this.getItemsCount()-1);},getFirstIndexOnPage:function(){this.firstIndexOnPage=Math.floor(this.firstIndexOnPage/this.getItemsPerPage())*this.getItemsPerPage();return this.firstIndexOnPage;},getLastIndexOnPage:function(){return Math.min(this.getFirstIndexOnPage()+this.getItemsPerPage()-1,this.getItemsCount()-1);},onPageChanged:function(_76,_77){},renderPage:function(_78){if(_78.beginRendering){_78.beginRendering(this);}
try{if(this.getItemsCount()){var _79=this.getLastIndexOnPage();var _7a=-1;for(var i=this.getFirstIndexOnPage();i<=_79;i++){_7a++;_78.render(this,this.items[i],i,_7a);}}}
finally{if(_78.endRendering){_78.endRendering(this);}}},addPageNavigation:function(_7c){if(!this.getItemsCount()){return;}
var _7d=this;var _7e=function(e){if(!e){var e=window.event;}
abego.consumeEvent(e);var _80=abego.toInt(this.getAttribute("page"),0);var _81=_7d.getCurrentPageIndex();if(_80==_81){return;}
var _82=_80*_7d.getItemsPerPage();_7d.setFirstIndexOnPage(_82);_7d.onPageChanged(_80,_81);};var _83;var _84=this.getCurrentPageIndex();var _85=this.getLastPageIndex();if(_84>0){_83=createTiddlyButton(_7c,"Previous","Go to previous page (Shortcut: Alt-'<')",_7e,"prev");_83.setAttribute("page",(_84-1).toString());_83.setAttribute("accessKey","<");}
for(var i=-this.getMaxPagesInNavigation();i<this.getMaxPagesInNavigation();i++){var _87=_84+i;if(_87<0){continue;}
if(_87>_85){break;}
var _88=(i+_84+1).toString();var _89=_87==_84?"currentPage":"otherPage";_83=createTiddlyButton(_7c,_88,"Go to page %0".format([_88]),_7e,_89);_83.setAttribute("page",(_87).toString());}
if(_84<_85){_83=createTiddlyButton(_7c,"Next","Go to next page (Shortcut: Alt-'>')",_7e,"next");_83.setAttribute("page",(_84+1).toString());_83.setAttribute("accessKey",">");}}});abego.LimitedTextRenderer=function(){var _8a=40;var _8b=4;var _8c=function(_8d,_8e,_8f){var n=_8d.length;if(n==0){_8d.push({start:_8e,end:_8f});return;}
var i=0;for(;i<n;i++){var _92=_8d[i];if(_92.start<=_8f&&_8e<=_92.end){var r;var _94=i+1;for(;_94<n;_94++){r=_8d[_94];if(r.start>_8f||_8e>_92.end){break;}}
var _95=_8e;var _96=_8f;for(var j=i;j<_94;j++){r=_8d[j];_95=Math.min(_95,r.start);_96=Math.max(_96,r.end);}
_8d.splice(i,_94-i,{start:_95,end:_96});return;}
if(_92.start>_8f){break;}}
_8d.splice(i,0,{start:_8e,end:_8f});};var _98=function(_99){var _9a=0;for(var i=0;i<_99.length;i++){var _9c=_99[i];_9a+=_9c.end-_9c.start;}
return _9a;};var _9d=function(c){return(c>="a"&&c<="z")||(c>="A"&&c<="Z")||c=="_";};var _9f=function(s,_a1){if(!_9d(s[_a1])){return null;}
for(var i=_a1-1;i>=0&&_9d(s[i]);i--){}
var _a3=i+1;var n=s.length;for(i=_a1+1;i<n&&_9d(s[i]);i++){}
return{start:_a3,end:i};};var _a5=function(s,_a7,_a8){var _a9;if(_a8){_a9=_9f(s,_a7);}else{if(_a7<=0){return _a7;}
_a9=_9f(s,_a7-1);}
if(!_a9){return _a7;}
if(_a8){if(_a9.start>=_a7-_8b){return _a9.start;}
if(_a9.end<=_a7+_8b){return _a9.end;}}else{if(_a9.end<=_a7+_8b){return _a9.end;}
if(_a9.start>=_a7-_8b){return _a9.start;}}
return _a7;};var _aa=function(s,_ac){var _ad=[];if(_ac){var _ae=0;var n=s.length;var _b0=0;do{_ac.lastIndex=_ae;var _b1=_ac.exec(s);if(_b1){if(_ae<_b1.index){var t=s.substring(_ae,_b1.index);_ad.push({text:t});}
_ad.push({text:_b1[0],isMatch:true});_ae=_b1.index+_b1[0].length;}else{_ad.push({text:s.substr(_ae)});break;}}while(true);}else{_ad.push({text:s});}
return _ad;};var _b3=function(_b4){var _b5=0;for(var i=0;i<_b4.length;i++){if(_b4[i].isMatch){_b5++;}}
return _b5;};var _b7=function(s,_b9,_ba,_bb,_bc){var _bd=Math.max(Math.floor(_bc/(_bb+1)),_8a);var _be=Math.max(_bd-(_ba-_b9),0);var _bf=Math.min(Math.floor(_ba+_be/3),s.length);var _c0=Math.max(_bf-_bd,0);_c0=_a5(s,_c0,true);_bf=_a5(s,_bf,false);return{start:_c0,end:_bf};};var _c1=function(_c2,s,_c4){var _c5=[];var _c6=_b3(_c2);var pos=0;for(var i=0;i<_c2.length;i++){var t=_c2[i];var _ca=t.text;if(t.isMatch){var _cb=_b7(s,pos,pos+_ca.length,_c6,_c4);_8c(_c5,_cb.start,_cb.end);}
pos+=_ca.length;}
return _c5;};var _cc=function(s,_ce,_cf){var _d0=_cf-_98(_ce);while(_d0>0){if(_ce.length==0){_8c(_ce,0,_a5(s,_cf,false));return;}else{var _d1=_ce[0];var _d2;var _d3;if(_d1.start==0){_d2=_d1.end;if(_ce.length>1){_d3=_ce[1].start;}else{_8c(_ce,_d2,_a5(s,_d2+_d0,false));return;}}else{_d2=0;_d3=_d1.start;}
var _d4=Math.min(_d3,_d2+_d0);_8c(_ce,_d2,_d4);_d0-=(_d4-_d2);}}};var _d5=function(_d6,s,_d8,_d9,_da){if(_d9.length==0){return;}
var _db=function(_dc,s,_de,_df,_e0){var t;var _e2;var pos=0;var i=0;var _e5=0;for(;i<_de.length;i++){t=_de[i];_e2=t.text;if(_df<pos+_e2.length){_e5=_df-pos;break;}
pos+=_e2.length;}
var _e6=_e0-_df;for(;i<_de.length&&_e6>0;i++){t=_de[i];_e2=t.text.substr(_e5);_e5=0;if(_e2.length>_e6){_e2=_e2.substr(0,_e6);}
if(t.isMatch){createTiddlyElement(_dc,"span",null,"marked",_e2);}else{createTiddlyText(_dc,_e2);}
_e6-=_e2.length;}
if(_e0<s.length){abego.createEllipsis(_dc);}};if(_d9[0].start>0){abego.createEllipsis(_d6);}
var _e7=_da;for(var i=0;i<_d9.length&&_e7>0;i++){var _e9=_d9[i];var len=Math.min(_e9.end-_e9.start,_e7);_db(_d6,s,_d8,_e9.start,_e9.start+len);_e7-=len;}};this.render=function(_eb,s,_ed,_ee){if(s.length<_ed){_ed=s.length;}
var _ef=_aa(s,_ee);var _f0=_c1(_ef,s,_ed);_cc(s,_f0,_ed);_d5(_eb,s,_ef,_f0,_ed);};};(function(){function alertAndThrow(msg){alert(msg);throw msg;}
if(version.major<2||(version.major==2&&version.minor<1)){alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.1 or newer.\n\nCheck the archive for YourSearch plugins\nsupporting older versions of TiddlyWiki.\n\nArchive: http://tiddlywiki.abego-software.de/archive");}
abego.YourSearch={};var _f2;var _f3;var _f4=function(_f5){_f2=_f5;};var _f6=function(){return _f2?_f2:[];};var _f7=function(){return _f2?_f2.length:0;};var _f8=4;var _f9=10;var _fa=2;var _fb=function(s,re){var m=s.match(re);return m?m.length:0;};var _ff=function(_100,_101){var _102=_101.getMarkRegExp();if(!_102){return 1;}
var _103=_100.title.match(_102);var _104=_103?_103.length:0;var _105=_fb(_100.getTags(),_102);var _106=_103?_103.join("").length:0;var _107=_100.title.length>0?_106/_100.title.length:0;var rank=_104*_f8+_105*_fa+_107*_f9+1;return rank;};var _109=function(_10a,_10b,_10c,_10d,_10e,_10f){_f3=null;var _110=_10a.reverseLookup("tags",_10f,false);try{var _111=[];if(config.options.chkSearchInTitle){_111.push("title");}
if(config.options.chkSearchInText){_111.push("text");}
if(config.options.chkSearchInTags){_111.push("tags");}
_f3=new abego.TiddlerQuery(_10b,_10c,_10d,_111,config.options.chkSearchExtendedFields);}
catch(e){return[];}
var _112=_f3.filter(_110);var _113=abego.YourSearch.getRankFunction();for(var i=0;i<_112.length;i++){var _115=_112[i];var rank=_113(_115,_f3);_115.searchRank=rank;}
if(!_10e){_10e="title";}
var _117=function(a,b){var _11a=a.searchRank-b.searchRank;if(_11a==0){if(a[_10e]==b[_10e]){return(0);}else{return(a[_10e]<b[_10e])?-1:+1;}}else{return(_11a>0)?-1:+1;}};_112.sort(_117);return _112;};var _11b=80;var _11c=50;var _11d=250;var _11e=50;var _11f=25;var _120=10;var _121="yourSearchResult";var _122="yourSearchResultItems";var _123;var _124;var _125;var _126;var _127;var _128=function(){if(version.extensions.YourSearchPlugin.styleSheetInited){return;}
version.extensions.YourSearchPlugin.styleSheetInited=true;setStylesheet(store.getTiddlerText("YourSearchStyleSheet"),"yourSearch");};var _129=function(){return _124!=null&&_124.parentNode==document.body;};var _12a=function(){if(_129()){document.body.removeChild(_124);}};var _12b=function(e){_12a();var _12d=this.getAttribute("tiddlyLink");if(_12d){var _12e=this.getAttribute("withHilite");var _12f=highlightHack;if(_12e&&_12e=="true"&&_f3){highlightHack=_f3.getMarkRegExp();}
story.displayTiddler(this,_12d);highlightHack=_12f;}
return(false);};var _130=function(){if(!_125){return;}
var root=_125;var _132=findPosX(root);var _133=findPosY(root);var _134=root.offsetHeight;var _135=_132;var _136=_133+_134;var _137=findWindowWidth();if(_137<_124.offsetWidth){_124.style.width=(_137-100)+"px";_137=findWindowWidth();}
var _138=_124.offsetWidth;if(_135+_138>_137){_135=_137-_138-30;}
if(_135<0){_135=0;}
_124.style.left=_135+"px";_124.style.top=_136+"px";_124.style.display="block";};var _139=function(){if(_124){window.scrollTo(0,ensureVisible(_124));}
if(_125){window.scrollTo(0,ensureVisible(_125));}};var _13a=function(){_130();_139();};var _13b;var _13c;var _13d=new abego.PageWiseRenderer();var _13e=function(_13f){this.itemHtml=store.getTiddlerText("YourSearchItemTemplate");if(!this.itemHtml){alertAndThrow("YourSearchItemTemplate not found");}
this.place=document.getElementById(_122);if(!this.place){this.place=createTiddlyElement(_13f,"div",_122);}};merge(_13e.prototype,{render:function(_140,_141,_142,_143){_13b=_143;_13c=_141;var item=createTiddlyElement(this.place,"div",null,"yourSearchItem");item.innerHTML=this.itemHtml;applyHtmlMacros(item,null);refreshElements(item,null);},endRendering:function(_145){_13c=null;}});var _146=function(){if(!_124||!_125){return;}
var html=store.getTiddlerText("YourSearchResultTemplate");if(!html){html="<b>Tiddler YourSearchResultTemplate not found</b>";}
_124.innerHTML=html;applyHtmlMacros(_124,null);refreshElements(_124,null);var _148=new _13e(_124);_13d.renderPage(_148);_13a();};_13d.getItemsPerPage=function(){var n=(config.options.chkPreviewText)?abego.toInt(config.options.txtItemsPerPageWithPreview,_120):abego.toInt(config.options.txtItemsPerPage,_11f);return(n>0)?n:1;};_13d.onPageChanged=function(){_146();};var _14a=function(){if(_125==null||!config.options.chkUseYourSearch){return;}
if((_125.value==_123)&&_123&&!_129()){if(_124&&(_124.parentNode!=document.body)){document.body.appendChild(_124);_13a();}else{abego.YourSearch.onShowResult(true);}}};var _14b=function(){_12a();_124=null;_123=null;};var _14c=function(self,e){while(e!=null){if(self==e){return true;}
e=e.parentNode;}
return false;};var _14f=function(e){if(e.target==_125){return;}
if(e.target==_126){return;}
if(_124&&_14c(_124,e.target)){return;}
_12a();};var _151=function(e){if(e.keyCode==27){_12a();}};addEvent(document,"click",_14f);addEvent(document,"keyup",_151);var _153=function(text,_155,_156){_123=text;_f4(_109(store,text,_155,_156,"title","excludeSearch"));abego.YourSearch.onShowResult();};var _157=function(_158,_159,_15a,_15b,_15c,_15d){_128();_123="";var _15e=null;var _15f=function(txt){if(config.options.chkUseYourSearch){_153(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}else{story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}
_123=txt.value;};var _161=function(e){_15f(_125);return false;};var _163=function(e){if(!e){var e=window.event;}
_125=this;switch(e.keyCode){case 13:if(e.ctrlKey&&_127&&_129()){_127.onclick.apply(_127,[e]);}else{_15f(this);}
break;case 27:if(_129()){_12a();}else{this.value="";clearMessage();}
break;}
if(String.fromCharCode(e.keyCode)==this.accessKey||e.altKey){_14a();}
if(this.value.length<3&&_15e){clearTimeout(_15e);}
if(this.value.length>2){if(this.value!=_123){if(!config.options.chkUseYourSearch||config.options.chkSearchAsYouType){if(_15e){clearTimeout(_15e);}
var txt=this;_15e=setTimeout(function(){_15f(txt);},500);}}else{if(_15e){clearTimeout(_15e);}}}
if(this.value.length==0){_12a();}};var _166=function(e){this.select();clearMessage();_14a();};var args=_15c.parseParams("list",null,true);var _169=getFlag(args,"buttonAtRight");var _16a=getParam(args,"sizeTextbox",this.sizeTextbox);var btn;if(!_169){btn=createTiddlyButton(_158,this.label,this.prompt,_161);}
var txt=createTiddlyElement(_158,"input",null,null,null);if(_15a[0]){txt.value=_15a[0];}
txt.onkeyup=_163;txt.onfocus=_166;txt.setAttribute("size",_16a);txt.setAttribute("accessKey",this.accessKey);txt.setAttribute("autocomplete","off");if(config.browser.isSafari){txt.setAttribute("type","search");txt.setAttribute("results","5");}else{txt.setAttribute("type","text");}
if(_169){btn=createTiddlyButton(_158,this.label,this.prompt,_161);}
_125=txt;_126=btn;};var _16d=function(){_12a();var _16e=_f6();var n=_16e.length;if(n){var _170=[];for(var i=0;i<n;i++){_170.push(_16e[i].title);}
story.displayTiddlers(null,_170);}};var _172=function(_173,_174,_175,_176){invokeMacro(_173,"option",_174,_175,_176);var elem=_173.lastChild;var _178=elem.onclick;elem.onclick=function(e){var _17a=_178.apply(this,arguments);_146();return _17a;};return elem;};var _17b=function(s){var _17d=["''","{{{","}}}","//","<<<","/***","***/"];var _17e="";for(var i=0;i<_17d.length;i++){if(i!=0){_17e+="|";}
_17e+="("+_17d[i].escapeRegExp()+")";}
return s.replace(new RegExp(_17e,"mg"),"").trim();};var _180=function(){var i=_13b;return(i>=0&&i<=9)?(i<9?(i+1):0):-1;};var _182=new abego.LimitedTextRenderer();var _183=function(_184,s,_186){_182.render(_184,s,_186,_f3.getMarkRegExp());};var _187=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_188,_189,_18a,_18b,_18c,tags,_18e){_187.apply(this,arguments);_14b();};var _18f=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_190){_18f.apply(this,arguments);_14b();};config.macros.yourSearch={label:"yourSearch",prompt:"Gives access to the current/last YourSearch result",handler:function(_191,_192,_193,_194,_195,_196){if(_193.length==0){return;}
var name=_193[0];var func=config.macros.yourSearch.funcs[name];if(func){func(_191,_192,_193,_194,_195,_196);}},tests:{"true":function(){return true;},"false":function(){return false;},"found":function(){return _f7()>0;},"previewText":function(){return config.options.chkPreviewText;}},funcs:{itemRange:function(_199){if(_f7()){var _19a=_13d.getLastIndexOnPage();var s="%0 - %1".format([_13d.getFirstIndexOnPage()+1,_19a+1]);createTiddlyText(_199,s);}},count:function(_19c){createTiddlyText(_19c,_f7().toString());},query:function(_19d){if(_f3){createTiddlyText(_19d,_f3.toString());}},version:function(_19e){var t="YourSearch %0.%1.%2".format([version.extensions.YourSearchPlugin.major,version.extensions.YourSearchPlugin.minor,version.extensions.YourSearchPlugin.revision]);var e=createTiddlyElement(_19e,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#YourSearchPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_1a1){var e=createTiddlyElement(_1a1,"a");e.setAttribute("href","http://www.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2005-2008 <b><font color=\"red\">abego</font></b> Software<font>";},newTiddlerButton:function(_1a3){if(_f3){var r=abego.parseNewTiddlerCommandLine(_f3.getQueryText());var btn=config.macros.newTiddler.createNewTiddlerButton(_1a3,r.title,r.params,"new tiddler","Create a new tiddler based on search text. (Shortcut: Ctrl-Enter; Separators: '.', '#')",null,"text");var _1a6=btn.onclick;btn.onclick=function(){_12a();_1a6.apply(this,arguments);};_127=btn;}},linkButton:function(_1a7,_1a8,_1a9,_1aa,_1ab,_1ac){if(_1a9<2){return;}
var _1ad=_1a9[1];var text=_1a9<3?_1ad:_1a9[2];var _1af=_1a9<4?text:_1a9[3];var _1b0=_1a9<5?null:_1a9[4];var btn=createTiddlyButton(_1a7,text,_1af,_12b,null,null,_1b0);btn.setAttribute("tiddlyLink",_1ad);},closeButton:function(_1b2,_1b3,_1b4,_1b5,_1b6,_1b7){var _1b8=createTiddlyButton(_1b2,"close","Close the Search Results (Shortcut: ESC)",_12a);},openAllButton:function(_1b9,_1ba,_1bb,_1bc,_1bd,_1be){var n=_f7();if(n==0){return;}
var _1c0=n==1?"open tiddler":"open all %0 tiddlers".format([n]);var _1c1=createTiddlyButton(_1b9,_1c0,"Open all found tiddlers (Shortcut: Alt-O)",_16d);_1c1.setAttribute("accessKey","O");},naviBar:function(_1c2,_1c3,_1c4,_1c5,_1c6,_1c7){_13d.addPageNavigation(_1c2);},"if":function(_1c8,_1c9,_1ca,_1cb,_1cc,_1cd){if(_1ca.length<2){return;}
var _1ce=_1ca[1];var _1cf=(_1ce=="not");if(_1cf){if(_1ca.length<3){return;}
_1ce=_1ca[2];}
var test=config.macros.yourSearch.tests[_1ce];var _1d1=false;try{if(test){_1d1=test(_1c8,_1c9,_1ca,_1cb,_1cc,_1cd)!=_1cf;}else{_1d1=(!eval(_1ce))==_1cf;}}
catch(ex){}
if(!_1d1){_1c8.style.display="none";}},chkPreviewText:function(_1d2,_1d3,_1d4,_1d5,_1d6,_1d7){var _1d8=_1d4.slice(1).join(" ");var elem=_172(_1d2,"chkPreviewText",_1d5,_1d7);elem.setAttribute("accessKey","P");elem.title="Show text preview of found tiddlers (Shortcut: Alt-P)";return elem;}}};config.macros.foundTiddler={label:"foundTiddler",prompt:"Provides information on the tiddler currently processed on the YourSearch result page",handler:function(_1da,_1db,_1dc,_1dd,_1de,_1df){var name=_1dc[0];var func=config.macros.foundTiddler.funcs[name];if(func){func(_1da,_1db,_1dc,_1dd,_1de,_1df);}},funcs:{title:function(_1e2,_1e3,_1e4,_1e5,_1e6,_1e7){if(!_13c){return;}
var _1e8=_180();var _1e9=_1e8>=0?"Open tiddler (Shortcut: Alt-%0)".format([_1e8.toString()]):"Open tiddler";var btn=createTiddlyButton(_1e2,null,_1e9,_12b,null);btn.setAttribute("tiddlyLink",_13c.title);btn.setAttribute("withHilite","true");_183(btn,_13c.title,_11b);if(_1e8>=0){btn.setAttribute("accessKey",_1e8.toString());}},tags:function(_1eb,_1ec,_1ed,_1ee,_1ef,_1f0){if(!_13c){return;}
_183(_1eb,_13c.getTags(),_11c);},text:function(_1f1,_1f2,_1f3,_1f4,_1f5,_1f6){if(!_13c){return;}
_183(_1f1,_17b(_13c.text),_11d);},field:function(_1f7,_1f8,_1f9,_1fa,_1fb,_1fc){if(!_13c){return;}
var name=_1f9[1];var len=_1f9.length>2?abego.toInt(_1f9[2],_11e):_11e;var v=store.getValue(_13c,name);if(v){_183(_1f7,_17b(v),len);}},number:function(_200,_201,_202,_203,_204,_205){var _206=_180();if(_206>=0){var text="%0)".format([_206.toString()]);createTiddlyElement(_200,"span",null,"shortcutNumber",text);}}}};var opts={chkUseYourSearch:true,chkPreviewText:true,chkSearchAsYouType:true,chkSearchInTitle:true,chkSearchInText:true,chkSearchInTags:true,chkSearchExtendedFields:true,txtItemsPerPage:_11f,txtItemsPerPageWithPreview:_120};for(var n in opts){if(config.options[n]==undefined){config.options[n]=opts[n];}}
config.shadowTiddlers.AdvancedOptions+="\n<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]]) ([[help|YourSearch Help]])// ";config.shadowTiddlers["YourSearch Help"]="!Field Search\nWith the Field Search you can restrict your search to certain fields of a tiddler, e.g"+" only search the tags or only the titles. The general form is //fieldname//'':''//textToSearch// (e."+"g. {{{title:intro}}}). In addition one-character shortcuts are also supported for the standard field"+"s {{{title}}}, {{{text}}} and {{{tags}}}:\n|!What you want|!What you type|!Example|\n|Search ''titles "+"only''|start word with ''!''|{{{!jonny}}} (shortcut for {{{title:jonny}}})|\n|Search ''contents/text "+"only''|start word with ''%''|{{{%football}}} (shortcut for {{{text:football}}})|\n|Search ''tags only"+"''|start word with ''#''|{{{#Plugin}}} (shortcut for {{{tags:Plugin}}})|\n\nUsing this feature you may"+" also search the extended fields (\"Metadata\") introduced with TiddlyWiki 2.1, e.g. use {{{priority:1"+"}}} to find all tiddlers with the priority field set to \"1\".\n\nYou may search a word in more than one"+" field. E.g. {{{!#Plugin}}} (or {{{title:tags:Plugin}}} in the \"long form\") finds tiddlers containin"+"g \"Plugin\" either in the title or in the tags (but does not look for \"Plugin\" in the text). \n\n!Boole"+"an Search\nThe Boolean Search is useful when searching for multiple words.\n|!What you want|!What you "+"type|!Example|\n|''All words'' must exist|List of words|{{{jonny jeremy}}} (or {{{jonny and jeremy}}}"+")|\n|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\n|A word ''must "+"not exist''|Start word with ''-''|{{{-jonny}}} (or {{{not jonny}}})|\n\n''Note:'' When you specify two"+" words, separated with a space, YourSearch finds all tiddlers that contain both words, but not neces"+"sarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need"+" to put the words into quotes. I.e. you type: {{{\"john brown\"}}}.\n\nUsing parenthesis you may change "+"the default \"left to right\" evaluation of the boolean search. E.g. {{{not (jonny or jeremy)}}} finds"+" all tiddlers that contain neither \"jonny\" nor \"jeremy. In contrast to this {{{not jonny or jeremy}}"+"} (i.e. without parenthesis) finds all tiddlers that either don't contain \"jonny\" or that contain \"j"+"eremy\".\n\n!'Exact Word' Search\nBy default a search result all matches that 'contain' the searched tex"+"t. E.g. if you search for {{{Task}}} you will get all tiddlers containing 'Task', but also '~Complet"+"edTask', '~TaskForce' etc.\n\nIf you only want to get the tiddlers that contain 'exactly the word' you"+" need to prefix it with a '='. E.g. typing '=Task' will find the tiddlers that contain the word 'Tas"+"k', ignoring words that just contain 'Task' as a substring.\n\n!~CaseSensitiveSearch and ~RegExpSearch"+"\nThe standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearc"+"h. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\n\nIn addition you m"+"ay do a \"regular expression\" search even with the ''~RegExpSearch'' set to false by directly enterin"+"g the regular expression into the search field, framed with {{{/.../}}}. \n\nExample: {{{/m[ae][iy]er/"+"}}} will find all tiddlers that contain either \"maier\", \"mayer\", \"meier\" or \"meyer\".\n\n!~JavaScript E"+"xpression Filtering\nIf you are familiar with JavaScript programming and know some TiddlyWiki interna"+"ls you may also use JavaScript expression for the search. Just enter a JavaScript boolean expression"+" into the search field, framed with {{{ { ... } }}}. In the code refer to the variable tiddler and e"+"valuate to {{{true}}} when the given tiddler should be included in the result. \n\nExample: {{{ { tidd"+"ler.modified > new Date(\"Jul 4, 2005\")} }}} returns all tiddler modified after July 4th, 2005.\n\n!Com"+"bined Search\nYou are free to combine the various search options. \n\n''Examples''\n|!What you type|!Res"+"ult|\n|{{{!jonny !jeremy -%football}}}|all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its tit"+"les, but no {{{football}}} in content.|\n|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact wor"+"d). Tags named '~CompletedTask', '~TaskForce' etc. are not considered.|\n\n!Access Keys\nYou are encour"+"aged to use the access keys (also called \"shortcut\" keys) for the most frequently used operations. F"+"or quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\n\n|"+"!Key|!Operation|\n|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search in"+"put field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the pr"+"evious search result. This way you can quickly display multiple tiddlers using \"Press {{{Alt-F}}}. S"+"elect tiddler.\" sequences.|\n|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Resul"+"t]] is already closed and the cursor is in the search input field the field's content is cleared so "+"you start a new query.|\n|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second e"+"tc. tiddler from the result list.|\n|{{{Alt-O}}}|Opens all found tiddlers.|\n|{{{Alt-P}}}|Toggles the "+"'Preview Text' mode.|\n|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[Your"+"Search Result]].|\n|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the "+"{{{Return}}} key actually starts the search (as does pressing the 'search' button).|\n\n//If some of t"+"hese shortcuts don't work for you check your browser if you have other extensions installed that alr"+"eady \"use\" these shortcuts.//";config.shadowTiddlers["YourSearch Options"]="|>|!YourSearch Options|\n|>|<<option chkUseYourSearch>> Use 'Your Search'|\n|!|<<option chkPreviewText"+">> Show Text Preview|\n|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required"+" to start search)|\n|!|Default Search Filter:<<option chkSearchInTitle>>Title ('!')     <<option chk"+"SearchInText>>Text ('%')     <<option chkSearchInTags>>Tags ('#')    <<option chkSearchExtendedFiel"+"ds>>Extended Fields<html><br><font size=\"-2\">The fields of a tiddlers that are searched when you don"+"'t explicitly specify a filter in the search text <br>(Explictly specify fields using one or more '!"+"', '%', '#' or 'fieldname:' prefix before the word/text to find).</font></html>|\n|!|Number of items "+"on search result page: <<option txtItemsPerPage>>|\n|!|Number of items on search result page with pre"+"view text: <<option txtItemsPerPageWithPreview>>|\n";config.shadowTiddlers["YourSearchStyleSheet"]="/***\n!~YourSearchResult Stylesheet\n***/\n/*{{{*/\n.yourSearchResult {\n\tposition: absolute;\n\twidth: 800"+"px;\n\n\tpadding: 0.2em;\n\tlist-style: none;\n\tmargin: 0;\n\n\tbackground: #ffd;\n\tborder: 1px solid DarkGra"+"y;\n}\n\n/*}}}*/\n/***\n!!Summary Section\n***/\n/*{{{*/\n.yourSearchResult .summary {\n\tborder-bottom-width:"+" thin;\n\tborder-bottom-style: solid;\n\tborder-bottom-color: #999999;\n\tpadding-bottom: 4px;\n}\n\n.yourSea"+"rchRange, .yourSearchCount, .yourSearchQuery   {\n\tfont-weight: bold;\n}\n\n.yourSearchResult .summary ."+"button {\n\tfont-size: 10px;\n\n\tpadding-left: 0.3em;\n\tpadding-right: 0.3em;\n}\n\n.yourSearchResult .summa"+"ry .chkBoxLabel {\n\tfont-size: 10px;\n\n\tpadding-right: 0.3em;\n}\n\n/*}}}*/\n/***\n!!Items Area\n***/\n/*{{{*"+"/\n.yourSearchResult .marked {\n\tbackground: none;\n\tfont-weight: bold;\n}\n\n.yourSearchItem {\n\tmargin-to"+"p: 2px;\n}\n\n.yourSearchNumber {\n\tcolor: #808080;\n}\n\n\n.yourSearchTags {\n\tcolor: #008000;\n}\n\n.yourSearc"+"hText {\n\tcolor: #808080;\n\tmargin-bottom: 6px;\n}\n\n/*}}}*/\n/***\n!!Footer\n***/\n/*{{{*/\n.yourSearchFoote"+"r {\n\tmargin-top: 8px;\n\tborder-top-width: thin;\n\tborder-top-style: solid;\n\tborder-top-color: #999999;"+"\n}\n\n.yourSearchFooter a:hover{\n\tbackground: none;\n\tcolor: none;\n}\n/*}}}*/\n/***\n!!Navigation Bar\n***/"+"\n/*{{{*/\n.yourSearchNaviBar a {\n\tfont-size: 16px;\n\tmargin-left: 4px;\n\tmargin-right: 4px;\n\tcolor: bla"+"ck;\n\ttext-decoration: underline;\n}\n\n.yourSearchNaviBar a:hover {\n\tbackground-color: none;\n}\n\n.yourSe"+"archNaviBar .prev {\n\tfont-weight: bold;\n\tcolor: blue;\n}\n\n.yourSearchNaviBar .currentPage {\n\tcolor: #"+"FF0000;\n\tfont-weight: bold;\n\ttext-decoration: none;\n}\n\n.yourSearchNaviBar .next {\n\tfont-weight: bold"+";\n\tcolor: blue;\n}\n/*}}}*/\n";config.shadowTiddlers["YourSearchResultTemplate"]="<!--\n{{{\n-->\n<span macro=\"yourSearch if found\">\n<!-- The Summary Header ============================"+"================ -->\n<table class=\"summary\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">"+"<tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Result <span class=\"yourSearchRange\" macro=\"yourSearc"+"h itemRange\"></span>\n\t\t&nbsp;of&nbsp;<span class=\"yourSearchCount\" macro=\"yourSearch count\"></span>\n"+"\t\tfor&nbsp;<span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>\n\t</td>\n\t<td class=\"yourSea"+"rchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch chkPreviewText\"></span><span class=\"chkBoxLabel"+"\">preview text</span>\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch openAllButton\"></span>\n\t\t<span macro=\"yourSearch lin"+"kButton 'YourSearch Options' options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkB"+"utton 'YourSearch Help' help 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch clo"+"seButton\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n\n<!-- The List of Found Tiddlers ================="+"=========================== -->\n<div id=\"yourSearchResultItems\" itemsPerPage=\"25\" itemsPerPageWithPr"+"eview=\"10\"></div>\n\n<!-- The Footer (with the Navigation) ==========================================="+"= -->\n<table class=\"yourSearchFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody"+">\n  <tr>\n\t<td align=\"left\">\n\t\tResult page: <span class=\"yourSearchNaviBar\" macro=\"yourSearch naviBar"+"\"></span>\n\t</td>\n\t<td align=\"right\"><span macro=\"yourSearch version\"></span>, <span macro=\"yourSearc"+"h copyright\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n<!-- end of the 'tiddlers found' case ========="+"================================== -->\n</span>\n\n\n<!-- The \"No tiddlers found\" case ================="+"========================== -->\n<span macro=\"yourSearch if not found\">\n<table class=\"summary\" border="+"\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Resu"+"lt: No tiddlers found for <span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>.\n\t</td>\n\t<t"+"d class=\"yourSearchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Options'"+" options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Help' help"+" 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch closeButton\"></span>\n\t</td>\n  <"+"/tr>\n</tbody></table>\n</span>\n\n\n<!--\n}}}\n-->\n";config.shadowTiddlers["YourSearchItemTemplate"]="<!--\n{{{\n-->\n<span class='yourSearchNumber' macro='foundTiddler number'></span>\n<span class='yourSea"+"rchTitle' macro='foundTiddler title'/></span>&nbsp;-&nbsp;\n<span class='yourSearchTags' macro='found"+"Tiddler field tags 50'/></span>\n<span macro=\"yourSearch if previewText\"><div class='yourSearchText' macro='fo"+"undTiddler field text 250'/></div></span>\n<!--\n}}}\n-->";config.shadowTiddlers["YourSearch"]="<<tiddler [[YourSearch Help]]>>";config.shadowTiddlers["YourSearch Result"]="The popup-like window displaying the result of a YourSearch query.";config.macros.search.handler=_157;var _20a=function(){if(config.macros.search.handler!=_157){alert("Message from YourSearchPlugin:\n\n\nAnother plugin has disabled the 'Your Search' features.\n\n\nYou may "+"disable the other plugin or change the load order of \nthe plugins (by changing the names of the tidd"+"lers)\nto enable the 'Your Search' features.");}};setTimeout(_20a,5000);abego.YourSearch.getStandardRankFunction=function(){return _ff;};abego.YourSearch.getRankFunction=function(){return abego.YourSearch.getStandardRankFunction();};abego.YourSearch.getCurrentTiddler=function(){return _13c;};abego.YourSearch.closeResult=function(){_12a();};abego.YourSearch.getFoundTiddlers=function(){return _f2;};abego.YourSearch.getQuery=function(){return _f3;};abego.YourSearch.onShowResult=function(_20b){highlightHack=_f3?_f3.getMarkRegExp():null;if(!_20b){_13d.setItems(_f6());}
if(!_124){_124=createTiddlyElement(document.body,"div",_121,"yourSearchResult");}else{if(_124.parentNode!=document.body){document.body.appendChild(_124);}}
_146();highlightHack=null;};})();}
//%/
<div class='toolbar' macro='toolbar projectify +saveTiddler -cancelTiddler deleteAction'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view gtd.project'></span></div>
<div class='editor' macro='edit title'></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'></span></div>
<div class='toolbar' macro='toolbar changeContext changeProject deleteAction closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view gtd.project link'></span></div>
<div class='subtitle'><span macro='view modified date [[DD MMM YYYY]]'></span> (created <span macro='view created date [[DD MMM YYYY]]'></span>)&nbsp;<span macro='gtdActionCompleted'></span>complete&nbsp;<span macro='gtdToggleTag floating'></span>floating</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><br/>
<div macro='newReminder'></div>
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteContext'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></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'></span></div>
<div class='toolbar' macro='toolbar newAction closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='tagging'><span class='subtitle'><span macro='gtdToggleState chkGTDActionListReviewMode'></span>Review next actions only</span></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
Completed document conversion. Do not delete this tiddler unless you want to rebuild the action metadata.

This tiddler also contains document-specific preferences which, if deleted, will revert to default settings.
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteProject deleteProjectAll'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></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'></span></div>
<div class='toolbar' macro='toolbar newProjectAction archiveProject deleteProject deleteProjectAll closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><!-- <span macro='view modifier link'></span>, --><span macro='view modified date [[DD MMM YYYY]]'></span> (created <span macro='view created date [[DD MMM YYYY]]'></span>)&nbsp;<span macro='gtdToggleTag important'></span>important&nbsp;<span macro='gtdToggleTag someday'></span>defer</div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div><br/><div macro='newReminder'></div>
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='title' macro='view title'></div><div class='subtitle' macro='today "DDD, MMM DD, YYYY hh:0mm"'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>