Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
11463 lines (10548 sloc) 465 KB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<html xmlns="" xml:lang="en" lang="en">
<script id="versionArea" type="text/javascript">
var version = {title: "TiddlyWiki", major: 2, minor: 8, revision: 1, date: new Date("June 23, 2013"), extensions: {}};
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="copyright" content="
TiddlyWiki created by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)
Copyright (c) Jeremy Ruston 2004-2007
Copyright (c) UnaMesa Association 2007-2012
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of the UnaMesa Association nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
" />
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<title> - </title>
<style id="styleArea" type="text/css">
#saveTest {display:none;}
#messageArea {display:none;}
#copyright {display:none;}
#storeArea {display:none;}
#storeArea div {padding:0.5em; margin:1em 0em 0em 0em; border-color:#fff #666 #444 #ddd; border-style:solid; border-width:2px; overflow:auto;}
#shadowArea {display:none;}
#javascriptWarning {width:100%; text-align:center; font-weight:bold; background-color:#dd1100; color:#fff; padding:1em 0em;}
<body onload="main();" onunload="if(window.unload) unload();">
<div id="copyright">
Welcome to TiddlyWiki created by Jeremy Ruston; Copyright &copy; 2004-2007 Jeremy Ruston, Copyright &copy; 2007-2011 UnaMesa Association
<div id="javascriptWarning">
This page requires JavaScript to function properly.<br /><br />If you are using Microsoft Internet Explorer you may need to click on the yellow bar above and select 'Allow Blocked Content'. You must then click 'Yes' on the following security warning.
<div id="saveTest"></div>
<div id="backstageCloak"></div>
<div id="backstageButton"></div>
<div id="backstageArea"><div id="backstageToolbar"></div></div>
<div id="backstage">
<div id="backstagePanel"></div>
<div id="contentWrapper"></div>
<div id="contentStash"></div>
<div id="shadowArea">
<div title="ColorPalette">
<pre>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
<div title="EditTemplate">
&lt;div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'&gt;&lt;/div&gt;
&lt;div class='title' macro='view title'&gt;&lt;/div&gt;
&lt;div class='editor' macro='edit title'&gt;&lt;/div&gt;
&lt;div macro='annotations'&gt;&lt;/div&gt;
&lt;div class='editor' macro='edit text'&gt;&lt;/div&gt;
&lt;div class='editor' macro='edit tags'&gt;&lt;/div&gt;&lt;div class='editorFooter'&gt;&lt;span macro='message views.editor.tagPrompt'&gt;&lt;/span&gt;&lt;span macro='tagChooser excludeLists'&gt;&lt;/span&gt;&lt;/div&gt;
<div title="GettingStarted">
<pre>To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] &amp; [[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: &lt;&lt;option txtUserName&gt;&gt;
<div title="ImportTiddlers">
<div title="MarkupPreHead">
&lt;link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' /&gt;
<div title="OptionsPanel">
<pre>These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser
Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])
&lt;&lt;option txtUserName&gt;&gt;
&lt;&lt;option chkSaveBackups&gt;&gt; [[SaveBackups]]
&lt;&lt;option chkAutoSave&gt;&gt; [[AutoSave]]
&lt;&lt;option chkRegExpSearch&gt;&gt; [[RegExpSearch]]
&lt;&lt;option chkCaseSensitiveSearch&gt;&gt; [[CaseSensitiveSearch]]
&lt;&lt;option chkAnimate&gt;&gt; [[EnableAnimations]]
Also see [[AdvancedOptions]]
<div title="PageTemplate">
&lt;div class='header' role='banner' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'&gt;
&lt;div class='headerShadow'&gt;
&lt;span class='siteTitle' refresh='content' tiddler='SiteTitle'&gt;&lt;/span&gt;&amp;nbsp;
&lt;span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'&gt;&lt;/span&gt;
&lt;div class='headerForeground'&gt;
&lt;span class='siteTitle' refresh='content' tiddler='SiteTitle'&gt;&lt;/span&gt;&amp;nbsp;
&lt;span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'&gt;&lt;/span&gt;
&lt;div id='mainMenu' role='navigation' refresh='content' tiddler='MainMenu'&gt;&lt;/div&gt;
&lt;div id='sidebar'&gt;
&lt;div id='sidebarOptions' role='navigation' refresh='content' tiddler='SideBarOptions'&gt;&lt;/div&gt;
&lt;div id='sidebarTabs' role='complementary' refresh='content' force='true' tiddler='SideBarTabs'&gt;&lt;/div&gt;
&lt;div id='displayArea' role='main'&gt;
&lt;div id='messageArea'&gt;&lt;/div&gt;
&lt;div id='tiddlerDisplay'&gt;&lt;/div&gt;
<div title="StyleSheetColors">
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]];
border-left:1px solid [[ColorPalette::TertiaryLight]];
border-top:1px solid [[ColorPalette::TertiaryLight]];
border-right:1px solid [[ColorPalette::TertiaryLight]];
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}
#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}
.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}
#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}
.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}
.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}
.tiddler .defaultCommand {font-weight:bold;}
.shadow .title {color:[[ColorPalette::TertiaryDark]];}
.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}
.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}
.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}
.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}
.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]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}
#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);}
<div title="StyleSheetLayout">
* html .tiddler {height:1%;}
body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}
h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}
hr {height:1px;}
a {text-decoration:none;}
dt {font-weight:bold;}
ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}
.txtOptionInput {width:11em;}
#contentWrapper .chkOptionInput {border:0;}
.externalLink {text-decoration:underline;}
.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}
.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}
/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}
#mainMenu .tiddlyLinkExisting,
#mainMenu .tiddlyLinkNonExisting,
#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}
.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0; top:0;}
.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}
#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}
#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}
.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}
#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}
.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}
.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}
.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}
#contentWrapper {display:block;}
#splashScreen {display:none;}
#displayArea {margin:1em 17em 0 14em;}
.toolbar {text-align:right; font-size:.9em;}
.tiddler {padding:1em 1em 0;}
.missing .viewer,.missing .title {font-style:italic;}
.title {font-size:1.6em; font-weight:bold;}
.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}
.tiddler .button {padding:0.2em 0.4em;}
.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}
.footer {font-size:.9em;}
.footer li {display:inline;}
.annotation {padding:0.5em; margin:0.5em;}
* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}
.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0 3px 0 3px;}
.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}
.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0; padding-bottom:0;}
.fieldsetFix {border:0; padding:0; margin:1px 0px;}
.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}
* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}
.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
<div title="StyleSheetLocale">
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
<div title="StyleSheetPrint">
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox where print preview displays the noscript content */
<div title="ViewTemplate">
&lt;div class='toolbar' role='navigation' macro='toolbar [[ToolbarCommands::ViewToolbar]]'&gt;&lt;/div&gt;
&lt;div class='title' macro='view title'&gt;&lt;/div&gt;
&lt;div class='subtitle'&gt;&lt;span macro='view modifier link'&gt;&lt;/span&gt;, &lt;span macro='view modified date'&gt;&lt;/span&gt; (&lt;span macro='message views.wikified.createdPrompt'&gt;&lt;/span&gt; &lt;span macro='view created date'&gt;&lt;/span&gt;)&lt;/div&gt;
&lt;div class='tagging' macro='tagging'&gt;&lt;/div&gt;
&lt;div class='tagged' macro='tags'&gt;&lt;/div&gt;
&lt;div class='viewer' macro='view text wikified'&gt;&lt;/div&gt;
&lt;div class='tagClear'&gt;&lt;/div&gt;
<div id="storeArea">
<div title="CalendarPlugin" modifier="AlexTsui" created="200807230358" modified="200901262203" tags="systemConfig systemTiddlers">
|Author|Eric Shulman|
|Original Author|SteveRumsby|
|Description|display monthly and yearly calendars|
NOTE: For enhanced date display (including popups), you must also install [[DatePlugin]]
|{{{&lt;&lt;calendar&gt;&gt;}}}|Produce a full-year calendar for the current year|
|{{{&lt;&lt;calendar year&gt;&gt;}}}|Produce a full-year calendar for the given year|
|{{{&lt;&lt;calendar year month&gt;&gt;}}}|Produce a one-month calendar for the given month and year|
|{{{&lt;&lt;calendar thismonth&gt;&gt;}}}|Produce a one-month calendar for the current month|
|{{{&lt;&lt;calendar lastmonth&gt;&gt;}}}|Produce a one-month calendar for last month|
|{{{&lt;&lt;calendar nextmonth&gt;&gt;}}}|Produce a one-month calendar for next month|
|{{{&lt;&lt;calendar +n&gt;&gt;}}}&lt;br&gt;{{{&lt;&lt;calendar -n&gt;&gt;}}}|Produce a one-month calendar for a month +/- 'n' months from now|
|''First day of week:''&lt;br&gt;{{{config.options.txtCalFirstDay}}}|&lt;&lt;option txtCalFirstDay&gt;&gt;|(Monday = 0, Sunday = 6)|
|''First day of weekend:''&lt;br&gt;{{{config.options.txtCalStartOfWeekend}}}|&lt;&lt;option txtCalStartOfWeekend&gt;&gt;|(Monday = 0, Sunday = 6)|
&lt;&lt;option chkDisplayWeekNumbers&gt;&gt; Display week numbers //(note: Monday will be used as the start of the week)//
|''Week number display format:''&lt;br&gt;{{{config.options.txtWeekNumberDisplayFormat }}}|&lt;&lt;option txtWeekNumberDisplayFormat &gt;&gt;|
|''Week number link format:''&lt;br&gt;{{{config.options.txtWeekNumberLinkFormat }}}|&lt;&lt;option txtWeekNumberLinkFormat &gt;&gt;|
2008.09.10: added &quot;+n&quot; (and &quot;-n&quot;) param to permit display of relative months (e.g., &quot;+6&quot; means &quot;six months from now&quot;, &quot;-3&quot; means &quot;three months ago&quot;. Based on suggestion from Jean.
2008.06.17: added support for config.macros.calendar.todaybg
2008.02.27: in handler(), DON'T set hard-coded default date format, so that *customized* value (pre-defined in config.macros.calendar.journalDateFmt is used.
2008.02.17: in createCalendarYear(), fix next/previous year calculation (use parseInt() to convert to numeric value). Also, use journalDateFmt for date linking when NOT using [[DatePlugin]].
2008.02.16: in createCalendarDay(), week numbers now created as TiddlyLinks, allowing quick creation/navigation to 'weekly' journals (based on request from Kashgarinn)
2008.01.08: in createCalendarMonthHeader(), &quot;month year&quot; heading is now created as TiddlyLink, allowing quick creation/navigation to 'month-at-a-time' journals
2007.11.30: added &quot;return false&quot; to onclick handlers (prevent IE from opening blank pages)
2006.08.23: added handling for weeknumbers (code supplied by Martin Budden (see &quot;wn**&quot; comment marks). Also, incorporated updated by Jeremy Sheeley to add caching for reminders (see [[ReminderMacros]], if installed)
2005.10.30: in config.macros.calendar.handler(), use &quot;tbody&quot; element for IE compatibility. Also, fix year calculation for IE's getYear() function (which returns '2005' instead of '105'). Also, in createCalendarDays(), use showDate() function (see [[DatePlugin]], if installed) to render autostyled date with linked popup. Updated calendar stylesheet definition: use .calendar class-specific selectors, add text centering and margin settings
2006.05.29: added journalDateFmt handling
!!!!!Code section:
version.extensions.CalendarPlugin= { major: 0, minor: 7, revision: 0, date: new Date(2008, 6, 17)};
if(config.options.txtCalFirstDay == undefined)
config.options.txtCalFirstDay = 0;
if(config.options.txtCalStartOfWeekend == undefined)
config.options.txtCalStartOfWeekend = 5;
if(config.options.chkDisplayWeekNumbers == undefined)//wn**
config.options.chkDisplayWeekNumbers = false;
config.options.txtCalFirstDay = 0;
if(config.options.txtWeekNumberDisplayFormat == undefined)//wn**
config.options.txtWeekNumberDisplayFormat = &quot;w0WW&quot;;
if(config.options.txtWeekNumberLinkFormat == undefined)//wn**
config.options.txtWeekNumberLinkFormat = &quot;YYYY-w0WW&quot;;
config.macros.calendar = {};
config.macros.calendar.monthnames = [&quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;, &quot;Apr&quot;, &quot;May&quot;, &quot;Jun&quot;, &quot;Jul&quot;, &quot;Aug&quot;, &quot;Sep&quot;, &quot;Oct&quot;, &quot;Nov&quot;, &quot;Dec&quot;];
config.macros.calendar.daynames = [&quot;M&quot;, &quot;T&quot;, &quot;W&quot;, &quot;T&quot;, &quot;F&quot;, &quot;S&quot;, &quot;S&quot;];
config.macros.calendar.todaybg = &quot;#ccccff&quot;;
config.macros.calendar.weekendbg = &quot;#c0c0c0&quot;;
config.macros.calendar.monthbg = &quot;#e0e0e0&quot;;
config.macros.calendar.holidaybg = &quot;#ffc0c0&quot;;
config.macros.calendar.journalDateFmt = &quot;DD MMM YYYY&quot;;
config.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
config.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead
function calendarIsHoliday(date) // Is the given date a holiday?
var longHoliday = date.formatString(&quot;0DD/0MM/YYYY&quot;);
var shortHoliday = date.formatString(&quot;0DD/0MM&quot;);
for(var i = 0; i &lt; config.macros.calendar.holidays.length; i++) {
if(config.macros.calendar.holidays[i] == longHoliday || config.macros.calendar.holidays[i] == shortHoliday)
return true;
return false;
config.macros.calendar.handler = function(place,macroName,params) {
var calendar = createTiddlyElement(place, &quot;table&quot;, null, &quot;calendar&quot;, null);
var tbody = createTiddlyElement(calendar, &quot;tbody&quot;, null, null, null);
var today = new Date();
var year = today.getYear();
if (year&lt;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(&quot;SideBarOptions&quot;);
var re = new RegExp(&quot;&lt;&lt;(?:newJournal)([^&gt;]*)&gt;&gt;&quot;,&quot;mg&quot;); var fm = re.exec(text);
if (fm &amp;&amp; fm[1]!=null) { var pa=fm[1].readMacroParams(); if (pa[0]) this.journalDateFmt = pa[0]; }
var month=-1;
if (params[0] == &quot;thismonth&quot;) {
var month=today.getMonth();
} else if (params[0] == &quot;lastmonth&quot;) {
var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
} else if (params[0] == &quot;nextmonth&quot;) {
var month = today.getMonth()+1; if (month&gt;11) { month=0; year++; }
} else if (params[0]&amp;&amp;&quot;+-&quot;.indexOf(params[0].substr(0,1))!=-1) {
var month = today.getMonth()+parseInt(params[0]);
if (month&gt;11) { year+=Math.floor(month/12); month%=12; };
if (month&lt;0) { year+=Math.floor(month/12); month=12+month%12; }
} else if (params[0]) {
year = params[0];
if(params[1]) month=parseInt(params[1])-1;
if (month&gt;11) month=11; if (month&lt;0) month=0;
if (month!=-1) {
cacheReminders(new Date(year, month, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, month);
} 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 &lt; 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][&quot;matchedDate&quot;]] = &quot;reminder:&quot; + t[i][&quot;params&quot;][&quot;title&quot;];
function createCalendarOneMonth(calendar, year, mon)
var row = createTiddlyElement(calendar, &quot;tr&quot;, null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + &quot; &quot; + year, true, year, mon);
row = createTiddlyElement(calendar, &quot;tr&quot;, null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
function createCalendarMonth(calendar, year, mon)
var row = createTiddlyElement(calendar, &quot;tr&quot;, null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + &quot; &quot; + year, false, year, mon);
row = createTiddlyElement(calendar, &quot;tr&quot;, null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
function createCalendarYear(calendar, year)
var row;
row = createTiddlyElement(calendar, &quot;tr&quot;, null, null, null);
var back = createTiddlyElement(row, &quot;td&quot;, null, null, null);
var backHandler = function() {
createCalendarYear(calendar, parseInt(year)-1);
return false; // consume click
createTiddlyButton(back, &quot;&lt;&quot;, &quot;Previous year&quot;, backHandler);
back.align = &quot;center&quot;;
var yearHeader = createTiddlyElement(row, &quot;td&quot;, null, &quot;calendarYear&quot;, year);
yearHeader.align = &quot;center&quot;;
var fwd = createTiddlyElement(row, &quot;td&quot;, null, null, null);
var fwdHandler = function() {
createCalendarYear(calendar, parseInt(year)+1);
return false; // consume click
createTiddlyButton(fwd, &quot;&gt;&quot;, &quot;Next year&quot;, fwdHandler);
fwd.align = &quot;center&quot;;
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, &quot;tr&quot;, 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, &quot;tr&quot;, 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, &quot;td&quot;, null, null, null);
back.align = &quot;center&quot;; = config.macros.calendar.monthbg;
var backMonHandler = function() {
var newyear = year;
var newmon = mon-1;
if(newmon == -1) { newmon = 11; newyear = newyear-1;}
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
return false; // consume click
createTiddlyButton(back, &quot;&lt;&quot;, &quot;Previous month&quot;, backMonHandler);
month = createTiddlyElement(row, &quot;td&quot;, null, &quot;calendarMonthname&quot;)
month.setAttribute(&quot;colSpan&quot;, config.options.chkDisplayWeekNumbers?6:5);//wn**
var fwd = createTiddlyElement(row, &quot;td&quot;, null, null, null);
fwd.align = &quot;center&quot;; = config.macros.calendar.monthbg;
var fwdMonHandler = function() {
var newyear = year;
var newmon = mon+1;
if(newmon == 12) { newmon = 0; newyear = newyear+1;}
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
return false; // consume click
createTiddlyButton(fwd, &quot;&gt;&quot;, &quot;Next month&quot;, fwdMonHandler);
} else {
month = createTiddlyElement(row, &quot;td&quot;, null, &quot;calendarMonthname&quot;, name)
month.align = &quot;center&quot;; = config.macros.calendar.monthbg;
function createCalendarDayHeader(row, num)
var cell;
for(var i = 0; i &lt; num; i++) {
if (config.options.chkDisplayWeekNumbers) createTiddlyElement(row, &quot;td&quot;);//wn**
for(var j = 0; j &lt; 7; j++) {
var d = j + (config.options.txtCalFirstDay - 0);
if(d &gt; 6) d = d - 7;
cell = createTiddlyElement(row, &quot;td&quot;, null, null, config.macros.calendar.daynames[d]);
if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1)) = config.macros.calendar.weekendbg;
function createCalendarDays(row, col, first, max, year, mon) {
var i;
if (config.options.chkDisplayWeekNumbers){
if (first&lt;=max) {
var ww = new Date(year,mon,first);
var td=createTiddlyElement(row, &quot;td&quot;);//wn**
var link=createTiddlyLink(td,ww.formatString(config.options.txtWeekNumberLinkFormat),false);
else createTiddlyElement(row, &quot;td&quot;, null, null, null);//wn**
for(i = 0; i &lt; col; i++)
createTiddlyElement(row, &quot;td&quot;, null, null, null);
var day = first;
for(i = col; i &lt; 7; i++) {
var d = i + (config.options.txtCalFirstDay - 0);
if(d &gt; 6) d = d - 7;
var daycell = createTiddlyElement(row, &quot;td&quot;, null, null, null);
var isaWeekend = ((d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))? true:false);
if(day &gt; 0 &amp;&amp; day &lt;= max) {
var celldate = new Date(year, mon, day);
// ELS 2005.10.30: use &lt;&lt;date&gt;&gt; macro's showDate() function to create popup
// ELS 5/29/06 - use journalDateFmt
if (window.showDate)
showDate(daycell,celldate,&quot;popup&quot;,&quot;DD&quot;,config.macros.calendar.journalDateFmt,true, isaWeekend);
else {
if(isaWeekend) = config.macros.calendar.weekendbg;
var title = celldate.formatString(config.macros.calendar.journalDateFmt);
if(calendarIsHoliday(celldate)) = config.macros.calendar.holidaybg;
var now=new Date();
if ((now-celldate&gt;=0) &amp;&amp; (now-celldate&lt;86400000)) // is today? = config.macros.calendar.todaybg;
if(window.findTiddlersWithReminders == null) {
var link = createTiddlyLink(daycell, title, false);
} else
var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
// 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 &lt;hr&gt;
// * the list of reminders for that date
// NOTE: The following code is only used when [[DatePlugin]] is not present
function onClickCalendarDate(e)
var button = this;
var date = button.getAttribute(&quot;title&quot;);
var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));
date = dat.formatString(config.macros.calendar.journalDateFmt);
var popup = createTiddlerPopup(this);
var newReminder = function() {
var t = store.getTiddlers(date);
displayTiddler(null, date, 2, null, null, false, false);
if(t) {
document.getElementById(&quot;editorBody&quot; + date).value += &quot;\n&lt;&lt;reminder day:&quot; + dat.getDate() +
&quot; month:&quot; + (dat.getMonth()+1) + &quot; year:&quot; + (dat.getYear()+1900) + &quot; title: &gt;&gt;&quot;;
} else {
document.getElementById(&quot;editorBody&quot; + date).value = &quot;&lt;&lt;reminder day:&quot; + dat.getDate() +
&quot; month:&quot; + (dat.getMonth()+1) +&quot; year:&quot; + (dat.getYear()+1900) + &quot; title: &gt;&gt;&quot;;
return false; // consume click
var link = createTiddlyButton(popup, &quot;New reminder&quot;, null, newReminder);
var t = findTiddlersWithReminders(dat, [0,14], null, 1);
for(var i = 0; i &lt; t.length; i++) {
link = createTiddlyLink(popup, t[i].tiddler, false);
return false; // consume click
function calendarMaxDays(year, mon)
var max = config.macros.calendar.monthdays[mon];
if(mon == 1 &amp;&amp; (year % 4) == 0 &amp;&amp; ((year % 100) != 0 || (year % 400) == 0)) max++;
return max;
function createCalendarDayRows(cal, year, mon)
var row = createTiddlyElement(cal, &quot;tr&quot;, null, null, null);
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 &lt; 0) first1 = first1 + 7;
var day1 = -first1 + 1;
var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first2 &lt; 0) first2 = first2 + 7;
var day2 = -first2 + 1;
var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first3 &lt; 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 &lt;= max1 || day2 &lt;= max2 || day3 &lt;= max3) {
row = createTiddlyElement(cal, &quot;tr&quot;, 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, &quot;tr&quot;, null, null, null);
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 &lt; 0) first1 = first1+ 7;
var day1 = -first1 + 1;
var max1 = calendarMaxDays(year, mon);
while(day1 &lt;= max1) {
row = createTiddlyElement(cal, &quot;tr&quot;, null, null, null);
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
setStylesheet(&quot;.calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }&quot;, &quot;calendarStyles&quot;);
<div title="CheckboxPlugin" modifier="atsui" created="201405012343" tags="systemConfig systemTiddlers">
|Author|Eric Shulman|
|Description|Add checkboxes to your tiddler content|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content. Checkbox states are preserved by:
* by setting/removing tags on specified tiddlers,
* or, by setting custom field values on specified tiddlers,
* or, by saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler content (deprecated)
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data. In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
&gt;see [[CheckboxPluginInfo]]
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global &quot;; to current checkbox element when processing checkbox clicks. This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using &quot;story.findContainingTiddler(place)&quot;. Also, wrap handlers in &quot;function()&quot; so &quot;return&quot; can be used within handler code.
|please see [[CheckboxPluginInfo]] for additional revision details|
2005.12.07 [0.9.0] initial BETA release
version.extensions.CheckboxPlugin = {major: 2, minor: 4, revision:0 , date: new Date(2008,1,5)};
config.checkbox = { refresh: { tagged:true, tagging:true, container:true } };
config.formatters.push( {
name: &quot;checkbox&quot;,
match: &quot;\\[[xX_ ][\\]\\=\\(\\{]&quot;,
lookahead: &quot;\\[([xX_ ])(=[^\\s\\(\\]{]+)?(\\([^\\)]*\\))?({[^}]*})?({[^}]*})?({[^}]*})?\\]&quot;,
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,&quot;mg&quot;);
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch &amp;&amp; lookaheadMatch.index == w.matchStart) {
// get params
var checked=(lookaheadMatch[1].toUpperCase()==&quot;X&quot;);
var id=lookaheadMatch[2];
var target=lookaheadMatch[3];
if (target) target=target.substr(1,target.length-2).trim(); // trim off parentheses
var fn_init=lookaheadMatch[4];
var fn_clickBefore=lookaheadMatch[5];
var fn_clickAfter=lookaheadMatch[6];
var tid=story.findContainingTiddler(w.output); if (tid) tid=tid.getAttribute(&quot;tiddler&quot;);
var srctid=w.tiddler?w.tiddler.title:null;
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(&quot;tiddler&quot;))
var srcpos=0; // &quot;inline X&quot; not applicable to macro syntax
var target=params.shift(); if (!target) target=&quot;&quot;;
var defaultState=params[0]==&quot;checked&quot;; if (defaultState) params.shift();
var id=params.shift(); if (id &amp;&amp; !id.length) id=null;
var fn_init=params.shift(); if (fn_init &amp;&amp; !fn_init.length) fn_init=null;
var fn_clickBefore=params.shift();
if (fn_clickBefore &amp;&amp; !fn_clickBefore.length) fn_clickBefore=null;
var fn_clickAfter=params.shift();
if (fn_clickAfter &amp;&amp; !fn_clickAfter.length) fn_clickAfter=null;
var refresh={ tagged:true, tagging:true, container:false };
create: function(place,tid,srctid,srcpos,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter) {
// create checkbox element
var c = document.createElement(&quot;input&quot;);
c.srctid=srctid; // remember source tiddler
c.srcpos=srcpos; // remember location of &quot;X&quot;
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;
// set default state
// track state in config.options.ID
if (id) {; // trim off leading &quot;=&quot;
if (config.options[]!=undefined)
// track state in (tiddlername|tagname) or (fieldname@tiddlername)
if (target) {
var pos=target.indexOf(&quot;@&quot;);
if (pos!=-1) {
c.field=pos?target.substr(0,pos):&quot;checked&quot;; // get fieldname (or use default &quot;checked&quot;)
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)==&quot;true&quot;); // set checkbox from saved state
} else {
var pos=target.indexOf(&quot;|&quot;); if (pos==-1) var pos=target.indexOf(&quot;:&quot;);
if (pos==0) c.tag=target.substr(1); // trim leading &quot;|&quot; or &quot;:&quot;
if (pos&gt;0) { c.tiddler=target.substr(0,pos); c.tag=target.substr(pos+1); }
if (!c.tag.length) c.tag=&quot;checked&quot;;
var t=store.getTiddler(c.tiddler);
if (t &amp;&amp; t.tags)
c.checked=t.isTagged(c.tag); // set checkbox from saved state
// trim off surrounding { and } delimiters from init/click handlers
if (fn_init) c.fn_init=&quot;(function(){&quot;+fn_init.trim().substr(1,fn_init.length-2)+&quot;})()&quot;;
if (fn_clickBefore) c.fn_clickBefore=&quot;(function(){&quot;+fn_clickBefore.trim().substr(1,fn_clickBefore.length-2)+&quot;})()&quot;;
if (fn_clickAfter) c.fn_clickAfter=&quot;(function(){&quot;+fn_clickAfter.trim().substr(1,fn_clickAfter.length-2)+&quot;})()&quot;;
c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie
onClickCheckbox: function(event) {;
if (this.init &amp;&amp; this.fn_init) // custom function hook to set initial state (run only once)
{ try { eval(this.fn_init); } catch(e) { displayMessage(&quot;Checkbox init error: &quot;+e.toString()); } }
if (!this.init &amp;&amp; this.fn_clickBefore) // custom function hook to override changes in checkbox state
{ try { eval(this.fn_clickBefore) } catch(e) { displayMessage(&quot;Checkbox onClickBefore error: &quot;+e.toString()); } }
if (
// save state in config AND cookie (only when ID starts with 'chk')
{ config.options[]=this.checked; if (,3)==&quot;chk&quot;) saveOptionCookie(; }
if (this.srctid &amp;&amp; this.srcpos&gt;0 &amp;&amp; (! ||,3)!=&quot;chk&quot;) &amp;&amp; !this.tag &amp;&amp; !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 &amp;&amp; this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()==&quot;X&quot;)) { // if changed
if (!story.isDirty(t.title)) story.refreshTiddler(t.title,null,true);
if (this.field) {
if (this.checked &amp;&amp; !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,&quot;&quot;,config.options.txtUserName,new Date());
// set the field value in the target tiddler
// DEBUG: displayMessage(this.field+&quot;@&quot;+this.tiddler+&quot; is &quot;+this.checked);
if (this.tag) {
if (this.checked &amp;&amp; !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,&quot;&quot;,config.options.txtUserName,new Date());
var t=store.getTiddler(this.tiddler);
if (t) {
var tagged=(t.tags &amp;&amp; t.tags.indexOf(this.tag)!=-1);
if (this.checked &amp;&amp; !tagged) { t.tags.push(this.tag); store.setDirty(true); }
if (!this.checked &amp;&amp; tagged) { t.tags.splice(t.tags.indexOf(this.tag),1); store.setDirty(true); }
// if tag state has been changed, update display of corresponding tiddlers (unless they are in edit mode...)
if (this.checked!=tagged) {
if (this.refresh.tagged) {
if (!story.isDirty(this.tiddler)) // the TAGGED tiddler in view mode
else // 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
if (!this.init &amp;&amp; this.fn_clickAfter) // custom function hook to react to changes in checkbox state
{ try { eval(this.fn_clickAfter) } catch(e) { displayMessage(&quot;Checkbox onClickAfter error: &quot;+e.toString()); } }
// refresh containing tiddler (but not during initial rendering, or we get an infinite loop!) (and not when editing container)
if (!this.init &amp;&amp; this.refresh.container &amp;&amp; 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,&quot;tags&quot;);
if (!tagfield||tagfield.getAttribute(&quot;edit&quot;)!=&quot;tags&quot;) 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&lt;tags.length;t++) tags[t]=String.encodeTiddlyLink(tags[t]);
tagfield.value=tags.join(&quot; &quot;); // reassemble tag string (with brackets as needed)
<div title="DefaultTiddlers" modifier="atsui" created="200807250312" modified="201502150252" changecount="1">
<div title="Examples" creator="atsui" modifier="atsui" created="201502150251" modified="201502150255" changecount="12">
# Edit a tiddler by double-clicking. Try setting SiteTitle and SiteSubtitle.
# Make a new tiddler with camel case like so: ExampleTiddler
# Click 'save changes' on the right hand side.
\( \sum_i x_i = 0 \)
See NestedSlidersPluginInfo for examples.
[ ] CheckboxPlugin
[X] Check it out</pre>
<div title="ImageSizePlugin" modifier="atsui" created="201409081829" tags="systemConfig">
|Author|Eric Shulman|
|Description|adds support for resizing images|
This plugin adds optional syntax to scale an image to a specified width and height and/or interactively resize the image with the mouse.
The extended image syntax is:
where ''(w,h)'' indicates the desired width and height (in CSS units, e.g., px, em, cm, in, or %). Use ''auto'' (or a blank value) for either dimension to scale that dimension proportionally (i.e., maintain the aspect ratio). You can also calculate a CSS value 'on-the-fly' by using a //javascript expression// enclosed between &quot;&quot;&quot;{{&quot;&quot;&quot; and &quot;&quot;&quot;}}&quot;&quot;&quot;. Appending a plus sign (+) to a dimension enables interactive resizing in that dimension (by dragging the mouse inside the image). Use ~SHIFT-click to show the full-sized (un-scaled) image. Use ~CTRL-click to restore the starting size (either scaled or full-sized).
[&lt;img(21% ,+)[images/meow.gif]]
[&lt;img(13%+, )[images/meow.gif]]
[&lt;img( 8%+, )[images/meow.gif]]
[&lt;img( 5% , )[images/meow.gif]]
[&lt;img( 3% , )[images/meow.gif]]
[&lt;img( 2% , )[images/meow.gif]]
[img( 1%+,+)[images/meow.gif]]
[&lt;img(21% ,+)[images/meow.gif]]
[&lt;img(13%+, )[images/meow.gif]]
[&lt;img( 8%+, )[images/meow.gif]]
[&lt;img( 5% , )[images/meow.gif]]
[&lt;img( 3% , )[images/meow.gif]]
[&lt;img( 2% , )[images/meow.gif]]
[img( 1%+,+)[images/meow.gif]]
2011.09.03 [1.2.3] bypass addStretchHandlers() if no '+' suffix is used (i.e., not resizable)
2010.07.24 [1.2.2] moved tip/dragtip text to config.formatterHelpers.imageSize object to enable customization
2009.02.24 [1.2.1] cleanup width/height regexp, use '+' suffix for resizing
2009.02.22 [1.2.0] added stretchable images
2008.01.19 [1.1.0] added evaluated width/height values
2008.01.18 [1.0.1] regexp for &quot;(width,height)&quot; now passes all CSS values to browser for validation
2008.01.17 [1.0.0] initial release
version.extensions.ImageSizePlugin= {major: 1, minor: 2, revision: 3, date: new Date(2011,9,3)};
var f=config.formatters[config.formatters.findByField(&quot;name&quot;,&quot;image&quot;)];
f.handler=function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch &amp;&amp; lookaheadMatch.index == w.matchStart) {
var floatLeft=lookaheadMatch[1];
var floatRight=lookaheadMatch[2];
var width=lookaheadMatch[3];
var height=lookaheadMatch[4];
var tooltip=lookaheadMatch[5];
var src=lookaheadMatch[6];
var link=lookaheadMatch[7];
// Simple bracketted link
var e = w.output;
if(link) { // LINKED IMAGE
if (config.formatterHelpers.isExternalLink(link)) {
if (config.macros.attach &amp;&amp; config.macros.attach.isAttachment(link)) {
// see [[AttachFilePluginFormatters]]
e = createExternalLink(w.output,link);
e.title = config.macros.attach.linkTooltip + link;
} else
e = createExternalLink(w.output,link);
} else
e = createTiddlyLink(w.output,link,false,null,w.isStatic);
var img = createTiddlyElement(e,&quot;img&quot;);
if(floatLeft) img.align=&quot;left&quot;; else if(floatRight) img.align=&quot;right&quot;;
if(width||height) {
var x=width.trim(); var y=height.trim();
var stretchW=(x.substr(x.length-1,1)=='+'); if (stretchW) x=x.substr(0,x.length-1);
var stretchH=(y.substr(y.length-1,1)=='+'); if (stretchH) y=y.substr(0,y.length-1);
if (x.substr(0,2)==&quot;{{&quot;)
{ try{x=eval(x.substr(2,x.length-4))} catch(e){displayMessage(e.description||e.toString())} }
if (y.substr(0,2)==&quot;{{&quot;)
{ try{y=eval(y.substr(2,y.length-4))} catch(e){displayMessage(e.description||e.toString())} };;
if (stretchW||stretchH) config.formatterHelpers.addStretchHandlers(img,stretchW,stretchH);
if(tooltip) img.title = tooltip;
if (config.macros.attach &amp;&amp; config.macros.attach.isAttachment(src))
src=config.macros.attach.getAttachment(src); // see [[AttachFilePluginFormatters]]
else if (config.formatterHelpers.resolvePath) { // see [[ImagePathPlugin]]
if (config.browser.isIE || config.browser.isSafari) {
return false;
} else
w.nextMatch = this.lookaheadRegExp.lastIndex;
tip: 'SHIFT-CLICK=show full size, CTRL-CLICK=restore initial size',
dragtip: 'DRAG=stretch/shrink, '
config.formatterHelpers.addStretchHandlers=function(e,stretchW,stretchH) {
e.statusMsg='width=%0, height=%1';'move';;;
e.onmousedown=function(ev) { var ev=ev||window.event;
return false;
e.onmousemove=function(ev) { var ev=ev||window.event;
if (this.sizing) {
var currX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
var currY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
var newW=(currX-this.offsetLeft)/(this.startX-this.offsetLeft)*this.startW;
var newH=(currY-this.offsetTop )/(this.startY-this.offsetTop )*this.startH;
if (this.stretchW) s.width =Math.floor(Math.max(newW,this.minW))+'px';
if (this.stretchH) s.height=Math.floor(Math.max(newH,this.minH))+'px';
clearMessage(); displayMessage(this.statusMsg.format([s.width,s.height]));
return false;
e.onmouseup=function(ev) { var ev=ev||window.event;
if (ev.shiftKey) {''; }
if (ev.ctrlKey) {;; }
return false;
e.onmouseout=function(ev) { var ev=ev||window.event;
return false;
<div title="Links" modifier="AlexTsui" created="200902050610">
<pre>DEBUG Tutorial</pre>
<div title="MainMenu" modifier="atsui" created="200807230359" modified="200903200601">
<pre>&lt;&lt;calendar thismonth&gt;&gt;
<div title="MathJaxPlugin" modifier="atsui" created="201411290110" tags="systemConfig">
|''Description:''|Enable LaTeX formulas for TiddlyWiki|
|''Date:''|Feb 11, 2012|
|''Author:''|Guy Rutenberg|
|''License:''|[[BSD open source license]]|
!! Changelog
!!! 1.0.1 Feb 11, 2012
* Fixed interoperability with TiddlerBarPlugin
!! How to Use
Currently the plugin supports the following delemiters:
* &quot;&quot;&quot;\(&quot;&quot;&quot;..&quot;&quot;&quot;\)&quot;&quot;&quot; - Inline equations
* &quot;&quot;&quot;$$&quot;&quot;&quot;..&quot;&quot;&quot;$$&quot;&quot;&quot; - Displayed equations
* &quot;&quot;&quot;\[&quot;&quot;&quot;..&quot;&quot;&quot;\]&quot;&quot;&quot; - Displayed equations
!! Demo
This is an inline equation \(P(E) = {n \choose k} p^k (1-p)^{ n-k}\) and this is a displayed equation:
\[J_\alpha(x) = \sum_{m=0}^\infty \frac{(-1)^m}{m! \, \Gamma(m + \alpha + 1)}{\left({\frac{x}{2}}\right)}^{2 m + \alpha}\]
This is another displayed equation $$e=mc^2$$
!! Code
config.extensions.MathJax = {
mathJaxScript : &quot;;,
// uncomment the following line if you want to access MathJax using SSL
// mathJaxScript : &quot;;,
displayTiddler: function(TiddlerName) {
config.extensions.MathJax.displayTiddler_old.apply(this, arguments);
MathJax.Hub.Queue([&quot;Typeset&quot;, MathJax.Hub]);
jQuery.getScript(config.extensions.MathJax.mathJaxScript, function(){
extensions: [&quot;tex2jax.js&quot;],
&quot;HTML-CSS&quot;: { scale: 100 }
config.extensions.MathJax.displayTiddler_old = story.displayTiddler;
story.displayTiddler = config.extensions.MathJax.displayTiddler;
name: &quot;mathJaxFormula&quot;,
match: &quot;\\\\\\[|\\$\\$|\\\\\\(&quot;,
//lookaheadRegExp: /(?:\\\[|\$\$)((?:.|\n)*?)(?:\\\]|$$)/mg,
handler: function(w)
switch(w.matchText) {
case &quot;\\[&quot;: // displayed equations
this.lookaheadRegExp = /\\\[((?:.|\n)*?)(\\\])/mg;
case &quot;$$&quot;: // inline equations
this.lookaheadRegExp = /\$\$((?:.|\n)*?)(\$\$)/mg;
case &quot;\\(&quot;: // inline equations
this.lookaheadRegExp = /\\\(((?:.|\n)*?)(\\\))/mg;
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch &amp;&amp; lookaheadMatch.index == w.matchStart) {
w.nextMatch = this.lookaheadRegExp.lastIndex;
<div title="NestedSlidersPlugin" modifier="atsui" created="201410092008" modified="201410092008" tags="systemTiddlers systemConfig">
|Author|Eric Shulman|
|Description|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
&gt;see [[NestedSlidersPluginInfo]]
&lt;&lt;option chkFloatingSlidersAnimate&gt;&gt; allow floating sliders to animate when opening/closing
&gt;Note: This setting can cause 'clipping' problems in some versions of InternetExplorer.
&gt;In addition, for floating slider animation to occur you must also allow animation in general (see [[AdvancedOptions]]).
2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class). In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
|please see [[NestedSlidersPluginInfo]] for additional revision details|
2005.11.03 - 1.0.0 initial public release. Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
version.extensions.NestedSlidersPlugin= {major: 2, minor: 4, revision: 9, date: new Date(2008,11,15)};
// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkFloatingSlidersAnimate===undefined)
config.options.chkFloatingSlidersAnimate=false; // avoid clipping problems in IE
// default styles for 'floating' class
setStylesheet(&quot;.floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
background-color:#eee; color:#000; border:1px solid #000; text-align:left; }&quot;,&quot;floatingPanelStylesheet&quot;);
// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
window.removeCookie=function(name) {
document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
config.formatters.push( {
name: &quot;nestedSliders&quot;,
match: &quot;\\n?\\+{3}&quot;,
terminator: &quot;\\s*\\={3}\\n?&quot;,
lookahead: &quot;\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\@\\[\\&gt;]*\\^)?)?(\\*)?(\\@)?(?:\\{\\{([\\w]+[\\s\\w]*)\\{)?(\\[[^\\]]*\\])?(\\[[^\\]]*\\])?(?:\\}{3})?(\\#[^:]*\\:)?(\\&gt;)?(\\.\\.\\.)?\\s*&quot;,
handler: function(w)
lookaheadRegExp = new RegExp(this.lookahead,&quot;mg&quot;);
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch &amp;&amp; lookaheadMatch.index == w.matchStart)
var defopen=lookaheadMatch[1];
var cookiename=lookaheadMatch[2];
var header=lookaheadMatch[3];
var panelwidth=lookaheadMatch[4];
var transient=lookaheadMatch[5];
var hover=lookaheadMatch[6];
var buttonClass=lookaheadMatch[7];
var label=lookaheadMatch[8];
var openlabel=lookaheadMatch[9];
var panelID=lookaheadMatch[10];
var blockquote=lookaheadMatch[11];
var deferred=lookaheadMatch[12];
// location for rendering button and panel
var place=w.output;
// default to closed, no cookie, no accesskey, no alternate text/tip
var show=&quot;none&quot;; var cookie=&quot;&quot;; var key=&quot;&quot;;
var closedtext=&quot;&gt;&quot;; var closedtip=&quot;&quot;;
var openedtext=&quot;&lt;&quot;; var openedtip=&quot;&quot;;
// extra &quot;+&quot;, default to open
if (defopen) show=&quot;block&quot;;
// cookie, use saved open/closed state
if (cookiename) {
if (config.options[cookie]==undefined)
{ config.options[cookie] = (show==&quot;block&quot;) }
// parse label/tooltip/accesskey: [label=X|tooltip]
if (label) {
var parts=label.trim().slice(1,-1).split(&quot;|&quot;);
if (closedtext.substr(closedtext.length-2,1)==&quot;=&quot;)
{ key=closedtext.substr(closedtext.length-1,1); closedtext=closedtext.slice(0,-2); }
if (parts.length) closedtip=openedtip=parts.join(&quot;|&quot;);
else { closedtip=&quot;show &quot;+closedtext; openedtip=&quot;hide &quot;+closedtext; }
// parse alternate label/tooltip: [label|tooltip]
if (openlabel) {
var parts=openlabel.trim().slice(1,-1).split(&quot;|&quot;);
if (parts.length) openedtip=parts.join(&quot;|&quot;);
else openedtip=&quot;hide &quot;+openedtext;
var title=show=='block'?openedtext:closedtext;
var tooltip=show=='block'?openedtip:closedtip;
// create the button
if (header) { // use &quot;Hn&quot; header format instead of button/link
var lvl=(header.length&gt;5)?5:header.length;
var btn = createTiddlyElement(createTiddlyElement(place,&quot;h&quot;+lvl,null,null,null),&quot;a&quot;,null,buttonClass,title);
var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,buttonClass);
btn.innerHTML=title; // enables use of HTML entities in label
// set extra button attributes
btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
btn.defOpen=defopen!=null; // save default open/closed state (boolean)
btn.keyparam=key; // save the access key letter (&quot;&quot; if none)
if (key.length) {
btn.setAttribute(&quot;accessKey&quot;,key); // init access key
btn.onfocus=function(){this.setAttribute(&quot;accessKey&quot;,this.keyparam);}; // **reclaim** access key on focus
btn.onmouseover=function(ev) {
// optional 'open on hover' handling
if (this.getAttribute(&quot;hover&quot;)==&quot;true&quot; &amp;&amp;'none') {,ev); // close transients
onClickNestedSlider(ev); // open this slider
// mouseover on button aligns floater position with button
if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this,this.sliderPanel);
// create slider panel
var panelClass=panelwidth?&quot;floatingPanel&quot;:&quot;sliderPanel&quot;;
if (panelID) panelID=panelID.slice(1,-1); // trim off delimiters
var panel=createTiddlyElement(place,&quot;div&quot;,panelID,panelClass,null);
panel.button = btn; // so the slider panel know which button it belongs to
btn.sliderPanel=panel; // so the button knows which slider panel it belongs to
panel.defaultPanelWidth=(panelwidth &amp;&amp; panelwidth.length&gt;2)?panelwidth.slice(1,-1):&quot;&quot;;
panel.setAttribute(&quot;transient&quot;,transient==&quot;*&quot;?&quot;true&quot;:&quot;false&quot;); = show;;
panel.onmouseover=function(event) // mouseover on panel aligns floater position with button
{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this.button,this); }
// render slider (or defer until shown)
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
if ((show==&quot;block&quot;)||!deferred) {
// render now if panel is supposed to be shown or NOT deferred rendering
// align floater position with button
if (window.adjustSliderPos) window.adjustSliderPos(place,btn,panel);
else {
var src = w.source.substr(w.nextMatch);
var endpos=findMatchingDelimiter(src,&quot;+++&quot;,&quot;===&quot;);
w.nextMatch += endpos+3;
if (w.source.substr(w.nextMatch,1)==&quot;\n&quot;) w.nextMatch++;
function findMatchingDelimiter(src,starttext,endtext) {
var startpos = 0;
var endpos = src.indexOf(endtext);
// check for nested delimiters
while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
// count number of nested 'starts'
var startcount=0;
var temp = src.substring(startpos,endpos-1);
var pos=temp.indexOf(starttext);
while (pos!=-1) { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
// set up to check for additional 'starts' after adjusting endpos
// find endpos for corresponding number of matching 'ends'
while (startcount &amp;&amp; endpos!=-1) {
endpos = src.indexOf(endtext,endpos+endtext.length);
return (endpos==-1)?src.length:endpos;
if (!e) var e = window.event;
var theTarget = resolveTarget(e);
while (theTarget &amp;&amp; theTarget.sliderPanel==undefined) theTarget=theTarget.parentNode;
if (!theTarget) return false;
var theSlider = theTarget.sliderPanel;
var isOpen =!=&quot;none&quot;;
// if SHIFT-CLICK, dock panel first (see [[MoveablePanelPlugin]])
if (e.shiftKey &amp;&amp; config.macros.moveablePanel) config.macros.moveablePanel.dock(theSlider,e);
// toggle label
// toggle tooltip
// deferred rendering (if needed)
if (theSlider.getAttribute(&quot;rendered&quot;)==&quot;false&quot;) {
var place=theSlider;
if (theSlider.getAttribute(&quot;blockquote&quot;)==&quot;true&quot;)
// show/hide the slider
if(config.options.chkAnimate &amp;&amp; (!hasClass(theSlider,'floatingPanel') || config.options.chkFloatingSlidersAnimate))
anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,&quot;none&quot;));
else = isOpen ? &quot;none&quot; : &quot;block&quot;;
// reset to default width (might have been changed via plugin code);
// align floater panel position with target button
if (!isOpen &amp;&amp; window.adjustSliderPos) window.adjustSliderPos(theSlider.parentNode,theTarget,theSlider);
// if showing panel, set focus to first 'focus-able' element in panel
if (!=&quot;none&quot;) {
var ctrls=theSlider.getElementsByTagName(&quot;*&quot;);
for (var c=0; c&lt;ctrls.length; c++) {
var t=ctrls[c].tagName.toLowerCase();
if ((t==&quot;input&quot; &amp;&amp; ctrls[c].type!=&quot;hidden&quot;) || t==&quot;textarea&quot; || t==&quot;select&quot;)
{ try{ ctrls[c].focus(); } catch(err){;} break; }
var cookie=theTarget.sliderCookie;
if (cookie &amp;&amp; cookie.length) {
if (config.options[cookie]!=theTarget.defOpen) window.saveOptionCookie(cookie);
else window.removeCookie(cookie); // remove cookie if slider is in default display state
// prevent SHIFT-CLICK from being processed by browser (opens blank window... yuck!)
// prevent clicks *within* a slider button from being processed by browser
// but allow plain click to bubble up to page background (to close transients, if any)
if (e.shiftKey || theTarget!=resolveTarget(e))
{ e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); }
Popup.remove(); // close open popup (if any)
return false;
// click in document background closes transient panels
document.onclick=function(ev) { if (!ev) var ev=window.event; var target=resolveTarget(ev);
if (document.nestedSliders_savedOnClick)
var retval=document.nestedSliders_savedOnClick.apply(this,arguments);
// if click was inside a popup... leave transient panels alone
var p=target; while (p) if (hasClass(p,&quot;popup&quot;)) break; else p=p.parentNode;
if (p) return retval;
// if click was inside transient panel (or something contained by a transient panel), leave it alone
var p=target; while (p) {
if ((hasClass(p,&quot;floatingPanel&quot;)||hasClass(p,&quot;sliderPanel&quot;))&amp;&amp;p.getAttribute(&quot;transient&quot;)==&quot;true&quot;) break;
if (p) return retval;
// otherwise, find and close all transient panels...
var all=document.all?document.all:document.getElementsByTagName(&quot;DIV&quot;);
for (var i=0; i&lt;all.length; i++) {
// if it is not a transient panel, or the click was on the button that opened this panel, don't close it.
if (all[i].getAttribute(&quot;transient&quot;)!=&quot;true&quot; || all[i].button==target) continue;
// otherwise, if the panel is currently visible, close it by clicking it's button
if (all[i].style.display!=&quot;none&quot;) window.onClickNestedSlider({target:all[i].button})
if (!hasClass(all[i],&quot;floatingPanel&quot;)&amp;&amp;!hasClass(all[i],&quot;sliderPanel&quot;)) all[i].style.display=&quot;none&quot;;
return retval;
// adjust floating panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel) {
if (hasClass(panel,&quot;floatingPanel&quot;) &amp;&amp; !hasClass(panel,&quot;undocked&quot;)) {
// see [[MoveablePanelPlugin]] for use of 'undocked'
var rightEdge=document.body.offsetWidth-1;
var panelWidth=panel.offsetWidth;
var left=0;
var top=btn.offsetHeight;
if (;relative&quot; &amp;&amp; findPosX(btn)+panelWidth&gt;rightEdge) {
left-=findPosX(btn)+panelWidth-rightEdge; // shift panel relative to button
if (findPosX(btn)+left&lt;0) left=-findPosX(btn); // stay within left edge
if (!=&quot;relative&quot;) {
var left=findPosX(btn);
var top=findPosY(btn)+btn.offsetHeight;
var p=place; while (p &amp;&amp; !hasClass(p,'floatingPanel')) p=p.parentNode;
if (p) { left-=findPosX(p); top-=findPosY(p); }
if (left+panelWidth&gt;rightEdge) left=rightEdge-panelWidth;
if (left&lt;0) left=0;
// TW2.1 and earlier:
// hijack Slider stop handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function()
{ this.coreStop.apply(this,arguments); = &quot;visible&quot;; }
// TW2.2+
// hijack Morpher stop handler so sliderPanel/floatingPanel overflow is visible after animation has completed
if (version.major+.1*version.minor+.01*version.revision&gt;=2.2) {
Morpher.prototype.coreStop = Morpher.prototype.stop;
Morpher.prototype.stop = function() {
var e=this.element;
if (hasClass(e,&quot;sliderPanel&quot;)||hasClass(e,&quot;floatingPanel&quot;)) {
// adjust panel overflow and position after animation = &quot;visible&quot;;
if (window.adjustSliderPos) window.adjustSliderPos(e.parentNode,e.button,e);
<div title="NestedSlidersPluginInfo" modifier="atsui" created="201410092007" tags="pluginInfo">
|Author|Eric Shulman|
|Description|documentation for NestedSlidersPlugin|
This plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content.
content goes here
* ''&quot;&quot;&quot;+++&quot;&quot;&quot; (or &quot;&quot;&quot;++++&quot;&quot;&quot;) and &quot;&quot;&quot;===&quot;&quot;&quot;''&lt;br&gt;marks the start and end of the slider definition, respectively. When the extra {{{+}}} is used, the slider will be open when initially displayed.
* ''&quot;&quot;&quot;(cookiename)&quot;&quot;&quot;''&lt;br&gt;saves the slider opened/closed state, and restores this state whenever the slider is re-rendered.
* ''&quot;&quot;&quot;! through !!!!!&quot;&quot;&quot;''&lt;br&gt;displays the slider label using a formatted headline (Hn) style instead of a button/link style
* ''&quot;&quot;&quot;^width^ (or just ^)&quot;&quot;&quot;''&lt;br&gt;makes the slider 'float' on top of other content rather than shifting that content downward. 'width' must be a valid CSS value (e.g., &quot;30em&quot;, &quot;180px&quot;, &quot;50%&quot;, etc.). If omitted, the default width is &quot;auto&quot; (i.e., fit to content)
* ''&quot;&quot;&quot;*&quot;&quot;&quot;''&lt;br&gt;denotes &quot;transient display&quot;: when a click occurs elsewhere in the document, the slider/floating panel will be automatically closed. This is useful for creating 'pulldown menus' that automatically go away after they are used. //Note: using SHIFT-click on a slider label will open/close that slider without triggering the automatic closing of any transient slider panels that are currently displayed, permitting ''temporary'' display of several transient panels at once.//
* ''&quot;&quot;&quot;@&quot;&quot;&quot;''&lt;br&gt;denotes &quot;open on hover&quot;: the slider/floating panel will be automatically opened as soon as the mouse moves over the slider label, without requiring a click.
* ''&quot;&quot;&quot;{{class{[label=key|tooltip][altlabel|alttooltip]}}}&quot;&quot;&quot;''&lt;br&gt;uses label/tooltip/accesskey. &quot;&quot;&quot;{{class{...}}}&quot;&quot;&quot;, &quot;&quot;&quot;=key&quot;&quot;&quot;, &quot;&quot;&quot;|tooltip&quot;&quot;&quot; and &quot;&quot;&quot;[altlabel|alttooltip]&quot;&quot;&quot; are optional. 'class' is any valid CSS class name, used to style the slider label text. 'key' must be a ''single letter only''. altlabel/alttooltip specify alternative label/tooltip for use when slider/floating panel is displayed. //Note: you can use HTML syntax within the label text to include HTML entities (e.g., {{{&amp;raquo;}}} (&amp;raquo;) or {{{&amp;#x25ba;}}} (&amp;#x25ba;), or even embedded images (e.g., {{{&lt;img src=&quot;images/eric3.gif&quot;&gt;}}}).//
* ''&quot;&quot;&quot;#panelID:&quot;&quot;&quot;''&lt;br&gt;defines a unique DOM element ID that is assigned to the panel element used to display the slider content. This ID can then be used later to reposition the panel using the {{{&lt;&lt;DOM move id&gt;&gt;}}} macro (see [[DOMTweaksPlugin]]), or to access/modify the panel element through use of {{{document.getElementById(...)}}}) javascript code in a plugin or inline script.
* ''&quot;&quot;&quot;&gt;&quot;&quot;&quot;''&lt;br&gt;automatically adds blockquote formatting to slider content
* ''&quot;&quot;&quot;...&quot;&quot;&quot;''&lt;br&gt;defers rendering of closed sliders until the first time they are opened.
*You can 'nest' sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created.
*Deferred rendering (...) can be used to offset processing overhead until actually needed. However, this may produce unexpected results in some cases. Use with care.
* To make slider definitions easier to read and recognize when editing a tiddler, newlines immediately following the 'start slider' or preceding the 'end slider' sequences are automatically supressed so that excess whitespace is eliminated from the output.
simple in-line slider:
use a custom label and tooltip:
content automatically blockquoted:
all options (except cookie) //(default open, heading, sized floater, transient, open on hover, class, label/tooltip/key, blockquoted, deferred)//
++++!!!^30em^*@{{big{[label=Z|click or press Alt-Z to open]}}}&gt;...
++++!!!^30em^*@{{big{[label=Z|click or press Alt-Z to open]}}}&gt;...
complex nesting example:
+++[get info...=I|click for information or press Alt-I]
put some general information here,
plus a floating panel with more specific info:
+++^10em^[view details...|click for details]
put some detail here, which could in turn contain a transient panel,
perhaps with a +++^25em^*[glossary definition]explaining technical terms===
+++[get info...=I|click for information or press Alt-I]
put some general information here,
plus a floating panel with more specific info:
+++^10em^[view details...|click for details]
put some detail here, which could in turn contain a transient panel,
perhaps with a +++^25em^*[glossary definition]explaining technical terms===
embedded image as slider button
+++[&lt;img src=images/eric3.gif&gt;|click me!]&gt;
+++[&lt;img src=images/eric3.gif&gt;|click me!]&gt;
2008.11.15 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class). In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
2008.11.13 2.4.8 in document.onclick(), if transient panel is not a sliderPanel or floatingPanel, hide it via CSS
2008.10.05 2.4.7 in onClickNestedSlider(), added try/catch around focus() call to prevent IE error if input field being focused on is currently not visible.
2008.09.07 2.4.6 added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.06.07 2.4.5 in 'onmouseover' handler for 'open on hover' slider buttons, use call() method when invoking document.onclick function (avoids error in IE)
2008.06.07 2.4.4 changed default for chkFloatingSlidersAnimate to FALSE to avoid clipping problem on some browsers (IE). Updated Morpher hijack (again) to adjust regular sliderPanel styles as well as floatingPanel styles.
2008.05.07 2.4.3 updated Morpher hijack to adjust floatingPanel styles after animation without affecting other animated elements (i.e. popups). Also, updated adjustSliderPos() to account for scrollwidth and use core findWindowWidth().
2008.04.02 2.4.2 in onClickNestedSlider, handle clicks on elements contained //within// slider buttons (e.g., when using HTML to display an image as a slider button).
2008.04.01 2.4.1 open on hover also triggers document.onclick to close other transient sliders
2008.04.01 2.4.0 re-introduced 'open on hover' feature using &quot;@&quot; symbol
2008.03.26 2.3.5 in document.onclick(), if click is in popup, don't dismiss transient panel (if any)
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 2.3.4 added hijack for Animator.prototype.startAnimating(). Previously, the plugin code simply set the overflow to &quot;visible&quot; after animation. This code tweak corrects handling of elements that were styled with overflow=hidden/auto/scroll before animation by saving the overflow style and then restoring it after animation has completed.
2007.12.17 2.3.3 use hasClass() instead of direct comparison to test for &quot;floatingPanel&quot; class. Allows floating panels to have additional classes assigned to them (i.e., by AnimationEffectsPlugin).
2007.11.14 2.3.2 in onClickNestedSlider(), prevent SHIFT-click events from opening a new, empty browser window by setting &quot;cancelBubble=true&quot; and calling &quot;stopPropagation()&quot;. Note: SHIFT-click is still processed as a normal click (i.e., it toggles the slider panel display). Also, using SHIFT-click will prevent 'transient' sliders from being automatically closed when another slider is opened, allowing you to *temporarily* display several transient sliders at once.
2007.07.26 2.3.1 in document.onclick(), propagate return value from hijacked core click handler to consume OR bubble up click as needed. Fixes &quot;IE click disease&quot;, whereby nearly every mouse click causes a page transition.
2007.07.20 2.3.0 added syntax for setting panel ID (#panelID:). This allows individual slider panels to be repositioned within tiddler content simply by giving them a unique ID and then moving them to the desired location using the {{{&lt;&lt;DOM move id&gt;&gt;}}} macro.
2007.07.19 2.2.0 added syntax for alttext and alttip (button label and tooltip to be displayed when panel is open)
2007.07.14 2.1.2 corrected use of 'transient' attribute in IE to prevent (non-recursive) infinite loop
2007.07.12 2.1.0 replaced use of &quot;*&quot; for 'open/close on rollover' (which didn't work too well). &quot;*&quot; now indicates 'transient' panels that are automatically closed if a click occurs somewhere else in the document. This permits use of nested sliders to create nested &quot;pulldown menus&quot; that automatically disappear after interaction with them has been completed. Also, in onClickNestedSlider(), use &quot;theTarget.sliderCookie&quot;, instead of &quot;this.sliderCookie&quot; to correct cookie state tracking when automatically dismissing transient panels.
2007.06.10 2.0.5 add check to ensure that window.adjustSliderPanel() is defined before calling it (prevents error on shutdown when mouse event handlers are still defined)
2007.05.31 2.0.4 add handling to invoke adjustSliderPanel() for onmouseover events on slider button and panel. This allows the panel position to be re-synced when the button position shifts due to changes in unrelated content above it on the page. (thanks to Harsha for bug report)
2007.03.30 2.0.3 added chkFloatingSlidersAnimate (default to FALSE), so that slider animation can be disabled independent of the overall document animation setting (avoids strange rendering and focus problems in floating panels)
2007.03.01 2.0.2 for TW2.2+, hijack Morpher.prototype.stop so that &quot;overflow:hidden&quot; can be reset to &quot;overflow:visible&quot; after animation ends
2007.03.01 2.0.1 in hijack for Slider.prototype.stop, use apply() to pass params to core function
2006.07.28 2.0.0 added custom class syntax around label/tip/key syntax: {{{{{classname{[label=key|tip]}}}}}}
2006.07.25 1.9.3 when parsing slider, save default open/closed state in button element, then in onClickNestedSlider(), if slider state matches saved default, instead of saving cookie, delete it. Significantly reduces the 'cookie overhead' when default slider states are used.
2006.06.29 1.9.2 in onClickNestedSlider(), when setting focus to first control, skip over type=&quot;hidden&quot;
2006.06.22 1.9.1 added panel.defaultPanelWidth to save requested panel width, even after resizing has changed the style value
2006.05.11 1.9.0 added optional '^width^' syntax for floating sliders and '=key' syntax for setting an access key on a slider label
2006.05.09 1.8.0 in onClickNestedSlider(), when showing panel, set focus to first child input/textarea/select element
2006.04.24 1.7.8 in adjustSliderPos(), if floating panel is contained inside another floating panel, subtract offset of containing panel to find correct position
2006.02.16 1.7.7 corrected deferred rendering to account for use-case where show/hide state is tracked in a cookie
2006.02.15 1.7.6 in adjustSliderPos(), ensure that floating panel is positioned completely within the browser window (i.e., does not go beyond the right edge of the browser window)
2006.02.04 1.7.5 add 'var' to unintended global variable declarations to avoid FireFox crash bug when assigning to globals
2006.01.18 1.7.4 only define adjustSliderPos() function if it has not already been provided by another plugin. This lets other plugins 'hijack' the function even when they are loaded first.
2006.01.16 1.7.3 added adjustSliderPos(place,btn,panel,panelClass) function to permit specialized logic for placement of floating panels. While it provides improved placement for many uses of floating panels, it exhibits a relative offset positioning error when used within *nested* floating panels. Short-term workaround is to only adjust the position for 'top-level' floaters.
2006.01.16 1.7.2 added button property to slider panel elements so that slider panel can tell which button it belongs to. Also, re-activated and corrected animation handling so that nested sliders aren't clipped by hijacking Slider.prototype.stop so that &quot;overflow:hidden&quot; can be reset to &quot;overflow:visible&quot; after animation ends
2006.01.14 1.7.1 added optional &quot;^&quot; syntax for floating panels. Defines new CSS class, &quot;.floatingPanel&quot;, as an alternative for standard in-line &quot;.sliderPanel&quot; styles.
2006.01.14 1.7.0 added optional &quot;*&quot; syntax for rollover handling to show/hide slider without requiring a click (Based on a suggestion by tw4efl)
2006.01.03 1.6.2 When using optional &quot;!&quot; heading style, instead of creating a clickable &quot;Hn&quot; element, create an &quot;A&quot; element inside the &quot;Hn&quot; element. (allows click-through in SlideShowPlugin, which captures nearly all click events, except for hyperlinks)
2005.12.15 1.6.1 added optional &quot;...&quot; syntax to invoke deferred ('lazy') rendering for initially hidden sliders
removed checkbox option for 'global' application of lazy sliders
2005.11.25 1.6.0 added optional handling for 'lazy sliders' (deferred rendering for initially hidden sliders)
2005.11.21 1.5.1 revised regular expressions: if present, a single newline //preceding// and/or //following// a slider definition will be suppressed so start/end syntax can be place on separate lines in the tiddler 'source' for improved readability. Similarly, any whitespace (newlines, tabs, spaces, etc.) trailing the 'start slider' syntax or preceding the 'end slider' syntax is also suppressed.
2005.11.20 1.5.0 added (cookiename) syntax for optional tracking and restoring of slider open/close state
2005.11.11 1.4.0 added !!!!! syntax to render slider label as a header (Hn) style instead of a button/link style
2005.11.07 1.3.0 removed alternative syntax {{{(((}}} and {{{)))}}} (so they can be used by other formatting extensions) and simplified/improved regular expressions to trim multiple excess newlines
2005.11.05 1.2.1 changed name to NestedSlidersPlugin
2005.11.04 1.2.0 added alternative character-mode syntax {{{(((}}} and {{{)))}}}
tweaked &quot;eat newlines&quot; logic for line-mode {{{+++}}} and {{{===}}} syntax
2005.11.03 1.1.1 fixed toggling of default tooltips (&quot;more...&quot; and &quot;less...&quot;) when a non-default button label is used. code cleanup, added documentation
2005.11.03 1.1.0 changed delimiter syntax from {{{(((}}} and {{{)))}}} to {{{+++}}} and {{{===}}}. changed name to EasySlidersPlugin
2005.11.03 1.0.0 initial public release
<div title="SideBarOptions" modifier="atsui" created="201304061914" modified="201304061915">
<pre>&lt;&lt;search&gt;&gt;&lt;&lt;closeAll&gt;&gt;&lt;&lt;permaview&gt;&gt;&lt;&lt;newTiddler&gt;&gt;&lt;&lt;newJournal &quot;YYYY-MM-DD&quot; &quot;journal&quot;&gt;&gt;&lt;&lt;saveChanges&gt;&gt;&lt;&lt;slider chkSliderOptionsPanel OptionsPanel &quot;options »&quot; &quot;Change TiddlyWiki advanced options&quot;&gt;&gt;</pre>
<div title="SiteSubtitle" modifier="atsui" created="200902092123" modified="200903200601">
<div title="SiteTitle" modifier="atsui" created="200902092122" modified="200903200601">
<div title="StyleSheet" modifier="AlexTsui" created="200901262202">
<pre>.calendar a.tiddlyLinkExisting {
font-weight: bolder;
font-size: larger;
.calendar a.tiddlyLinkNonExisting {
font-size: smaller
<script id="jsArea" type="text/javascript">
// Please note:
// * This code is designed to be readable but for compactness it only includes brief comments. You can see fuller comments
// in the project repository at
// * You should never need to modify this source code directly. TiddlyWiki is carefully designed to allow deep customisation
// without changing the core code. Please consult the development group at
// JSLint directives
/*global jQuery:false, version:false */
/*jslint bitwise:true, browser:true, confusion:true, eqeq:true, evil:true, forin:true, maxerr:100, plusplus:true, regexp:true, sloppy:true, sub:true, undef:true, unparam:true, vars:true, white:true */
//-- Configuration repository
// Miscellaneous options
var config = {
numRssItems: 20, // Number of items in the RSS feed
animDuration: 400, // Duration of UI animations in milliseconds
cascadeFast: 20, // Speed for cascade animations (higher == slower)
cascadeSlow: 60, // Speed for EasterEgg cascade animations
cascadeDepth: 5, // Depth of cascade animation
locale: "en" // W3C language tag
// Hashmap of alternative parsers for the wikifier
config.parsers = {};
// Adaptors
config.adaptors = {};
config.defaultAdaptor = null;
// Backstage tasks
config.tasks = {};
// Annotations
config.annotations = {};
// Custom fields to be automatically added to new tiddlers
config.defaultCustomFields = {};
// Messages
config.messages = {
messageClose: {},
dates: {},
tiddlerPopup: {}
// Options that can be set in the options panel and/or cookies
config.options = {
chkRegExpSearch: false,
chkCaseSensitiveSearch: false,
chkIncrementalSearch: true,
chkAnimate: true,
chkSaveBackups: true,
chkAutoSave: false,
chkGenerateAnRssFeed: false,
chkSaveEmptyTemplate: false,
chkOpenInNewWindow: true,
chkToggleLinks: false,
chkHttpReadOnly: true,
chkForceMinorUpdate: false,
chkConfirmDelete: true,
chkInsertTabs: false,
chkUsePreForStorage: true, // Whether to use <pre> format for storage
chkDisplayInstrumentation: false,
txtBackupFolder: "",
txtEditorFocus: "text",
txtMainTab: "tabTimeline",
txtMoreTab: "moreTabAll",
txtMaxEditRows: "30",
txtFileSystemCharSet: "UTF-8",
txtTheme: ""
config.optionsDesc = {};
config.optionsSource = {};
// Default tiddler templates
config.tiddlerTemplates = {
1: "ViewTemplate",
2: "EditTemplate"
// More messages (rather a legacy layout that should not really be like this)
config.views = {
wikified: {
tag: {}
editor: {
tagChooser: {}
// Backstage tasks
config.backstageTasks = ["save","importTask","tweak","upgrade","plugins"];
// Extensions
config.extensions = {};
// Macros; each has a 'handler' member that is inserted later
config.macros = {
today: {},
version: {},
search: {sizeTextbox: 15},
tiddler: {},
tag: {},
tags: {},
tagging: {},
timeline: {},
allTags: {},
list: {
all: {},
missing: {},
orphans: {},
shadowed: {},
touched: {},
filter: {}
closeAll: {},
permaview: {},
saveChanges: {},
slider: {},
option: {},
options: {},
newTiddler: {},
newJournal: {},
tabs: {},
gradient: {},
message: {},
view: {defaultView: "text"},
edit: {},
tagChooser: {},
toolbar: {},
plugins: {},
refreshDisplay: {},
importTiddlers: {},
upgrade: {
source: "",
backupExtension: "pre.core.upgrade"
sync: {},
annotations: {}
// Commands supported by the toolbar macro
config.commands = {
closeTiddler: {},
closeOthers: {},
editTiddler: {},
saveTiddler: {hideReadOnly: true},
cancelTiddler: {},
deleteTiddler: {hideReadOnly: true},
permalink: {},
references: {type: "popup"},
jump: {type: "popup"},
syncing: {type: "popup"},
fields: {type: "popup"}
// Control of macro parameter evaluation
config.evaluateMacroParameters = "all";
// Basic regular expressions
config.textPrimitives = {
upperLetter: "[A-Z\u00c0-\u00de\u0150\u0170]",
lowerLetter: "[a-z0-9_\\-\u00df-\u00ff\u0151\u0171]",
anyLetter: "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]",
anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]"
if(!((new RegExp("[\u0150\u0170]","g")).test("\u0150"))) {
config.textPrimitives = {
upperLetter: "[A-Z\u00c0-\u00de]",
lowerLetter: "[a-z0-9_\\-\u00df-\u00ff]",
anyLetter: "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff]",
anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff]"
config.textPrimitives.sliceSeparator = "::";
config.textPrimitives.sectionSeparator = "##";
config.textPrimitives.urlPattern = "(?:file|http|https|mailto|ftp|irc|news|data):[^\\s'\"]+(?:/|\\b)";
config.textPrimitives.unWikiLink = "~";
config.textPrimitives.wikiLink = "(?:(?:" + config.textPrimitives.upperLetter + "+" +
config.textPrimitives.lowerLetter + "+" +
config.textPrimitives.upperLetter +
config.textPrimitives.anyLetter + "*)|(?:" +
config.textPrimitives.upperLetter + "{2,}" +
config.textPrimitives.lowerLetter + "+))";
config.textPrimitives.cssLookahead = "(?:(" + config.textPrimitives.anyLetter + "+)\\(([^\\)\\|\\n]+)(?:\\):))|(?:(" + config.textPrimitives.anyLetter + "+):([^;\\|\\n]+);)";
config.textPrimitives.cssLookaheadRegExp = new RegExp(config.textPrimitives.cssLookahead,"mg");
config.textPrimitives.brackettedLink = "\\[\\[([^\\]]+)\\]\\]";
config.textPrimitives.titledBrackettedLink = "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]";
config.textPrimitives.tiddlerForcedLinkRegExp = new RegExp("(?:" + config.textPrimitives.titledBrackettedLink + ")|(?:" +
config.textPrimitives.brackettedLink + ")|(?:" +
config.textPrimitives.urlPattern + ")","mg");
config.textPrimitives.tiddlerAnyLinkRegExp = new RegExp("("+ config.textPrimitives.wikiLink + ")|(?:" +
config.textPrimitives.titledBrackettedLink + ")|(?:" +
config.textPrimitives.brackettedLink + ")|(?:" +
config.textPrimitives.urlPattern + ")","mg");
config.glyphs = {
currBrowser: null,
browsers: [],
codes: {}
//-- Shadow tiddlers
config.shadowTiddlers = {
StyleSheet: "",
MarkupPreHead: "",
MarkupPostHead: "",
MarkupPreBody: "",
MarkupPostBody: "",
TabTimeline: '<<timeline>>',
TabAll: '<<list all>>',
TabTags: '<<allTags excludeLists>>',
TabMoreMissing: '<<list missing>>',
TabMoreOrphans: '<<list orphans>>',
TabMoreShadowed: '<<list shadowed>>',
AdvancedOptions: '<<options>>',
PluginManager: '<<plugins>>',
SystemSettings: '',
ToolbarCommands: '|~ViewToolbar|closeTiddler closeOthers +editTiddler > fields syncing permalink references jump|\n|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|',
WindowTitle: '<<tiddler SiteTitle>> - <<tiddler SiteSubtitle>>'
// Browser detection... In a very few places, there's nothing else for it but to know what browser we're using.
config.userAgent = navigator.userAgent.toLowerCase();
config.browser = {
isIE: config.userAgent.indexOf("msie") != -1 && config.userAgent.indexOf("opera") == -1,
isGecko: navigator.product == "Gecko" && config.userAgent.indexOf("WebKit") == -1,
ieVersion: /MSIE (\d{1,2}.\d)/i.exec(config.userAgent), // config.browser.ieVersion[1], if it exists, will be the IE version string, eg "6.0"
isSafari: config.userAgent.indexOf("applewebkit") != -1,
isBadSafari: !((new RegExp("[\u0150\u0170]","g")).test("\u0150")),
firefoxDate: /gecko\/(\d{8})/i.exec(config.userAgent), // config.browser.firefoxDate[1], if it exists, will be Firefox release date as "YYYYMMDD"
isOpera: config.userAgent.indexOf("opera") != -1,
isChrome: config.userAgent.indexOf('chrome') > -1,
isLinux: config.userAgent.indexOf("linux") != -1,
isUnix: config.userAgent.indexOf("x11") != -1,
isMac: config.userAgent.indexOf("mac") != -1,
isWindows: config.userAgent.indexOf("win") != -1
browsers: [
function() {return config.browser.isIE;},
function() {return true;}
codes: {
downTriangle: ["\u25BC","\u25BE"],
downArrow: ["\u2193","\u2193"],
bentArrowLeft: ["\u2190","\u21A9"],
bentArrowRight: ["\u2192","\u21AA"]
//-- Translateable strings
// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone
txtUserName: "YourName"});
save: {text: "save", tooltip: "Save your changes to this TiddlyWiki"},
importTask: {text: "import", tooltip: "Import tiddlers and plugins from other TiddlyWiki files and servers", content: '<<importTiddlers>>'},
tweak: {text: "tweak", tooltip: "Tweak the appearance and behaviour of TiddlyWiki", content: '<<options>>'},
upgrade: {text: "upgrade", tooltip: "Upgrade TiddlyWiki core code", content: '<<upgrade>>'},
plugins: {text: "plugins", tooltip: "Manage installed plugins", content: '<<plugins>>'}
// Options that can be set in the options panel and/or cookies
txtUserName: "Username for signing your edits",
chkRegExpSearch: "Enable regular expressions for searches",
chkCaseSensitiveSearch: "Case-sensitive searching",
chkIncrementalSearch: "Incremental key-by-key searching",
chkAnimate: "Enable animations",
chkSaveBackups: "Keep backup file when saving changes",
chkAutoSave: "Automatically save changes",
chkGenerateAnRssFeed: "Generate an RSS feed when saving changes",
chkSaveEmptyTemplate: "Generate an empty template when saving changes",
chkOpenInNewWindow: "Open external links in a new window",
chkToggleLinks: "Clicking on links to open tiddlers causes them to close",
chkHttpReadOnly: "Hide editing features when viewed over HTTP",
chkForceMinorUpdate: "Don't update modifier username and date when editing tiddlers",
chkConfirmDelete: "Require confirmation before deleting tiddlers",
chkInsertTabs: "Use the tab key to insert tab characters instead of moving between fields",
txtBackupFolder: "Name of folder to use for backups",
txtMaxEditRows: "Maximum number of rows in edit boxes",
txtTheme: "Name of the theme to use",
txtFileSystemCharSet: "Default character set for saving changes (Firefox/Mozilla only)"});
customConfigError: "Problems were encountered loading plugins. See PluginManager for details",
pluginError: "Error: %0",
pluginDisabled: "Not executed because disabled via 'systemConfigDisable' tag",
pluginForced: "Executed because forced via 'systemConfigForce' tag",
pluginVersionError: "Not executed because this plugin needs a newer version of TiddlyWiki",
nothingSelected: "Nothing is selected. You must select one or more items first",
savedSnapshotError: "It appears that this TiddlyWiki has been incorrectly saved. Please see for details",
subtitleUnknown: "(unknown)",
undefinedTiddlerToolTip: "The tiddler '%0' doesn't yet exist",
shadowedTiddlerToolTip: "The tiddler '%0' doesn't yet exist, but has a pre-defined shadow value",
tiddlerLinkTooltip: "%0 - %1, %2",
externalLinkTooltip: "External link to %0",
noTags: "There are no tagged tiddlers",
notFileUrlError: "You need to save this TiddlyWiki to a file before you can save changes",
cantSaveError: "It's not possible to save changes. Possible reasons include:\n- your browser doesn't support saving (Firefox, Internet Explorer, Safari and Opera all work if properly configured)\n- the pathname to your TiddlyWiki file contains illegal characters\n- the TiddlyWiki HTML file has been moved or renamed",
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to save backup file",
rssSaved: "RSS feed saved",
rssFailed: "Failed to save RSS feed file",
emptySaved: "Empty template saved",
emptyFailed: "Failed to save empty template file",
mainSaved: "Main TiddlyWiki file saved",
mainDownload: "Downloading/saving main TiddlyWiki file",
mainDownloadManual: "RIGHT CLICK HERE to download/save main TiddlyWiki file",
mainFailed: "Failed to save main TiddlyWiki file. Your changes have not been saved",
macroError: "Error in macro <<%0>>",
macroErrorDetails: "Error while executing macro <<%0>>:\n%1",
missingMacro: "No such macro",
overwriteWarning: "A tiddler named '%0' already exists. Choose OK to overwrite it",
unsavedChangesWarning: "WARNING! There are unsaved changes in TiddlyWiki\n\nChoose OK to save\nChoose CANCEL to discard",
confirmExit: "--------------------------------\n\nThere are unsaved changes in TiddlyWiki. If you continue you will lose those changes\n\n--------------------------------",
saveInstructions: "SaveChanges",
unsupportedTWFormat: "Unsupported TiddlyWiki format '%0'",
tiddlerSaveError: "Error when saving tiddler '%0'",
tiddlerLoadError: "Error when loading tiddler '%0'",
wrongSaveFormat: "Cannot save with storage format '%0'. Using standard format for save.",
invalidFieldName: "Invalid field name %0",
fieldCannotBeChanged: "Field '%0' cannot be changed",
loadingMissingTiddler: "Attempting to retrieve the tiddler '%0' from the '%1' server at:\n\n'%2' in the workspace '%3'",
upgradeDone: "The upgrade to version %0 is now complete\n\nClick 'OK' to reload the newly upgraded TiddlyWiki",
invalidCookie: "Invalid cookie '%0'"});
text: "close",
tooltip: "close this message area"});
config.messages.backstage = {
open: {text: "backstage", tooltip: "Open the backstage area to perform authoring and editing tasks"},
close: {text: "close", tooltip: "Close the backstage area"},
prompt: "backstage: ",
decal: {
edit: {text: "edit", tooltip: "Edit the tiddler '%0'"}
config.messages.listView = {
tiddlerTooltip: "Click for the full text of this tiddler",
previewUnavailable: "(preview not available)"
config.messages.dates.months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November","December"];
config.messages.dates.days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.messages.dates.shortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
"st"]; = "am"; = "pm";
labelNoTags: "no tags",
labelTags: "tags: ",
openTag: "Open tag '%0'",
tooltip: "Show tiddlers tagged with '%0'",
openAllText: "Open all",
openAllTooltip: "Open all of these tiddlers",
popupNone: "No other tiddlers tagged with '%0'"});
defaultText: "The tiddler '%0' doesn't yet exist. Double-click to create it",
defaultModifier: "(missing)",
shadowModifier: "(built-in shadow tiddler)",
dateFormat: "DD MMM YYYY",
createdPrompt: "created"});
tagPrompt: "Type tags separated with spaces, [[use double square brackets]] if necessary, or add existing",
defaultText: "Type the text for '%0'"});
text: "tags",
tooltip: "Choose existing tags to add to this tiddler",
popupNone: "There are no tags defined",
tagTooltip: "Add the tag '%0'"});
{unit: 1024*1024*1024, template: "%0\u00a0GB"},
{unit: 1024*1024, template: "%0\u00a0MB"},
{unit: 1024, template: "%0\u00a0KB"},
{unit: 1, template: "%0\u00a0B"}
label: "search",
prompt: "Search this TiddlyWiki",
placeholder: "",
accessKey: "F",
successMsg: "%0 tiddlers found matching %1",
failureMsg: "No tiddlers found matching %0"});
label: "tagging: ",
labelNotTag: "not tagging",
tooltip: "List of tiddlers tagged with '%0'"});
dateFormat: "DD MMM YYYY"});
tooltip: "Show tiddlers tagged with '%0'",
noTags: "There are no tagged tiddlers"});
config.macros.list.all.prompt = "All tiddlers in alphabetical order";
config.macros.list.missing.prompt = "Tiddlers that have links to them but are not defined";
config.macros.list.orphans.prompt = "Tiddlers that are not linked to from any other tiddlers";
config.macros.list.shadowed.prompt = "Tiddlers shadowed with default contents";
config.macros.list.touched.prompt = "Tiddlers that have been modified locally";
label: "close all",
prompt: "Close all displayed tiddlers (except any that are being edited)"});
label: "permaview",
prompt: "Link to an URL that retrieves all the currently displayed tiddlers"});
label: "save changes",
prompt: "Save all tiddlers to create a new TiddlyWiki",
accessKey: "S"});
label: "new tiddler",
prompt: "Create a new tiddler",
title: "New Tiddler",
accessKey: "N"});
label: "new journal",
prompt: "Create a new tiddler from the current date and time",
accessKey: "J"});
wizardTitle: "Tweak advanced options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>Show unknown options</input>",
unknownDescription: "//(unknown)//",
listViewTemplate: {
columns: [
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
wizardTitle: "Manage plugins",
step1Title: "Currently loaded plugins",
step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
skippedText: "(This plugin has not been executed because it was added since startup)",
noPluginText: "There are no plugins installed",
confirmDeleteText: "Are you sure you want to delete these plugins:\n\n%0",
removeLabel: "remove systemConfig tag",
removePrompt: "Remove systemConfig tag",
deleteLabel: "delete",
deletePrompt: "Delete these tiddlers forever",
listViewTemplate: {
columns: [
{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
{name: 'Description', field: 'Description', title: "Description", type: 'String'},
{name: 'Version', field: 'Version', title: "Version", type: 'String'},
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
{name: 'Forced', field: 'forced', title: "Forced", tag: 'systemConfigForce', type: 'TagCheckbox'},
{name: 'Disabled', field: 'disabled', title: "Disabled", tag: 'systemConfigDisable', type: 'TagCheckbox'},
{name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"},
{name: 'Startup Time', field: 'startupTime', title: "Startup Time", type: 'String'},
{name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"},
{name: 'Log', field: 'log', title: "Log", type: 'StringList'}
rowClasses: [
{className: 'error', field: 'error'},
{className: 'warning', field: 'warning'}
listViewTemplateReadOnly: {
columns: [
{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
{name: 'Description', field: 'Description', title: "Description", type: 'String'},
{name: 'Version', field: 'Version', title: "Version", type: 'String'},
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
{name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"},
{name: 'Startup Time', field: 'startupTime', title: "Startup Time", type: 'String'},
{name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"},
{name: 'Log', field: 'log', title: "Log", type: 'StringList'}
rowClasses: [
{className: 'error', field: 'error'},
{className: 'warning', field: 'warning'}
moreLabel: "more",
morePrompt: "Show additional commands",
lessLabel: "less",
lessPrompt: "Hide additional commands",
separator: "|"
label: "refresh",
prompt: "Redraw the entire TiddlyWiki display"
readOnlyWarning: "You cannot import into a read-only TiddlyWiki file. Try opening it from a file:// URL",
wizardTitle: "Import tiddlers from another file or server",
step1Title: "Step 1: Locate the server or TiddlyWiki file",
step1Html: "Specify the type of the server: <select name='selTypes'><option value=''>Choose...</option></select><br>Enter the URL or pathname here: <input type='text' size=50 name='txtPath'><br>...or browse for a file: <input type='file' size=50 name='txtBrowse'><br><hr>...or select a pre-defined feed: <select name='selFeeds'><option value=''>Choose...</option></select>",
openLabel: "open",
openPrompt: "Open the connection to this file or server",
statusOpenHost: "Opening the host",
statusGetWorkspaceList: "Getting the list of available workspaces",
step2Title: "Step 2: Choose the workspace",
step2Html: "Enter a workspace name: <input type='text' size=50 name='txtWorkspace'><br>...or select a workspace: <select name='selWorkspace'><option value=''>Choose...</option></select>",
cancelLabel: "cancel",
cancelPrompt: "Cancel this import",
statusOpenWorkspace: "Opening the workspace",
statusGetTiddlerList: "Getting the list of available tiddlers",
errorGettingTiddlerList: "Error getting list of tiddlers, click Cancel to try again",
errorGettingTiddlerListHttp404: "Error retrieving tiddlers from url, please ensure the url exists. Click Cancel to try again.",
errorGettingTiddlerListHttp: "Error retrieving tiddlers from url, please ensure this url exists and is <a href=''>CORS</a> enabled",
errorGettingTiddlerListFile: "Error retrieving tiddlers from local file, please make sure the file is in the same directory as your TiddlyWiki. Click Cancel to try again.",
step3Title: "Step 3: Choose the tiddlers to import",
step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>Keep these tiddlers linked to this server so that you can synchronise subsequent changes</input><br><input type='checkbox' name='chkSave'>Save the details of this server in a 'systemServer' tiddler called:</input> <input type='text' size=25 name='txtSaveTiddler'>",
importLabel: "import",
importPrompt: "Import these tiddlers",
confirmOverwriteText: "Are you sure you want to overwrite these tiddlers:\n\n%0",
step4Title: "Step 4: Importing %0 tiddler(s)",
step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
doneLabel: "done",
donePrompt: "Close this wizard",
statusDoingImport: "Importing tiddlers",
statusDoneImport: "All tiddlers imported",
systemServerNamePattern: "%2 on %1",
systemServerNamePatternNoWorkspace: "%1",
confirmOverwriteSaveTiddler: "The tiddler '%0' already exists. Click 'OK' to overwrite it with the details of this server, or 'Cancel' to leave it unchanged",
serverSaveTemplate: "|''Type:''|%0|\n|''URL:''|%1|\n|''Workspace:''|%2|\n\nThis tiddler was automatically created to record the details of this server",
serverSaveModifier: "(System)",
listViewTemplate: {
columns: [
{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
{name: 'Tags', field: 'tags', title: "Tags", type: 'Tags'}
rowClasses: [
wizardTitle: "Upgrade TiddlyWiki core code",
step1Title: "Update or repair this TiddlyWiki to the latest release",
step1Html: "You are about to upgrade to the latest release of the TiddlyWiki core code (from <a href='%0' class='externalLink' target='_blank'>%1</a>). Your content will be preserved across the upgrade.<br><br>Note that core upgrades have been known to interfere with older plugins. If you run into problems with the upgraded file, see <a href='' class='externalLink' target='_blank'></a>",
errorCantUpgrade: "Unable to upgrade this TiddlyWiki. You can only perform upgrades on TiddlyWiki files stored locally",
errorNotSaved: "You must save changes before you can perform an upgrade",
step2Title: "Confirm the upgrade details",
step2Html_downgrade: "You are about to downgrade to TiddlyWiki version %0 from %1.<br><br>Downgrading to an earlier version of the core code is not recommended",
step2Html_restore: "This TiddlyWiki appears to be already using the latest version of the core code (%0).<br><br>You can continue to upgrade anyway to ensure that the core code hasn't been corrupted or damaged",
step2Html_upgrade: "You are about to upgrade to TiddlyWiki version %0 from %1",
upgradeLabel: "upgrade",
upgradePrompt: "Prepare for the upgrade process",
statusPreparingBackup: "Preparing backup",
statusSavingBackup: "Saving backup file",
errorSavingBackup: "There was a problem saving the backup file",
statusLoadingCore: "Loading core code",
errorLoadingCore: "Error loading the core code",
errorCoreFormat: "Error with the new core code",
statusSavingCore: "Saving the new core code",
statusReloadingCore: "Reloading the new core code",
startLabel: "start",
startPrompt: "Start the upgrade process",
cancelLabel: "cancel",
cancelPrompt: "Cancel the upgrade process",
step3Title: "Upgrade cancelled",
step3Html: "You have cancelled the upgrade process"
text: "close",
tooltip: "Close this tiddler"});
text: "close others",
tooltip: "Close all other tiddlers"});
text: "edit",
tooltip: "Edit this tiddler",
readOnlyText: "view",
readOnlyTooltip: "View the source of this tiddler"});
text: "done",
tooltip: "Save changes to this tiddler"});
text: "cancel",
tooltip: "Undo changes to this tiddler",
warning: "Are you sure you want to abandon your changes to '%0'?",
readOnlyText: "done",
readOnlyTooltip: "View this tiddler normally"});
text: "delete",
tooltip: "Delete this tiddler",
warning: "Are you sure you want to delete '%0'?"});
text: "permalink",
tooltip: "Permalink for this tiddler"});
text: "references",
tooltip: "Show tiddlers that link to this one",
popupNone: "No references"});
text: "jump",
tooltip: "Jump to another open tiddler"});
text: "fields",
tooltip: "Show the extended fields of this tiddler",
emptyText: "There are no extended fields for this tiddler",
listViewTemplate: {
columns: [
{name: 'Field', field: 'field', title: "Field", type: 'String'},
{name: 'Value', field: 'value', title: "Value", type: 'String'}
rowClasses: [
buttons: [
DefaultTiddlers: "[[GettingStarted]]",
MainMenu: "[[GettingStarted]]",
SiteTitle: "My TiddlyWiki",
SiteSubtitle: "a reusable non-linear personal web notebook",
SiteUrl: "",
SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "options \u00bb" "Change TiddlyWiki advanced options">>',
SideBarTabs: '<<tabs txtMainTab "Timeline" "Timeline" TabTimeline "All" "All tiddlers" TabAll "Tags" "All tags" TabTags "More" "More lists" TabMore>>',
TabMore: '<<tabs txtMoreTab "Missing" "Missing tiddlers" TabMoreMissing "Orphans" "Orphaned tiddlers" TabMoreOrphans "Shadowed" "Shadowed tiddlers" TabMoreShadowed>>'
AdvancedOptions: "This shadow tiddler provides access to several advanced options",
ColorPalette: "These values in this shadow tiddler determine the colour scheme of the ~TiddlyWiki user interface",
DefaultTiddlers: "The tiddlers listed in this shadow tiddler will be automatically displayed when ~TiddlyWiki starts up",
EditTemplate: "The HTML template in this shadow tiddler determines how tiddlers look while they are being edited",
GettingStarted: "This shadow tiddler provides basic usage instructions",
ImportTiddlers: "This shadow tiddler provides access to importing tiddlers",
MainMenu: "This shadow tiddler is used as the contents of the main menu in the left-hand column of the screen",
MarkupPreHead: "This tiddler is inserted at the top of the <head> section of the TiddlyWiki HTML file",
MarkupPostHead: "This tiddler is inserted at the bottom of the <head> section of the TiddlyWiki HTML file",
MarkupPreBody: "This tiddler is inserted at the top of the <body> section of the TiddlyWiki HTML file",
MarkupPostBody: "This tiddler is inserted at the end of the <body> section of the TiddlyWiki HTML file immediately after the script block",
OptionsPanel: "This shadow tiddler is used as the contents of the options panel slider in the right-hand sidebar",
PageTemplate: "The HTML template in this shadow tiddler determines the overall ~TiddlyWiki layout",
PluginManager: "This shadow tiddler provides access to the plugin manager",
SideBarOptions: "This shadow tiddler is used as the contents of the option panel in the right-hand sidebar",
SideBarTabs: "This shadow tiddler is used as the contents of the tabs panel in the right-hand sidebar",
SiteSubtitle: "This shadow tiddler is used as the second part of the page title",
SiteTitle: "This shadow tiddler is used as the first part of the page title",
SiteUrl: "This shadow tiddler should be set to the full target URL for publication",
StyleSheetColors: "This shadow tiddler contains CSS definitions related to the color of page elements. ''DO NOT EDIT THIS TIDDLER'', instead make your changes in the StyleSheet shadow tiddler",
StyleSheet: "This tiddler can contain custom CSS definitions",
StyleSheetLayout: "This shadow tiddler contains CSS definitions related to the layout of page elements. ''DO NOT EDIT THIS TIDDLER'', instead make your changes in the StyleSheet shadow tiddler",
StyleSheetLocale: "This shadow tiddler contains CSS definitions related to the translation locale",
StyleSheetPrint: "This shadow tiddler contains CSS definitions for printing",
SystemSettings: "This tiddler is used to store configuration options for this TiddlyWiki document",
TabAll: "This shadow tiddler contains the contents of the 'All' tab in the right-hand sidebar",
TabMore: "This shadow tiddler contains the contents of the 'More' tab in the right-hand sidebar",
TabMoreMissing: "This shadow tiddler contains the contents of the 'Missing' tab in the right-hand sidebar",
TabMoreOrphans: "This shadow tiddler contains the contents of the 'Orphans' tab in the right-hand sidebar",
TabMoreShadowed: "This shadow tiddler contains the contents of the 'Shadowed' tab in the right-hand sidebar",
TabTags: "This shadow tiddler contains the contents of the 'Tags' tab in the right-hand sidebar",
TabTimeline: "This shadow tiddler contains the contents of the 'Timeline' tab in the right-hand sidebar",
ToolbarCommands: "This shadow tiddler determines which commands are shown in tiddler toolbars",
ViewTemplate: "The HTML template in this shadow tiddler determines how tiddlers look"
//-- Main
var params = null; // Command line parameters
var store = null; // TiddlyWiki storage
var story = null; // Main story
var formatter = null; // Default formatters for the wikifier
var anim = typeof Animator == "function" ? new Animator() : null; // Animation engine
var readOnly = false; // Whether we're in readonly mode
var highlightHack = null; // Embarrassing hack department...
var hadConfirmExit = false; // Don't warn more than once
var safeMode = false; // Disable all plugins and cookies
var showBackstage; // Whether to include the backstage area
var installedPlugins = []; // Information filled in when plugins are executed
var startingUp = false; // Whether we're in the process of starting up
var pluginInfo,tiddler; // Used to pass information to plugins in loadPlugins()
// Whether this file can be saved back to the same location [Preemption]
window.allowSave = window.allowSave || function(l)
return true;
// Whether this file is being viewed locally
window.isLocal = function()
return (document.location.protocol == "file:");
// Whether to use the JavaSaver applet
var useJavaSaver = window.isLocal() && (config.browser.isSafari || config.browser.isOpera);
// Allow preemption code a chance to tweak config and useJavaSaver [Preemption]
if (window.tweakConfig) window.tweakConfig();
if(!window || !window.console) {
console = {tiddlywiki:true,log:function(message) {displayMessage(message);}};
// Starting up
function main()
var t10,t9,t8,t7,t6,t5,t4,t3,t2,t1,t0 = new Date();
startingUp = true;
var doc = jQuery(document);
window.onbeforeunload = function(e) {if(window.confirmExit) return confirmExit();};
params = getParameters();
params = params.parseParams("open",null,false);
store = new TiddlyWiki({config:config});
story = new Story("tiddlerDisplay","tiddler");
var s;
for(s=0; s<config.notifyTiddlers.length; s++)
t1 = new Date();
t2 = new Date();
t3 = new Date();
t4 = new Date();
readOnly = window.isLocal() ? false : config.options.chkHttpReadOnly;
var pluginProblem = loadPlugins("systemConfig");
t5 = new Date();
formatter = new Formatter(config.formatters);
showBackstage = showBackstage !== undefined ? showBackstage : !readOnly;
t6 = new Date();
var m;
for(m in config.macros) {
t7 = new Date();
t8 = new Date();
t9 = new Date();
if(pluginProblem) {
t10 = new Date();
if(config.options.chkDisplayInstrumentation) {
displayMessage("LoadShadows " + (t2-t1) + " ms");
displayMessage("LoadFromDiv " + (t3-t2) + " ms");
displayMessage("LoadPlugins " + (t5-t4) + " ms");
displayMessage("Macro init " + (t7-t6) + " ms");
displayMessage("Notify " + (t8-t7) + " ms");
displayMessage("Restart " + (t9-t8) + " ms");
displayMessage("Total: " + (t10-t0) + " ms");
startingUp = false;
// Called on unload. All functions called conditionally since they themselves may have been unloaded.
function unload()
// Restarting
function restart()
if(story.isEmpty()) {
function saveTest()
var s = document.getElementById("saveTest");
function loadShadowTiddlers()
var shadows = new TiddlyWiki();
shadows.forEachTiddler(function(title,tiddler){config.shadowTiddlers[title] = tiddler.text;});
function loadPlugins(tag)
return false;
var tiddlers = store.getTaggedTiddlers(tag);
tiddlers.sort(function(a,b) {return a.title < b.title ? -1 : (a.title == b.title ? 0 : 1);});
var toLoad = [];
var nLoaded = 0;
var map = {};
var nPlugins = tiddlers.length;
installedPlugins = [];
var i;
for(i=0; i<nPlugins; i++) {
var p = getPluginInfo(tiddlers[i]);
installedPlugins[i] = p;
var n = p.Name || p.title;
map[n] = p;
n = p.Source;
map[n] = p;
var visit = function(p) {
if(!p || p.done)
p.done = 1;
var reqs = p.Requires;
if(reqs) {
reqs = reqs.readBracketedList();
var i;
for(i=0; i<reqs.length; i++)
for(i=0; i<nPlugins; i++)
for(i=0; i<toLoad.length; i++) {
p = toLoad[i];
pluginInfo = p;
tiddler = p.tiddler;
if(isPluginExecutable(p)) {
if(isPluginEnabled(p)) {
p.executed = true;
var startTime = new Date();
try {
} catch(ex) {
p.error = true;
if(!console.tiddlywiki) {
console.log("error evaluating " + tiddler.title, ex);
pluginInfo.startupTime = String((new Date()) - startTime) + "ms";
} else {
} else {
p.warning = true;
return nLoaded != nPlugins;
function getPluginInfo(tiddler)
var p = store.getTiddlerSlices(tiddler.title,["Name","Description","Version","Requires","CoreVersion","Date","Source","Author","License","Browsers"]);
p.tiddler = tiddler;
p.title = tiddler.title;
p.log = [];
return p;
// Check that a particular plugin is valid for execution
function isPluginExecutable(plugin)
if(plugin.tiddler.isTagged("systemConfigForce")) {
return true;
if(plugin["CoreVersion"]) {
var coreVersion = plugin["CoreVersion"].split(".");
var w = parseInt(coreVersion[0],10) - version.major;
if(w == 0 && coreVersion[1])
w = parseInt(coreVersion[1],10) - version.minor;
if(w == 0 && coreVersion[2])
w = parseInt(coreVersion[2],10) - version.revision;
if(w > 0) {
return false;
return true;
function isPluginEnabled(plugin)
if(plugin.tiddler.isTagged("systemConfigDisable")) {
return false;
return true;
//-- Paramifiers
function getParameters()
var p = null;
if(window.location.hash) {
p = decodeURIComponent(window.location.hash.substr(1));
if(config.browser.firefoxDate != null && config.browser.firefoxDate[1] < "20051111")
p = convertUTF8ToUnicode(p);
return p;
function invokeParamifier(params,handler)
if(!params || params.length == undefined || params.length <= 1)
var i;
for(i=1; i<params.length; i++) {
var p = config.paramifiers[params[i].name];
if(p && p[handler] instanceof Function)
else {
var h = config.optionHandlers[params[i].name.substr(0,3)];
if(h && h.set instanceof Function)
config.paramifiers = {};
config.paramifiers.start = {
oninit: function(v) {
safeMode = v.toLowerCase() == "safe";
}; = {
onstart: function(v) {
if(!readOnly || store.tiddlerExists(v) || store.isShadowTiddler(v))
config.paramifiers.story = {
onstart: function(v) {
var list = store.getTiddlerText(v,"").parseParams("open",null,false);
}; = {
onstart: function(v) {,false,false);
config.paramifiers.searchRegExp = {
onstart: function(v) {,false,true);
config.paramifiers.tag = {
onstart: function(v) {
config.paramifiers.newTiddler = {
onstart: function(v) {
var args = v.parseParams("anon", null, null)[0];
var title = args.title ? args.title[0] : v;
var customFields = args.fields ? args.fields[0] : null;
if(!readOnly) {
var i,tags = args.tag || [];
for(i=0;i<tags.length;i++) {
config.paramifiers.newJournal = {
onstart: function(v) {
if(!readOnly) {
var now = new Date();
var title = now.formatString(v.trim());
config.paramifiers.readOnly = {
onconfig: function(v) {
var p = v.toLowerCase();
readOnly = p == "yes" ? true : (p == "no" ? false : readOnly);
config.paramifiers.theme = {
onconfig: function(v) {
config.paramifiers.upgrade = {
onstart: function(v) {
config.paramifiers.recent= {
onstart: function(v) {
var titles=[];
var i,tiddlers=store.getTiddlers("modified","excludeLists").reverse();
for(i=0; i<v && i<tiddlers.length; i++)
config.paramifiers.filter = {
onstart: function(v) {
//-- Formatter helpers
function Formatter(formatters)
var n;
this.formatters = [];
var pattern = [];
for(n=0; n<formatters.length; n++) {
pattern.push("(" + formatters[n].match + ")");
this.formatterRegExp = new RegExp(pattern.join("|"),"mg");
config.formatterHelpers = {
createElementAndWikify: function(w)
inlineCssHelper: function(w)
var styles = [];
config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
var s,v;
if(lookaheadMatch[1]) {
s = lookaheadMatch[1].unDash();
v = lookaheadMatch[2];
} else {
s = lookaheadMatch[3].unDash();
v = lookaheadMatch[4];
s = "backgroundColor";
s = "cssFloat";
styles.push({style: s, value: v});
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
return styles;
applyCssHelper: function(e,styles)
var t;
for(t=0; t< styles.length; t++) {
try {[styles[t].style] = styles[t].value;
} catch (ex) {
enclosedTextHelper: function(w)
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var text = lookaheadMatch[1];
if(config.browser.isIE && (config.browser.ieVersion[1] < 10))
text = text.replace(/\n/g,"\r");
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
isExternalLink: function(link)
if(store.tiddlerExists(link) || store.isShadowTiddler(link)) {
return false;
var urlRegExp = new RegExp(config.textPrimitives.urlPattern,"mg");
if(urlRegExp.exec(link)) {
return true;
if(link.indexOf(".")!=-1 || link.indexOf("\\")!=-1 || link.indexOf("/")!=-1 || link.indexOf("#")!=-1) {
return true;
return false;
//-- Standard formatters
config.formatters = [
name: "table",
match: "^\\|(?:[^\\n]*)\\|(?:[fhck]?)$",
lookaheadRegExp: /^\|([^\n]*)\|([fhck]?)$/mg,
rowTermRegExp: /(\|(?:[fhck]?)$\n?)/mg,
cellRegExp: /(?:\|([^\n\|]*)\|)|(\|[fhck]?$\n?)/mg,
cellTermRegExp: /((?:\x20*)\|)/mg,
rowTypes: {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
handler: function(w)
var table = createTiddlyElement(w.output,"table",null,"twtable");
var prevColumns = [];
var currRowType = null;
var rowContainer;
var rowCount = 0;
var onmouseover = function() {jQuery(this).addClass("hoverRow");};
var onmouseout = function() {jQuery(this).removeClass("hoverRow");};
w.nextMatch = w.matchStart;
this.lookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
var nextRowType = lookaheadMatch[2];
if(nextRowType == "k") {
table.className = lookaheadMatch[1];
w.nextMatch += lookaheadMatch[0].length+1;
} else {
if(nextRowType != currRowType) {
rowContainer = createTiddlyElement(table,this.rowTypes[nextRowType]);
currRowType = nextRowType;
if(currRowType == "c") {
// Caption
if(rowContainer != table.firstChild)
rowContainer.setAttribute("align",rowCount == 0?"top":"bottom");
} else {
var theRow = createTiddlyElement(rowContainer,"tr",null,rowCount%2?"oddRow":"evenRow");
theRow.onmouseover = onmouseover;
theRow.onmouseout = onmouseout;
this.lookaheadRegExp.lastIndex = w.nextMatch;
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
rowHandler: function(w,e,prevColumns)
var col = 0;
var colSpanCount = 1;
var prevCell = null;
this.cellRegExp.lastIndex = w.nextMatch;
var cellMatch = this.cellRegExp.exec(w.source);
while(cellMatch && cellMatch.index == w.nextMatch) {
if(cellMatch[1] == "~") {
// Rowspan