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]];}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

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

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which use a logographic writing system and 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;}

.htmlarea .toolbarHA table {border:1px solid ButtonFace; margin:0em 0em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing 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'></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 +saveTiddler -cancelTiddler deleteTiddler'></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'></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
<<formTiddler PlantillaTareasConFechas>>
start:Sep 11 2007 00:00:00 GMT
end:Sep 14 2007 23:59:59 GMT
title:Ejemplo de tarea con fecha (varios días)
description:tarea
¡Este museo es fantástico!
<<formTiddler PlantillaTareasConFechas>>
start:Sep 12 2007 12:00:00 GMT
title:Ejemplo, tarea con fecha (evento)
Solo tiene que copiar y pegar el siguiente código a su tiddler para un proyecto, y reemplazar XXXX con el título de ese tiddler.

{{{<<forEachTiddler where 
'tiddler.tags.contains("proyecto") &&
tiddler.tags.contains("XXXX")'>>}}}
Solo tiene que copiar y pegar el siguiente código a su tiddler para una meta y reemplazar XXXX con el título de ese tiddler.

{{{<<forEachTiddler where 
'tiddler.tags.contains("tarea") && 
tiddler.tags.contains("XXXX")'>>}}}
!Cada día
*Añadir tarea aquí
!Cada semana
*
!Cada mes
*
!Cada tres meses
*
!Cada año
*
/***
|''Name:''|CalendarPlugin|
|''Source:''|http://www.TiddlyTools.com/#CalendarPlugin|
|''Author:''|SteveRumsby|
|''License:''|unknown|
|''~CoreVersion:''|2.0.10|

// // updated by Jeremy Sheeley to add cacheing for reminders
// // see http://www.geocities.com/allredfaq/reminderMacros.html
// // ''Changes by ELS 2006.08.23:''
// // added handling for weeknumbers (code supplied by Martin Budden.  see "wn**" comment marks)
// // ''Changes by ELS 2005.10.30:''
// // config.macros.calendar.handler()
// // ^^use "tbody" element for IE compatibility^^
// // ^^IE returns 2005 for current year, FF returns 105... fix year adjustment accordingly^^
// // createCalendarDays()
// // ^^use showDate() function (if defined) to render autostyled date with linked popup^^
// // calendar stylesheet definition
// // ^^use .calendar class-specific selectors, add text centering and margin settings^^


!!!!!Configuration:
<<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//
|''First day of week:''|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
|''First day of weekend:''|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|

!!!!!Syntax:
|{{{<<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|

***/
// //Modify this section to change the text displayed for the month and day names, to a different language for example. You can also change the format of the tiddler names linked to from each date, and the colours used.

//{{{
config.macros.calendar = {};

config.macros.calendar.monthnames = ["Ene", "Feb", "Mar", "Abr", "Mayo", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"];
config.macros.calendar.daynames = ["L", "M", "M", "J", "V", "S", "D"];

config.macros.calendar.weekendbg = "#c0c0c0";
config.macros.calendar.monthbg = "#e0e0e0";
config.macros.calendar.holidaybg = "#ffc0c0";

//}}}
// //''Code section:''
// (you should not need to alter anything below here)//
//{{{
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;

config.macros.calendar.tiddlerformat = "0DD/0MM/YYYY";  // This used to be changeable - for now, it isn't// <<smiley :-(>> 

version.extensions.calendar = { major: 0, minor: 6, revision: 0, date: new Date(2006, 1, 22)};
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
//}}}

// //Is the given date a holiday?
//{{{
function calendarIsHoliday(date)
{
 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;
}
//}}}

// //The main entry point - the macro handler.
// //Decide what sort of calendar we are creating (month or year, and which month or year)
// // Create the main calendar container and pass that to sub-ordinate functions to create the structure.
// ELS 2005.10.30: added creation and use of "tbody" for IE compatibility and fixup for year >1900//
// ELS 2005.10.30: fix year calculation for IE's getYear() function (which returns '2005' instead of '105')//
// ELS 2006.05.29: add journalDateFmt handling//
//{{{
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");
   this.journalDateFmt = "DD-MMM-YYYY";
   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, year-1);
    };
  createTiddlyButton(back, "<", "Previous year", backHandler);
  back.align = "center";

  var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);
  yearHeader.align = "center";
  //yearHeader.setAttribute("colSpan", 19);
  yearHeader.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?22:19);//wn**

  var fwd = createTiddlyElement(row, "td", null, null, null);
  var fwdHandler = function() {
    removeChildren(calendar);
    createCalendarYear(calendar, year+1);
  };
  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;

/*
    back.setAttribute("colSpan", 2);

    var backYearHandler = function() {
      var newyear = year-1;
      removeChildren(cal);
      cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
      createCalendarOneMonth(cal, newyear, mon);
    };
    createTiddlyButton(back, "<<", "Previous year", backYearHandler);
*/
    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);
    };
    createTiddlyButton(back, "<", "Previous month", backMonHandler);


    month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
//    month.setAttribute("colSpan", 3);
//    month.setAttribute("colSpan", 5);
    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; 

//    fwd.setAttribute("colSpan", 2);
    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);
    };
    createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);
/*
    var fwdYear = createTiddlyElement(row, "td", null, null, null);
    var fwdYearHandler = function() {
      var newyear = year+1;
      removeChildren(cal);
      cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
      createCalendarOneMonth(cal, newyear, mon);
    };
    createTiddlyButton(fwd, ">>", "Next year", fwdYearHandler);
*/
  } else {
    month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
    //month.setAttribute("colSpan", 7);
    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);
      createTiddlyElement(row, "td", null, null, "w"+ww.getWeek());//wn**
    }
    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
      if (window.showDate) {
        showDate(daycell,celldate,"popup","DD",config.macros.calendar.journalDateFmt,true, isaWeekend); // ELS 5/29/06 - use journalDateFmt 
      } else {
        if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
        var title = celldate.formatString(config.macros.calendar.tiddlerformat);
        if(calendarIsHoliday(celldate)) {
          daycell.style.background = config.macros.calendar.holidaybg;
        }
        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
//{{{
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.tiddlerformat);
  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: >>";
    }
  };
  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));
  }
}
//}}}

//{{{
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;
 }
}
//}}}

// //ELS 2005.10.30: added styles
//{{{
setStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:5px !important; }", "calendarStyles");
//}}}
// // override cookie settings for CalendarPlugin:
//{{{
config.options.txtCalFirstDay=6;
config.options.txtCalStartOfWeekend=5;
//}}}
<<calendar 2007>>
<<calendar 2008>>
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Version|2.2.4|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <<br>>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|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 either:
* automatically modifying the tiddler content (deprecated)
* or, 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.
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.
!!!!! Inline wiki-syntax usage
<<<
//{{{
[ ]or[_] and [x]or[X]
//}}}
Simple checkboxes using 'Inline X' storage.  The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked).  When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets.
>//''NOTE: 'Inline X' syntax has been deprecated...''  This storage format only works properly for checkboxes that are directly embedded and accessed from content in a single tiddler.  However, if that tiddler is 'transcluded' into another (by using the {{{<<tiddler TiddlerName>>}}} macro), the 'Inline X' will be ''erroneously stored in the containing tiddler's source content, resulting in corrupted content in that tiddler.''  For anything but the most simple of "to do list" uses, you should select from the various alternative storage methods described below...//
//{{{
[x=id]
//}}}
Assign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}.  If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value).  If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.
//{{{
[x(title|tag)] or [x(title:tag)]
//}}}
Initializes and tracks the current checkbox state by setting or removing a particular tag value from a specified tiddler.  If you omit the tiddler title (and the | or : separator), the specified tag is assigned to the current tiddler.  If you omit the tag value, as in {{{(title|)}}}, the default tag, {{{checked}}}, is assumed.  Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler.  When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state.  If a tiddler title named in the tag does not exist, the checkbox state defaults to the "inline X" value.  If this value is //checked//, or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the tag to it.  //''NOTE: beginning with version 2.1.2 of this plugin, the "|" separator is the preferred separator between the title and tag name, as it avoids syntactic ambiguity when ":" is used within tiddler titles or tag names.''//
//{{{
[x(field@tiddler)]
//}}}
Initializes and tracks the current checkbox state by setting a particular custom field value from a specified tiddler.  If you omit the tiddler title (but not the "@" separator), the specified field on the current tiddler is used.  If you omit the field name, as in {{{(@tiddler)}}}, a default fieldname of {{{checked}}} is assumed.  Omitting both the field and the tiddler title, {{{(@)}}}, defaults to setting the "checked" field on the current tiddler.  When field tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state.  If the tiddler title named in the parameter does not exist, the checkbox state defaults to the "inline X" value.  If this value is //checked// or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the field to it.
//{{{
[x{javascript}{javascript}]
//}}}
You can define optional javascript code segments to add custom initialization and/or 'onClick' handling to a checkbox.  The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to the default context-object, 'this'.

The first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state.  The second code segment (if present) is executed whenever the checkbox is clicked, so that you can perform programmed responses or intercept and override the checkbox state based on complex logic using the TW core API or custom functions defined in plugins (e.g. testing a particular tiddler title to see if certain tags are set or setting some tags when the checkbox is clicked).

Note: if you want to use the default checkbox initialization processing with a custom onclick function, use this syntax: {{{ [x=id{}{javascript}] }}} 
<<<
!!!!! Macro usage
<<<
In addition to embedded checkboxes using the wiki syntax described above, a ''macro-based syntax'' is also provided, for use in templates where wiki syntax cannot be directly used.  This macro syntax can also be used in tiddler content, as an alternative to the wiki syntax.  When embedded in [[PageTemplate]], [[ViewTemplate]], or [[EditTemplate]] (or custom alternative templates), use the following macro syntax:
//{{{
<span macro="checkbox target checked id onInit onClick"></span>
//}}}
or, when embedded in tiddler content, use the following macro syntax:
//{{{
<<checkbox target checked id onInit onClick>>
//}}}
where:
''target''
>is either a tag reference (e.g., ''tagname|tiddlername'') or a field reference (e.g. ''fieldname@tiddlername''), as described above.
''checked'' (optional)
>is a keyword that sets the initial state of the checkbox to "checked".  When omitted, the default checkbox state is "unchecked".
''id'' (optional)
>specifies an internal config.options.* ID, as described above.  If the ID begins with "chk", a cookie-based persistent value will be created to track the checkbox state in between sessions.
''onInit'' (optional)
>contains a javascript event handler to be performed when the checkbox is initially rendered (see details above).
''onClick'' (optional)
>contains a javascript event handler to be performed each time the checkbox is clicked (see details above).
>//note: to use the default onInit handler with a custom onClick handler, use "" (empty quotes) as a placeholder for the onInit parameter//
<<<
!!!!!Examples
<<<
''checked and unchecked static default ("inline X") values:''
//{{{
[X] label
[_] label
//}}}
>[X] label
>[_] label
''document-based value (id='demo', no cookie):''
//{{{
[_=demo] label
//}}}
>[_=demo] label
''cookie-based value  (id='chkDemo'):''
//{{{
[_=chkDemo] label
//}}}
>[_=chkDemo] label
''tag-based value (TogglyTagging):''
//{{{
[_(CheckboxPlugin|demotag)]
[_(CheckboxPlugin|demotag){this.refresh.tagged=this.refresh.container=false}]
//}}}
>[_(CheckboxPlugin|demotag)] toggle 'demotag' (and refresh tiddler display)
>[_(CheckboxPlugin|demotag){this.refresh.tagged=this.refresh.container=false}] toggle 'demotag' (no refresh)
''field-based values:''
//{{{
[_(demofield@CheckboxPlugin)] demofield@CheckboxPlugin
[_(demofield@)] demofield@ (equivalent to demonfield@ current tiddler)
[_(checked@CheckboxPlugin)] checked@CheckboxPlugin
[_(@CheckboxPlugin)] @CheckboxPlugin
[_(@)] @ (equivalent to checked@ current tiddler)
//}}}
>[_(demofield@CheckboxPlugin)] demofield@CheckboxPlugin
>[_(demofield@)] demofield@ (current tiddler)
>[_(checked@CheckboxPlugin)] checked@CheckboxPlugin
>[_(@CheckboxPlugin)] @CheckboxPlugin
>[_(@)] toggle field: @ (defaults to "checked@here")
>click to view current: <<toolbar fields>>
''custom init and onClick functions:''
//{{{
[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state
//}}}
>[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state
''retrieving option values:''
>config.options['demo']=<script>return config.options['demo']?"true":"false";</script>
>config.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>
<<<
!!!!!Configuration
<<<
Normally, when a checkbox state is changed, the affected tiddlers are automatically re-rendered, so that any checkbox-dependent dynamic content can be updated.  There are three possible tiddlers to be re-rendered, depending upon where the checkbox is placed, and what kind of storage method it is using.
*''container'': the tiddler in which the checkbox is displayed. (e.g., this tiddler)
*''tagged'': the tiddler that is being tagged (e.g., "~MyTask" when tagging "~MyTask:done")
*''tagging'': the "tag tiddler" (e.g., "~done" when tagging "~MyTask:done")
You can set the default refresh handling for all checkboxes in your document by using the following javascript syntax either in a systemConfig plugin, or as an inline script.  (Substitute true/false values as desired):
{{{config.checkbox.refresh = { tagged:true, tagging:true, container:true };}}}

You can also override these defaults for any given checkbox by using an initialization function to set one or more of the refresh options.  For example:
{{{[_{this.refresh.container=false}]}}}
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''CheckboxPlugin'' (tagged with <<tag systemConfig>>)
<<<
!!!!!Revision History
<<<
2007.08.06 - 2.2.5 supress automatic refresh of any tiddler that is currently being edited.  Ensures that current tiddler edit sessions are not prematurely discarded (losing any changes).  However, if checkbox changes a tag on a tiddler being edited, update the "tags" input field (if any) so that saving the edited tiddler correctly reflects any changes due to checkbox activity... see refreshEditorTagField().
2007.07.13 - 2.2.4 in handler(), fix srctid reference (was "w.tiddler", should have been "w.tiddler.title").  This fixes broken 'inline X' plus fatal macro error when using PartTiddlerPlugin.  Thanks to cmari for reporting the problem and UdoBorkowski for finding the code error.
2007.06.21 - 2.2.3 suppress automatic refresh of tiddler when using macro-syntax to prevent premature end of tiddler editing session.
2007.06.20 - 2.2.2 fixed handling for 'inline X' when checkboxes are contained in a 'trancluded' tiddler.  Now, regardless of where an inline X checkbox appears, the X will be placed in the originating source tiddler, rather than the tiddler in which the checkbox appears.
2007.06.17 - 2.2.1 Refactored code to add checkbox //macro// syntax for use in templates (e.g., {{{macro="checkbox ..."}}}. Also, code cleanup of existing tag handling.
2007.06.16 - 2.2.0 added support for tracking checkbox states using tiddler fields via "(fieldname@tiddlername)" syntax.
2006.05.04 - 2.1.3 fix use of findContainingTiddler() to check for a non-null return value, so that checkboxes won't crash when used outside of tiddler display context (such as in header, sidebar or mainmenu)
2006.03.11 - 2.1.2 added "|" as delimiter to tag-based storage syntax (e.g. "tiddler|tag") to avoid parsing ambiguity when tiddler titles or tag names contain ":".   Using ":" as a delimiter is still supported but is deprecated in favor of the new "|" usage.  Based on a problem reported by JeffMason.
2006.02.25 - 2.1.0 added configuration options to enable/disable forced refresh of tiddlers when toggling tags
2006.02.23 - 2.0.4 when toggling tags, force refresh of the tiddler containing the checkbox.
2006.02.23 - 2.0.3 when toggling tags, force refresh of the 'tagged tiddler' so that tag-related tiddler content (such as "to-do" lists) can be re-rendered.
2006.02.23 - 2.0.2 when using tag-based storage, allow use [[ and ]] to quote tiddler or tag names that contain spaces:
{{{[x([[Tiddler with spaces]]:[[tag with spaces]])]}}}
2006.01.10 - 2.0.1 when toggling tags, force refresh of the 'tagging tiddler'.  For example, if you toggle the "systemConfig" tag on a plugin, the corresponding "systemConfig" TIDDLER will be automatically refreshed (if currently displayed), so that the 'tagged' list in that tiddler will remain up-to-date.
2006.01.04 - 2.0.0 update for ~TW2.0
2005.12.27 - 1.1.2 Fix lookAhead regExp handling for {{{[x=id]}}}, which had been including the "]" in the extracted ID.  
Added check for "chk" prefix on ID before calling saveOptionCookie()
2005.12.26 - 1.1.2 Corrected use of toUpperCase() in tiddler re-write code when comparing {{{[X]}}} in tiddler content with checkbox state. Fixes a problem where simple checkboxes could be set, but never cleared.
2005.12.26 - 1.1.0 Revise syntax so all optional parameters are included INSIDE the [ and ] brackets.  Backward compatibility with older syntax is supported, so content changes are not required when upgrading to the current version of this plugin.   Based on a suggestion by GeoffSlocock
2005.12.25 - 1.0.0 added support for tracking checkbox state using tags ("TogglyTagging")
Revised version number for official post-beta release.
2005.12.08 - 0.9.3 support separate 'init' and 'onclick' function definitions.
2005.12.08 - 0.9.2 clean up lookahead pattern
2005.12.07 - 0.9.1 only update tiddler source content if checkbox state is actually different.  Eliminates unnecessary tiddler changes (and 'unsaved changes' warnings)
2005.12.07 - 0.9.0 initial BETA release
<<<
!!!!!Credits
<<<
This feature was created by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]
<<<
!!!!!Code
***/
//{{{
version.extensions.CheckboxPlugin = {major: 2, minor: 2, revision:5 , date: new Date(2007,8,6)};
//}}}

//{{{
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_click=lookaheadMatch[5];
			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_click);
			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_click=params.shift(); if (fn_click && !fn_click.length) fn_click=null;
		var refresh={ tagged:true, tagging:true, container:false };
		this.create(place,tiddler.title,tiddler.title,0,defaultState,id,target,refresh,fn_init,fn_click);
	},
	create: function(place,tid,srctid,srcpos,defaultState,id,target,refresh,fn_init,fn_click) {
		// 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
			}
		}
		if (fn_init) c.fn_init=fn_init.trim().substr(1,fn_init.length-2); // trim off surrounding { and } delimiters
		if (fn_click) c.fn_click=fn_click.trim().substr(1,fn_click.length-2);
		c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie
	},
	onClickCheckbox: function(event) {
		if (this.fn_init)
			// custom function hook to set initial state (run only once)
			{ try { eval(this.fn_init); this.fn_init=null; } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }
		else if (this.fn_click)
			// custom function hook to override or react to changes in checkbox state
			{ try { eval(this.fn_click) } catch(e) { displayMessage("Checkbox click 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.find(this.tag)!=null);
				if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }
				if (!this.checked && tagged) { t.tags.splice(t.tags.find(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)) story.refreshTiddler(this.tiddler,null,true); // the TAGGED tiddler in view mode
					else config.macros.checkbox.refreshEditorTagField(this.tiddler,this.tag,this.checked); // the TAGGED tiddler in edit mode (with tags field)
				}
				if (this.refresh.tagging)
					if (!story.isDirty(this.tag)) story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler
			}
		}
		// 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;
	}
}
//}}}
Un lugar conveniente para esta información confidencial.
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #000
PrimaryMid: #001177
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #001177
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
<<forEachTiddler where 'tiddler.tags.contains("Compras y salidas")' sortBy 'tiddler.title'>>
<<formTiddler PlantillaParaNuevosContactos>><data>{"firstname":"contacto","lastname":"imaginario","email":"suchandsuch@suchandsuch.com","phone":"01-616-538-8678","address":"Such and such lane","city":"Towaco","state":"TX","zip":"66666","country":"USA","webpage":"http://suchandsuch.com","birthday":"Feb. 27"}</data>
Sus hijos se llaman Julio y Esteban.
<<forEachTiddler 
where 'tiddler.tags.contains("contacto") && tiddler.tags.contains("amigo")'
sortBy 'tiddler.data("firstname")'
write
 '"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|"+tiddler.data("phone")+"| [[here|"+tiddler.title+"]]|\n"' 
>>
<<forEachTiddler 
where 'tiddler.tags.contains("contacto") && tiddler.tags.contains("familia")'
sortBy 'tiddler.data("firstname")'
write
 '"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|"+tiddler.data("phone")+"| [[here|"+tiddler.title+"]]|\n"' 
>>
<<forEachTiddler 
where 'tiddler.tags.contains("contacto") && tiddler.tags.contains("iglesia")'
sortBy 'tiddler.data("lastname") && tiddler.data("firstname")'
write
 '"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|[[here|"+tiddler.title+"]]|\n"' 
>>
<<forEachTiddler 
where 'tiddler.tags.contains("contacto") && tiddler.tags.contains("misc")'
sortBy 'tiddler.data("firstname")'
write
 '"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|"+tiddler.data("phone")+"| [[here|"+tiddler.title+"]]|\n"' 
>>
<<forEachTiddler 
where 'tiddler.tags.contains("contacto") && tiddler.tags.contains("trabajo")'
sortBy 'tiddler.data("firstname")'
write
 '"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|"+tiddler.data("phone")+"| [[here|"+tiddler.title+"]]|\n"' 
>>
<<forEachTiddler 
where 'tiddler.tags.contains("contacto")'
sortBy 'tiddler.data("lastname") && tiddler.data("firstname")'
write
 '"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|"+tiddler.data("email")+"| [[here|"+tiddler.title+"]]|\n"' 
>>
<<forEachTiddler where 'tiddler.tags.contains("Correspondencia")' sortBy 'tiddler.title'>>
/***
|''Name:''|DataTiddlerPlugin|
|''Version:''|1.0.6 (2006-08-26)|
|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Enhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).

Such tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers. 

''//Example: "Table with all December Expenses"//''
{{{
<<forEachTiddler
    where
        'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
    write
        '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
}}}
//(This assumes that expenses are stored in tiddlers tagged with "expense".)//
<<forEachTiddler
    where
        'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
    write
        '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
For other examples see DataTiddlerExamples.




''Access and Modify Tiddler Data''

You can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields. 

These values can be accessed and modified through the following Tiddler methods:
|!Method|!Example|!Description|
|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|

Alternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.
|!Method|!Description|
|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
//(For details on the various functions see the detailed comments in the source code.)//


''Data Representation in a Tiddler''

The data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]]. 

//''Data Section Example:''//
{{{
<data>{"isVIP":true,"user":"John Brown","age":34}</data>
}}}

The data section is not displayed when viewing the tiddler (see also "The showData Macro").

Beside the data section a tiddler may have all kind of other content.

Typically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.


''Saving Changes''

The "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.


''Notifications''

No notifications are sent when a tiddler's data value is changed through the "setData" methods. 

''Escape Data Section''
In case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.


''The showData Macro''

By default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:

''Syntax:'' 
|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|
|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|
|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|


!Revision history
* v1.0.6 (2006-08-26) 
** Removed misleading comment
* v1.0.5 (2006-02-27) (Internal Release Only)
** Internal
*** Make "JSLint" conform
* v1.0.4 (2006-02-05)
** Bugfix: showData fails in TiddlyWiki 2.0
* v1.0.3 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.2 (2005-12-22)
** Enhancements:
*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.
*** Improved (JSON) error messages.
** Bugs fixed: 
*** References are not updated when using the DataTiddler.
*** Changes to compound objects are not always saved.
*** "~</data>" is not rendered correctly (expected "</data>")
* v1.0.1 (2005-12-13)
** Features: 
*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed
** Bugs fixed: 
*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)
* v1.0.0 (2005-12-12)
** initial version

!Code
***/
//{{{
//============================================================================
//============================================================================
//                           DataTiddlerPlugin
//============================================================================
//============================================================================

// Ensure that the DataTiddler Plugin is only installed once.
//
if (!version.extensions.DataTiddlerPlugin) {



version.extensions.DataTiddlerPlugin = {
    major: 1, minor: 0, revision: 6,
    date: new Date(2006, 7, 26), 
    type: 'plugin',
    source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"
};

// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window; 
if (!TiddlyWiki.prototype.getTiddler) {
	TiddlyWiki.prototype.getTiddler = function(title) { 
		var t = this.tiddlers[title]; 
		return (t !== undefined && t instanceof Tiddler) ? t : null; 
	};
}

//============================================================================
// DataTiddler Class
//============================================================================

// ---------------------------------------------------------------------------
// Configurations and constants 
// ---------------------------------------------------------------------------

function DataTiddler() {
}

DataTiddler = {
    // Function to stringify a JavaScript value, producing the text for the data section content.
    // (Must match the implementation of DataTiddler.parse.)
    //
    stringify : null,
    

    // Function to parse the text for the data section content, producing a JavaScript value.
    // (Must match the implementation of DataTiddler.stringify.)
    //
    parse : null
};

// Ensure access for IE
window.DataTiddler = DataTiddler;

// ---------------------------------------------------------------------------
// Data Accessor and Mutator
// ---------------------------------------------------------------------------


// Returns the value of the given data field of the tiddler.
// When no such field is defined or its value is undefined
// the defaultValue is returned.
// 
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.getData = function(tiddler, field, defaultValue) {
    var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
    if (!(t instanceof Tiddler)) {
        throw "Tiddler expected. Got "+tiddler;
    }

    return DataTiddler.getTiddlerDataValue(t, field, defaultValue);
};


// Sets the value of the given data field of the tiddler to
// the value. When the value is equal to the defaultValue
// no value is set (and the field is removed)
//
// Changing data of a tiddler will not trigger notifications.
// 
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.setData = function(tiddler, field, value, defaultValue) {
    var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
    if (!(t instanceof Tiddler)) {
        throw "Tiddler expected. Got "+tiddler+ "("+t+")";
    }

    DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);
};


// Returns the data object of the tiddler, with a property for every field.
//
// The properties of the returned data object may only be read and
// not be modified. To modify the data use DataTiddler.setData(...) 
// or the corresponding Tiddler method.
//
// If no data section is defined a new (empty) object is returned.
//
// @param tiddler either a tiddler name or a Tiddler
//
DataTiddler.getDataObject = function(tiddler) {
    var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
    if (!(t instanceof Tiddler)) {
        throw "Tiddler expected. Got "+tiddler;
    }

    return DataTiddler.getTiddlerDataObject(t);
};

// Returns the text of the content of the data section of the tiddler.
//
// When no data section is defined for the tiddler null is returned 
//
// @param tiddler either a tiddler name or a Tiddler
// @return [may be null]
//
DataTiddler.getDataText = function(tiddler) {
    var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
    if (!(t instanceof Tiddler)) {
        throw "Tiddler expected. Got "+tiddler;
    }

    return DataTiddler.readDataSectionText(t);
};


// ---------------------------------------------------------------------------
// Internal helper methods (must not be used by code from outside this plugin)
// ---------------------------------------------------------------------------

// Internal.
//
// The original JSONError is not very user friendly, 
// especially it does not define a toString() method
// Therefore we extend it here.
//
DataTiddler.extendJSONError = function(ex) {
	if (ex.name == 'JSONError') {
        ex.toString = function() {
			return ex.name + ": "+ex.message+" ("+ex.text+")";
		};
	}
	return ex;
};

// Internal.
//
// @param t a Tiddler
//
DataTiddler.getTiddlerDataObject = function(t) {
    if (t.dataObject === undefined) {
        var data = DataTiddler.readData(t);
        t.dataObject = (data) ? data : {};
    }
    
    return t.dataObject;
};


// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {
    var value = DataTiddler.getTiddlerDataObject(tiddler)[field];
    return (value === undefined) ? defaultValue : value;
};


// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {
    var data = DataTiddler.getTiddlerDataObject(tiddler);
    var oldValue = data[field];
	
    if (value == defaultValue) {
        if (oldValue !== undefined) {
            delete data[field];
            DataTiddler.save(tiddler);
        }
        return;
    }
    data[field] = value;
    DataTiddler.save(tiddler);
};

// Internal.
//
// Reads the data section from the tiddler's content and returns its text
// (as a String).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readDataSectionText = function(tiddler) {
    var matches = DataTiddler.getDataTiddlerMatches(tiddler);
    if (matches === null || !matches[2]) {
        return null;
    }
    return matches[2];
};

// Internal.
//
// Reads the data section from the tiddler's content and returns it
// (as an internalized object).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readData = function(tiddler) {
    var text = DataTiddler.readDataSectionText(tiddler);
	try {
	    return text ? DataTiddler.parse(text) : null;
	} catch(ex) {
		throw DataTiddler.extendJSONError(ex);
	}
};

// Internal.
// 
// Returns the serialized text of the data of the given tiddler, as it
// should be stored in the data section.
//
// @param tiddler a Tiddler
//
DataTiddler.getDataTextOfTiddler = function(tiddler) {
    var data = DataTiddler.getTiddlerDataObject(tiddler);
    return DataTiddler.stringify(data);
};


// Internal.
// 
DataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {
	var index = s.indexOf(subString, startIndex);
	while ((index > 0) && (s[index-1] == '~')) { 
		index = s.indexOf(subString, index+1);
	}
	return index;
};

// Internal.
//
DataTiddler.getDataSectionInfo = function(text) {
	// Special care must be taken to handle "<data>" and "</data>" texts inside
	// a data section. 
	// Also take care not to use an escaped <data> (i.e. "~<data>") as the start 
	// of a data section. (Same for </data>)

    // NOTE: we are explicitly searching for a data section that contains a JSON
    // string, i.e. framed with braces. This way we are little bit more robust in
    // case the tiddler contains unescaped texts "<data>" or "</data>". This must
    // be changed when using a different stringifier.

	var startTagText = "<data>{";
	var endTagText = "}</data>";

	var startPos = 0;

	// Find the first not escaped "<data>".
	var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);
	if (startDataTagIndex < 0) {
		return null;
	}

	// Find the *last* not escaped "</data>".
	var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);
	if (endDataTagIndex < 0) {
		return null;
	}
	var nextEndDataTagIndex;
	while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {
		endDataTagIndex = nextEndDataTagIndex;
	}

	return {
		prefixEnd: startDataTagIndex, 
		dataStart: startDataTagIndex+(startTagText.length)-1, 
		dataEnd: endDataTagIndex, 
		suffixStart: endDataTagIndex+(endTagText.length)
	};
};

// Internal.
// 
// Returns the "matches" of a content of a DataTiddler on the
// "data" regular expression. Return null when no data is defined
// in the tiddler content.
//
// Group 1: text before data section (prefix)
// Group 2: content of data section
// Group 3: text behind data section (suffix)
//
// @param tiddler a Tiddler
// @return [may be null] null when the tiddler contains no data section, otherwise see above.
//
DataTiddler.getDataTiddlerMatches = function(tiddler) {
	var text = tiddler.text;
	var info = DataTiddler.getDataSectionInfo(text);
	if (!info) {
		return null;
	}

	var prefix = text.substr(0,info.prefixEnd);
	var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);
	var suffix = text.substr(info.suffixStart);
	
	return [text, prefix, data, suffix];
};


// Internal.
//
// Saves the data in a <data> block of the given tiddler (as a minor change). 
//
// The "chkAutoSave" and "chkForceMinorUpdate" options are respected. 
// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.
//
// Notifications are not send. 
//
// This method should only be called when the data really has changed. 
//
// @param tiddler
//             the tiddler to be saved.
//
DataTiddler.save = function(tiddler) {

    var matches = DataTiddler.getDataTiddlerMatches(tiddler);

    var prefix;
    var suffix;
    if (matches === null) {
        prefix = tiddler.text;
        suffix = "";
    } else {
        prefix = matches[1];
        suffix = matches[3];
    }

    var dataText = DataTiddler.getDataTextOfTiddler(tiddler);
    var newText = 
            (dataText !== null) 
                ? prefix + "<data>" + dataText + "</data>" + suffix
                : prefix + suffix;
    if (newText != tiddler.text) {
        // make the change in the tiddlers text
        
        // ... see DataTiddler.MyTiddlerChangedFunction
        tiddler.isDataTiddlerChange = true;
        
        // ... do the action change
        tiddler.set(
                tiddler.title,
                newText,
                config.options.txtUserName, 
                config.options.chkForceMinorUpdate? undefined : new Date(),
                tiddler.tags);

        // ... see DataTiddler.MyTiddlerChangedFunction
        delete tiddler.isDataTiddlerChange;

        // Mark the store as dirty.
        store.dirty = true;
 
        // AutoSave if option is selected
        if(config.options.chkAutoSave) {
           saveChanges();
        }
    }
};

// Internal.
//
DataTiddler.MyTiddlerChangedFunction = function() {
    // Remove the data object from the tiddler when the tiddler is changed
    // by code other than DataTiddler code. 
    //
    // This is necessary since the data object is just a "cached version" 
    // of the data defined in the data section of the tiddler and the 
    // "external" change may have changed the content of the data section.
    // Thus we are not sure if the data object reflects the data section 
    // contents. 
    // 
    // By deleting the data object we ensure that the data object is 
    // reconstructed the next time it is needed, with the data defined by
    // the data section in the tiddler's text.
    
    // To indicate that a change is a "DataTiddler change" a temporary
    // property "isDataTiddlerChange" is added to the tiddler.
    if (this.dataObject && !this.isDataTiddlerChange) {
        delete this.dataObject;
    }
    
    // call the original code.
	DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);
};


//============================================================================
// Formatters
//============================================================================

// This formatter ensures that "~<data>" is rendered as "<data>". This is used to 
// escape the "<data>" of a data section, just in case someone really wants to use
// "<data>" as a text in a tiddler and not start a data section.
//
// Same for </data>.
//
config.formatters.push( {
    name: "data-escape",
    match: "~<\\/?data>",

    handler: function(w) {
            w.outputText(w.output,w.matchStart + 1,w.nextMatch);
    }
} );


// This formatter ensures that <data>...</data> sections are not rendered.
//
config.formatters.push( {
    name: "data",
    match: "<data>",

    handler: function(w) {
		var info = DataTiddler.getDataSectionInfo(w.source);
		if (info && info.prefixEnd == w.matchStart) {
            w.nextMatch = info.suffixStart;
		} else {
			w.outputText(w.output,w.matchStart,w.nextMatch);
		}
    }
} );


//============================================================================
// Tiddler Class Extension
//============================================================================

// "Hijack" the changed method ---------------------------------------------------

DataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;
Tiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;

// Define accessor methods -------------------------------------------------------

// Returns the value of the given data field of the tiddler. When no such field 
// is defined or its value is undefined the defaultValue is returned.
//
// When field is undefined (or null) the data object is returned. (See 
// DataTiddler.getDataObject.)
//
// @param field [may be null, undefined]
// @param defaultValue [may be null, undefined]
// @return [may be null, undefined]
//
Tiddler.prototype.data = function(field, defaultValue) {
    return (field) 
         ? DataTiddler.getTiddlerDataValue(this, field, defaultValue)
         : DataTiddler.getTiddlerDataObject(this);
};

// Sets the value of the given data field of the tiddler to the value. When the 
// value is equal to the defaultValue no value is set (and the field is removed).
//
// @param value [may be null, undefined]
// @param defaultValue [may be null, undefined]
//
Tiddler.prototype.setData = function(field, value, defaultValue) {
    DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);
};


//============================================================================
// showData Macro
//============================================================================

config.macros.showData = {
     // Standard Properties
     label: "showData",
     prompt: "Display the values stored in the data section of the tiddler"
};

config.macros.showData.handler = function(place,macroName,params) {
    // --- Parsing ------------------------------------------

    var i = 0; // index running over the params
    // Parse the optional "JSON"
    var showInJSONFormat = false;
    if ((i < params.length) && params[i] == "JSON") {
        i++;
        showInJSONFormat = true;
    }
    
    var tiddlerName = story.findContainingTiddler(place).id.substr(7);
    if (i < params.length) {
        tiddlerName = params[i];
        i++;
    }

    // --- Processing ------------------------------------------
    try {
        if (showInJSONFormat) {
            this.renderDataInJSONFormat(place, tiddlerName);
        } else {
            this.renderDataAsTable(place, tiddlerName);
        }
    } catch (e) {
        this.createErrorElement(place, e);
    }
};

config.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {
    var text = DataTiddler.getDataText(tiddlerName);
    if (text) {
        createTiddlyElement(place,"pre",null,null,text);
    }
};

config.macros.showData.renderDataAsTable = function(place,tiddlerName) {
    var text = "|!Name|!Value|\n";
    var data = DataTiddler.getDataObject(tiddlerName);
    if (data) {
        for (var i in data) {
            var value = data[i];
            text += "|"+i+"|"+DataTiddler.stringify(value)+"|\n";
        }
    }
    
    wikify(text, place);
};


// Internal.
//
// Creates an element that holds an error message
// 
config.macros.showData.createErrorElement = function(place, exception) {
    var message = (exception.description) ? exception.description : exception.toString();
    return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);
};

// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
    ".showDataError{color: #ffffff;background-color: #880000;}",
    "showData");


} // of "install only once"
// Used Globals (for JSLint) ==============

// ... TiddlyWiki Core
/*global 	createTiddlyElement, saveChanges, store, story, wikify */
// ... DataTiddler
/*global 	DataTiddler */
// ... JSON
/*global 	JSON */
			

/***
!JSON Code, used to serialize the data
***/
/*
Copyright (c) 2005 JSON.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*
    The global object JSON contains two methods.

    JSON.stringify(value) takes a JavaScript value and produces a JSON text.
    The value must not be cyclical.

    JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
    throw a 'JSONError' exception if there is an error.
*/
var JSON = {
    copyright: '(c)2005 JSON.org',
    license: 'http://www.crockford.com/JSON/license.html',
/*
    Stringify a JavaScript value, producing a JSON text.
*/
    stringify: function (v) {
        var a = [];

/*
    Emit a string.
*/
        function e(s) {
            a[a.length] = s;
        }

/*
    Convert a value.
*/
        function g(x) {
            var c, i, l, v;

            switch (typeof x) {
            case 'object':
                if (x) {
                    if (x instanceof Array) {
                        e('[');
                        l = a.length;
                        for (i = 0; i < x.length; i += 1) {
                            v = x[i];
                            if (typeof v != 'undefined' &&
                                    typeof v != 'function') {
                                if (l < a.length) {
                                    e(',');
                                }
                                g(v);
                            }
                        }
                        e(']');
                        return;
                    } else if (typeof x.toString != 'undefined') {
                        e('{');
                        l = a.length;
                        for (i in x) {
                            v = x[i];
                            if (x.hasOwnProperty(i) &&
                                    typeof v != 'undefined' &&
                                    typeof v != 'function') {
                                if (l < a.length) {
                                    e(',');
                                }
                                g(i);
                                e(':');
                                g(v);
                            }
                        }
                        return e('}');
                    }
                }
                e('null');
                return;
            case 'number':
                e(isFinite(x) ? +x : 'null');
                return;
            case 'string':
                l = x.length;
                e('"');
                for (i = 0; i < l; i += 1) {
                    c = x.charAt(i);
                    if (c >= ' ') {
                        if (c == '\\' || c == '"') {
                            e('\\');
                        }
                        e(c);
                    } else {
                        switch (c) {
                            case '\b':
                                e('\\b');
                                break;
                            case '\f':
                                e('\\f');
                                break;
                            case '\n':
                                e('\\n');
                                break;
                            case '\r':
                                e('\\r');
                                break;
                            case '\t':
                                e('\\t');
                                break;
                            default:
                                c = c.charCodeAt();
                                e('\\u00' + Math.floor(c / 16).toString(16) +
                                    (c % 16).toString(16));
                        }
                    }
                }
                e('"');
                return;
            case 'boolean':
                e(String(x));
                return;
            default:
                e('null');
                return;
            }
        }
        g(v);
        return a.join('');
    },
/*
    Parse a JSON text, producing a JavaScript value.
*/
    parse: function (text) {
        var p = /^\s*(([,:{}\[\]])|"(\\.|[^\x00-\x1f"\\])*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)\s*/,
            token,
            operator;

        function error(m, t) {
            throw {
                name: 'JSONError',
                message: m,
                text: t || operator || token
            };
        }

        function next(b) {
            if (b && b != operator) {
                error("Expected '" + b + "'");
            }
            if (text) {
                var t = p.exec(text);
                if (t) {
                    if (t[2]) {
                        token = null;
                        operator = t[2];
                    } else {
                        operator = null;
                        try {
                            token = eval(t[1]);
                        } catch (e) {
                            error("Bad token", t[1]);
                        }
                    }
                    text = text.substring(t[0].length);
                } else {
                    error("Unrecognized token", text);
                }
            } else {
                token = operator = undefined;
            }
        }


        function val() {
            var k, o;
            switch (operator) {
            case '{':
                next('{');
                o = {};
                if (operator != '}') {
                    for (;;) {
                        if (operator || typeof token != 'string') {
                            error("Missing key");
                        }
                        k = token;
                        next();
                        next(':');
                        o[k] = val();
                        if (operator != ',') {
                            break;
                        }
                        next(',');
                    }
                }
                next('}');
                return o;
            case '[':
                next('[');
                o = [];
                if (operator != ']') {
                    for (;;) {
                        o.push(val());
                        if (operator != ',') {
                            break;
                        }
                        next(',');
                    }
                }
                next(']');
                return o;
            default:
                if (operator !== null) {
                    error("Missing value");
                }
                k = token;
                next();
                return k;
            }
        }
        next();
        return val();
    }
};

/***
!Setup the data serialization
***/

DataTiddler.format = "JSON";
DataTiddler.stringify = JSON.stringify;
DataTiddler.parse = JSON.parse;

//}}}

Soy pastor ordenado con la Iglesia Cristiana Reformada sirviendo como misionero en México D. F. Uso ~TiddlyWiki principalmente para crear recursos bíblicos en español. Si quiere saber más de mí, visite nuestro sitio web ([[enlace aquí|http://www.giffmex.org]]). El sitio tiene información acerca de nosotros y enlaces a todos nuestros recursos en español e inglés.

Si tiene preguntas acerca de ~TiddlyWiki, debe primero consultar nuestro tutorial de ~TiddlyWiki ([[enlace aquí|http://www.giffmex.org/twtutorialespanol.html]]). Si sabe inglés, aun a medias, otra fuente importante de ayuda es el grupo de ~TiddlyWiki en Google Groups ([[enlace aquí|http://groups.google.com/group/TiddlyWiki]]).

Pero en el peor de casos si le urge contactarme personalmente, mi correo es 

''contacto (arroba) giffmex (punto) org.''
[[Instrucciones para TiddlyTareas]]
[[TareasCorrientes]]
[[Recordatorios]]
~TiddlyWiki es © 2007 [[UnaMesa|http://www.unamesa.org/]]

~TiddlyTareas es una adaptación gratuita de ~TiddlyWiki creada por [[David Gifford]]. 

~TiddlyTareas utiliza varias extensiones (plugins) por varios creadores. Estos plugins y su documentación se pueden revisar abriendo 'Etiquetas' en el menú derecho y seleccionar la etiqueta 'systemConfig'.
|!Estado|!Descripción|
|''prioridad''|Para tareas de alta prioridad. ~TiddlyTareas las incluye en la parte superior del tiddler [[TareasCorrientes]] y las marca con una estrella. Este tiddler aparece cada vez que usted abre ~TiddlyTareas.|
|''actual''|Para tareas actuales o corrientes, pero no de alta prioridad. ~TiddlyTareas las incluye en el tiddler [[TareasCorrientes]]. Este tiddler aparece cada vez que usted abre ~TiddlyTareas.|
|''espera''|Para tareas que esperan algo de alguien antes de poder realizarse. ~TiddlyTareas las incluye en la parte inferior del tiddler [[TareasCorrientes]] y las marca con "''(e)''". Este tiddler aparece cada vez que usted abre ~TiddlyTareas.|
|''fecha''|Para tareas asociadas con una fecha. Hay instrucciones más completas en [[Trabajar con calendarios y fechas]].|
|''informe''|Para tareas que usted ya terminó pero quiere reportar en su próximo informe a su jefe. ~TiddlyTareas las incluye en el tiddler llamado [[Informe]]. Cuando tiene que escribir su informe, solo revise la lista de tareas terminadas en el tiddler [[Informe]], y borrar los tiddlers después de incluirlos en su informe.|
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></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='editor' macro='edit text'></div>
<!--}}}-->
Hacer clic en 'nueva meta' a la derecha crea un tiddler como este, con la etiqueta 'meta'. El tiddler se añade automaticamente al índice en el tiddler MisMetas. Refresque su tiddler MisMetas para ver su nueva meta.
<<formTiddler PlantillaParaTareas>>
<<formTiddler PlantillaParaTareas>>
<<formTiddler PlantillaParaTareas>>
El depósito es nada más que un lugar donde puede depositar información que quiere guardar para procesar cuando tiene más tiempo para hacerlo.
<<forEachTiddler where 'tiddler.tags.contains("Enviar correo electrónico")' sortBy 'tiddler.title'>>
<<forEachTiddler where 'tiddler.tags.contains("Escribir")' sortBy 'tiddler.title'>>
<<calendar thismonth>>
//~~(Part of the [[ForEachTiddlerPlugin]])~~//

Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.

''Syntax:'' 
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|


''Using JavaScript''

To give you a lot of flexibility the [[ForEachTiddlerMacro]] uses JavaScript in its arguments. Even if you are not that familiar with JavaScript you may find forEachTiddler useful. Just have a look at the various ready-to-use [[ForEachTiddlerExamples]] and adapt them to your needs.

''The Elements of the Macro''

The arguments of the ForEachTiddlerMacro consist of multiple parts, each of them being optional.

<<slider chkFETInClause [[inClause]] "inClause" "inClause">>
<<slider chkFETWhereClause [[whereClause]] "whereClause" "whereClause">>
<<slider chkFETSortClause [[sortClause]] "sortClause" "sortClause">>
<<slider chkFETScriptClause [[scriptClause]] "scriptClause" "scriptClause">>
<<slider chkFETActions [[Action Specification]] "Action Specification" "Action Specification">>

''Using Macros and ">" inside the forEachTiddler Macro''

You may use other macro calls into the expression, especially in the actionParameters. To avoid that the {{{>>}}} of such a macro call is misinterpreted as the end of the {{{<<forEachTiddler...>>}}} macro you must escape the {{{>>}}} of the inner macro with {{{$))}}} E.g. if you want to use {{{<<tiddler ...>>}}} inside the {{{forEachTiddler}}} macro you have to write {{{<<tiddler ...$))}}}.

In addition it is necessary to escape single {{{>}}} with the text {{{$)}}}.

''Using {{{<<tiddler ... with: ...>>}}} to re-use ForEachTiddler definitions''

Sometimes you may want to use a certain ForEachTiddler definition in slight variations. E.g. you may want to list either the tiddlers tagged with "ToDo" and in the other case with "Done". To do so you may use "Tiddler parameters". Here an example:

Replace the variable part of the ForEachTiddler definition with $1 ($2,... $9 are supported). E.g. you may create the tiddler "ListTaggedTiddlers" like this
{{{
<<forEachTiddler 
 where 
 'tiddler.tags.contains("$1")'
>>
}}}

Now you can use the ListTaggedTiddlers for various specific tags, using the {{{<<tiddler ...>>}}} macro:
{{{
<<tiddler ListTaggedTiddlers with: "systemConfig">>
}}}
{{{
<<tiddler ListTaggedTiddlers with: "Plugin">>
}}}


See also [[ForEachTiddlerExamples]].
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''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-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description

Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.

''Syntax:'' 
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]]  is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|

See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].

!Revision history
* v1.0.8 (2007-04-12)
** Adapted to latest TiddlyWiki 2.2 Beta importTiddlyWiki API (introduced with changeset 2004). TiddlyWiki 2.2 Beta builds prior to changeset 2004 are no longer supported (but TiddlyWiki 2.1 and earlier, of cause)
* v1.0.7 (2007-03-28)
** Also support "pre" formatted TiddlyWikis (introduced with TW 2.2) (when using "in" clause to work on external tiddlers)
* v1.0.6 (2006-09-16)
** Context provides "viewerTiddler", i.e. the tiddler used to view the macro. Most times this is equal to the "inTiddler", but when using the "tiddler" macro both may be different.
** Support "begin", "end" and "none" expressions in "write" action
* v1.0.5 (2006-02-05)
** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.
** Support Firefox 1.5.0.1
** Internal
*** Make "JSLint" conform
*** "Only install once"
* v1.0.4 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.3 (2005-12-22)
** Features: 
*** Write output to a file supports multi-byte environments (Thanks to Bram Chen) 
*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)
** Enhancements:
*** Improved error messages on InternetExplorer.
* v1.0.2 (2005-12-10)
** Features: 
*** context object also holds reference to store (TiddlyWiki)
** Fixed Bugs: 
*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)
* v1.0.1 (2005-12-08)
** Features: 
*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".
*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.
*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).
*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .
*** Improved script evaluation (for where/sort clause and write scripts).
* v1.0.0 (2005-11-20)
** initial version

!Code
***/
//{{{

	
//============================================================================
//============================================================================
//		   ForEachTiddlerPlugin
//============================================================================
//============================================================================

// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {

if (!window.abego) window.abego = {};

version.extensions.ForEachTiddlerPlugin = {
	major: 1, minor: 0, revision: 8, 
	date: new Date(2007,3,12), 
	source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
	licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
	copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};

// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
	TiddlyWiki.prototype.forEachTiddler = function(callback) {
		for(var t in this.tiddlers) {
			callback.call(this,t,this.tiddlers[t]);
		}
	};
}

//============================================================================
// forEachTiddler Macro
//============================================================================

version.extensions.forEachTiddler = {
	major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};

// ---------------------------------------------------------------------------
// Configurations and constants 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler = {
	 // Standard Properties
	 label: "forEachTiddler",
	 prompt: "Perform actions on a (sorted) selection of tiddlers",

	 // actions
	 actions: {
		 addToList: {},
		 write: {}
	 }
};

// ---------------------------------------------------------------------------
//  The forEachTiddler Macro Handler 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler.getContainingTiddler = function(e) {
	while(e && !hasClass(e,"tiddler"))
		e = e.parentNode;
	var title = e ? e.getAttribute("tiddler") : null; 
	return title ? store.getTiddler(title) : null;
};

config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);

	if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
	// --- Parsing ------------------------------------------

	var i = 0; // index running over the params
	// Parse the "in" clause
	var tiddlyWikiPath = undefined;
	if ((i < params.length) && params[i] == "in") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "TiddlyWiki path expected behind 'in'.");
			return;
		}
		tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the where clause
	var whereClause ="true";
	if ((i < params.length) && params[i] == "where") {
		i++;
		whereClause = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the sort stuff
	var sortClause = null;
	var sortAscending = true; 
	if ((i < params.length) && params[i] == "sortBy") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "sortClause missing behind 'sortBy'.");
			return;
		}
		sortClause = this.paramEncode(params[i]);
		i++;

		if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
			 sortAscending = params[i] == "ascending";
			 i++;
		}
	}

	// Parse the script
	var scriptText = null;
	if ((i < params.length) && params[i] == "script") {
		i++;
		scriptText = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the action. 
	// When we are already at the end use the default action
	var actionName = "addToList";
	if (i < params.length) {
	   if (!config.macros.forEachTiddler.actions[params[i]]) {
			this.handleError(place, "Unknown action '"+params[i]+"'.");
			return;
		} else {
			actionName = params[i]; 
			i++;
		}
	} 
	
	// Get the action parameter
	// (the parsing is done inside the individual action implementation.)
	var actionParameter = params.slice(i);


	// --- Processing ------------------------------------------
	try {
		this.performMacro({
				place: place, 
				inTiddler: tiddler,
				whereClause: whereClause, 
				sortClause: sortClause, 
				sortAscending: sortAscending, 
				actionName: actionName, 
				actionParameter: actionParameter, 
				scriptText: scriptText, 
				tiddlyWikiPath: tiddlyWikiPath});

	} catch (e) {
		this.handleError(place, e);
	}
};

// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {

	var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);

	var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
	context["tiddlyWiki"] = tiddlyWiki;
	
	// Get the tiddlers, as defined by the whereClause
	var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
	context["tiddlers"] = tiddlers;

	// Sort the tiddlers, when sorting is required.
	if (parameter.sortClause) {
		this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
	}

	return {tiddlers: tiddlers, context: context};
};

// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
	return this.getTiddlersAndContext(parameter).tiddlers;
};

// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
//				  The following properties are supported:
//
//						place
//						whereClause
//						sortClause
//						sortAscending
//						actionName
//						actionParameter
//						scriptText
//						tiddlyWikiPath
//
//					All properties are optional. 
//					For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = fu