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

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

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

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

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

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

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

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
	
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

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

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

----
Also see AdvancedOptions
<<importTiddlers>>
This TiddlyWiki initialization
TiddlyHome Site
*added [[Tickets]] and [[Changes]]
*Changes url in all [[Commands]] ("../th/" -> "/_th/)
siteForm.php
*Change ''Group'' with ''Author Team''
~SiteClass.php
*''owner'' always added to ''group''
*Install TiddlyHome site in NewsWiki model
*release new version of TiddlyHome Site
*Upgrade to TiddlyWiki 2.2.0
*Upgrade to NewsWiki 1.0.0
*Upgrade to TiddlyWiki 2.2.4
*change in _th/lib/Htpasswd.php
**On Windows password isn't encrpted see :  [[Password Management in TiddlyHome on Windows]] for details
New release TiddlyHome 0.1.0
*index.html and Admin use NewsWiki 1.2.0
*TiddlyHomeSetupPlugin 1.1.0
*core is externalized in _th/lib/twcore.js
**Templates use externalized core
**download.php expands referenced javascript (src=...) 
**store.php retract javascript (reinstall src=...)
**sites sorted by modified in admin/sites.php 
*proxy full functionnal in TiddlyHome
**LoadRemoteFileThroughProxy added in TiddlyHomeSystem
**proxy.php don't need allowedsites.txt in the same domain
**Add TiddlyHomeSetupPlugin shadow SiteProxy added by TiddlyHomeSetupPlugin as shadow tiddler
New release TiddlyHome 0.1.1 :
*_th/lib/twcore.js : TiddlyWiki 2.2.5 core
release of [[TiddlyHome 0.1.2|TiddlyHomePackage_0.1.2.zip]]
Changes :
*_th/lib/twcore.js : TiddlyWiki 2.3.0 core<br>From now all TiddlyHome hosted TiddlyWikis use this new release.
*MarkupPreBody : Content display in the //info:// google request like in http://www.google.com/search?q=info:tiddlywiki.bidix.info

Author: BidiX
Vertical : NewsWiki 1.2.0
Motor: TiddlyWiki <<version>>
<<changeMode>>
Background: #fff
Foreground: #333
PrimaryPale: #FFBFBF
PrimaryLight: #BF2323
PrimaryMid: #BF2323
PrimaryDark: #660000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #ff0000
<<viewPalette>>
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>
<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>
<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>
<div macro="showWhenExists EditPanelTemplate">[[EditPanelTemplate]]</div>
<div class='editor' macro='edit text'></div>
<!--}}}-->
<<search>>
<<closeAll>>
<<newTiddler tag:News >>
<<newJournal title:'0DD/0MM/YYYY' label: "nouveau journal" tag:Journal tag:excludeLists>>
----
<<saveChanges>>
<<uploadToHome>>
<html><a href=download.php class='button'>download</a></html>
----
<<changeMode Reader>>
<<tiddler IsDirty>><<changeMode Author>>
<<changeMode>>
Author : <<option txtUserName>>
<!--{{{-->
<div id='header' class='header'>
	<div id='topMenu' refresh='content' tiddler='TopMenu'></div> 
	<div class='siteTitle'>
 		<span refresh='content' tiddler='IsDirty'></span>
 		<span refresh='content' tiddler='SiteTitle'></span>
	</div>
	<div class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></div>
</div>
<div id='sidebar'>
	<div id='sidebarOptions' refresh='content' tiddler='AuthorMenu'></div>
	<div id='sidebarTabs' refresh='content' force='true' tiddler='AuthorSidebarTabs'></div>
</div>
<div id='displayArea'>
	<div id='messageArea'></div>
	<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<<tabs txtMainTab "Chrono" "Affichage chronologique des éléments utilisateur" UserTabTimeline "Alpha" "Liste aphabétique des éléments utilisateur" TabUser "Index" "Liste des index utilisateur" UserTabTags>>
[[CommunStyleSheet]]
/*{{{*/
body {
	margin: 0 30px 0 30px;
 }
#sidebarTabs {
	font-size: .8em;
	line-height: 1em; 
}



/*}}}*/

<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title'>
	<span class='title' macro='view title'></span>
	<!--<span macro="miniTag">--></span>
</div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date [[DD MMM YYYY]]'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date [[DD MMM YYYY]]'></span>)</div>
<div class='tagged' macro='tags'></div>
<div class='tagClear'></div>
<div class='viewer' macro='view text wikified'></div>
<div macro="showWhenTagged [[systemList]]">
	<div class='viewer' macro="listByTag '' created  ''"></div>
</div>
<div class='tagging' macro='tagging'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
|''Name:''|AutoWeavePlugin|
|''Description:''|Automatically adds brackets to nonwikiwords on saving a tiddler.|
|''Version:''|0.1 (March 09, 2007)|
|''Source:''|http://weave.tiddlyspot.com/index.html#AutoWeavePlugin|
|''Author:''|laurence man|
|''[[License]]:''|[[BSD open source license]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Tested on: Firefox 2.0; InternetExplorer 6.0|
|''Patched:''|*Don't AutoWeave tiddlers tagged 'admin' <br>*changes [[excludeLists]] by [[admin]] in selected tiddlers<br>*don't AutoWeave when in adminMode|


!Description
Inspired by [[this|http://groups.google.com/group/TiddlyWiki/browse_thread/thread/93b8de752492ddc4/b0608ebb1149578c]] post on the tiddlywiki google group, and with helpful comments by Eric Shulman, this plugin automatically adds enclosing double brackets to nonwikiwords (i.e., auto linking them) on saving a tiddler. This does not affect the usual autolinking of wikiword tiddler titles.

A nonwikiword tiddler title will be double bracketed if it is found in the tiddler text, and if the title does not have any letters or numbers around it.

!Usage
By default only the first occurrence of each nonwikiword title in the text is auto-bracketed. To bracket all occurrences, change the following line in the below code:
{{{
var replaceOnlyFirst = true;
}}}
to
{{{
var replaceOnlyFirst = false;
}}}

You can also specify a list of tiddler titles that you do not want to be auto-bracketed. By default, the name of the tiddler containing the titles to exclude is called {{{noAutoLink}}}. That name can be specified by changing the following line in the code below:
{{{
var excludeThese = "noAutoLink";
}}}
to
{{{
var excludeThese = "whatever you want";
}}}

In your "noAutoTag" tiddler, each line should contain only one tiddler title to exclude from auto-bracketing. Don't add any spaces on that line unless they are in the tiddler title itself. For example:
{{{
montypython
xmas list - 2007
culture of capitalism - notes
}}}

!Problems/Limitations/Notes
* Can't handle tiddler titles with square brackets in them so they're ignored.
* Can choose to autolink only first occurrence of title, but if you edit the tiddler later and add that title into the tiddler text before the first occurrence of the title, it will be bracketed.
* Shadowed tiddlers and tiddlers tagged with "[[excludeLists]]" are not auto-bracketed.

!Code
***/
//{{{
TiddlyWiki.prototype.saveTiddler_weaveLinks =
TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler =
function(title,newTitle,newBody,modifier,modified,tags)
{
/*
 * BidiX : if mode = admin, no AutoWeave
 */
	if ((config.macros.changeMode) &&  (config.macros.changeMode.currentMode == '') )
		return this.saveTiddler_weaveLinks.apply(this, arguments);	 

 // User settings

 var replaceOnlyFirst = true;
 var excludeThese = "noAutoLink";

    // Don't tag the list of tiddler titles to exclude.
    if (title == excludeThese) 
        return this.saveTiddler_weaveLinks.apply(this, arguments);
	var tagArray = tags.readBracketedList();
	if (tagArray && tagArray.contains('admin'))
		return this.saveTiddler_weaveLinks.apply(this, arguments);


    // Helpers
    // ------------------------------------------------------------------------

    // To sort titles into descending length.
    var compareDescLen = function(a, b)
    {
        if (a.length == b.length) return 0;
        return b.length - a.length;
    }


    var isBounded = function(start, end)
    // [[Test]] if tiddler title has a non-alphanum char (or nothing) on each side.
    // Takes both indices of the title match, along with the title itself.
    {
        var reAlphaNum = new RegExp("\[\A-Za-z0-9\]");
        
        return !(start != 0 && reAlphaNum.test(newBody.substr(start - 1, 1)) ||
                 end != newBody.length - 1 && 
                 reAlphaNum.test( newBody.substr(end + 1, 1)));
    }

    var isBracketed = function(start, end)
    // Is matched string within given indices enclosed in pairs of brackets?
    // Assumes brackets aren't allowed in titles (even tiddler text); 
    // bumping into pair of non-enclosing brackets means string isn't enclosed.
    {
        var foundL = false;
        var foundR = false;
    
        // Start from char just before title up to second char in newBody.
        for (var i = start - 1; i > 0; i--)
        {
            if (newBody.charAt(i) == ']' && newBody.charAt(i - 1) == ']') 
                return false;
            if (newBody.charAt(i) == '[' && newBody.charAt(i - 1) == '[')
            {
                foundL = true;
                break;
            }
        }
        
        // Look from next char after title up to second last char.
        for (var i = end + 1; i < newBody.length - 1; i++)
        {
            if (newBody.charAt(i) == '[' && newBody.charAt(i + 1) == '[') 
                return false;
            if (newBody.charAt(i) == ']' && newBody.charAt(i + 1) == ']')
            {
                foundR = true; 
                break;
            }
        }
        return foundL && foundR;
    }
    
     
    var isNonWikiWord = function(word)
    // No brackets though they're allowed in tiddler titles.
    {
        return (word.indexOf(" ") != -1 ||
               word.search(config.textPrimitives.wikiLink) == -1) &&
               word.indexOf("[") == -1 &&
               word.indexOf("]") == -1;
    }
    
    var isUsrExcluded = function(currTitle)
    // Checks given tiddler title against those in the excluded list.
    {
        if (excludeArr)
        {
            for(var i = 0; i < excludeArr.length; i++)
                if (excludeArr[i] == currTitle) return true;
        }
        return false;
    }


//   var tids = store.getTiddlers("title","excludeLists");
	var tids = store.getTiddlers("title","admin");
    var arr = new Array(tids.length); // Titles to use: to be filtered, sorted.
    var arrLen = 0;                   // Number of titles.
    var matchIdx;                     // Index of a matching title.
    var searchIdx;                     // Searching from this index in newBody.
    var excludeArr;

    var titlesToExclude = store.getTiddlerText(excludeThese);
    
    // split(/\n/) might not be ok with IE?
    if (titlesToExclude) excludeArr = titlesToExclude.split('\n');

    // Filter list of titles.
    for (var i = 0; i < arr.length; i++)
    {
        if (isNonWikiWord(tids[i].title) && !isUsrExcluded(tids[i].title))
        {
            arr[arrLen] = tids[i].title;
            arrLen++;
        }
    }

    arr.sort(compareDescLen);

    // Main loop
    for (var i = 0; i < arrLen; i++)
    {
        searchIdx = 0;      // Start search for title at start of newBody.

        // If a match, replace if not bracketed and if it is free of alphanum
        // on either side. Search again from end of matching title in newBody.
        // Should maybe rewrite this using regexp.exec.

        for ( ; ;)
        {
            matchIdx = newBody.indexOf(arr[i], searchIdx);
            if (matchIdx == -1) break;

            var brackets = isBracketed(matchIdx, matchIdx + arr[i].length - 1);
            if (brackets && replaceOnlyFirst) break;
            
            if (isBounded(matchIdx, matchIdx + arr[i].length - 1, arr[i]) 
                && !brackets)
            {
                newBody = newBody.substring(0, matchIdx) + 
                        "[[" + arr[i] + "]]" + 
                        newBody.substring(matchIdx + arr[i].length);

                if (replaceOnlyFirst) break;
            }
            searchIdx = matchIdx + arr[i].length + 1;
        }
    }

return this.saveTiddler_weaveLinks.apply(this, arguments);
}
//}}}
Copyright (c) 2005-2007, BidiX (http://BidiX.info)

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 BidiX nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Contact : [[BidiX@bidix.info|mailto:BidiX@BidiX.info]]
URL : [[BidiX.info|http://BidiX.info/]]
Donation : [[Donation via Paypal|https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=BidiX%40bidix%2einfo&item_name=TiddlyWikiHacking%20Donations&item_number=Donations&no_shipping=2&no_note=1&tax=0&currency_code=EUR&bn=PP%2dDonationsBF&charset=UTF%2d8]] 
|''URL:''|http://tiddlywiki.bidix.info/|
|''Description:''|Repository for BidiX's TiddlyWiki Extensions|
|''Author:''|BidiX|
/***
''Name:'' CalendarPlugin
''Version:'' <<getversion calendar>> (<<getversiondate calendar "DD MMM YYYY">>)
''Author:'' SteveRumsby

''Configuration:''

|''First day of week:''|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
|''First day of weekend:''|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|

''Syntax:'' 
|{{{<<calendar>>}}}|Produce a full-year calendar for the current year|
|{{{<<calendar year>>}}}|Produce a full-year calendar for the given year|
|{{{<<calendar year month>>}}}|Produce a one-month calendar for the given month and year|
|{{{<<calendar thismonth>>}}}|Produce a one-month calendar for the current month|
|{{{<<calendar lastmonth>>}}}|Produce a one-month calendar for last month|
|{{{<<calendar nextmonth>>}}}|Produce a one-month calendar for next month|

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

// // ''[[Changes]] by ELS 2005.10.30:''
// // config.macros.calendar.handler()
// // ^^use "tbody" element for IE compatibility^^
// // ^^IE returns 2005 for current year, FF returns 105... fix year adjustment accordingly^^
// // createCalendarDays()
// // ^^use showDate() function (if defined) to render autostyled date with linked popup^^
// // calendar stylesheet definition
// // ^^use .calendar class-specific selectors, add text centering and margin settings^^

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

config.macros.calendar.monthnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.macros.calendar.daynames = ["M", "T", "W", "T", "F", "S", "S"];

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

//}}}
// //''Code section:''
// (you should not need to alter anything below here)//
//{{{
if(config.options.txtCalFirstDay == undefined)
  config.options.txtCalFirstDay = 0;
if(config.options.txtCalStartOfWeekend == undefined)
  config.options.txtCalStartOfWeekend = 5;

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

version.extensions.calendar = { major: 0, minor: 6, revision: 0, date: new Date(2006, 1, 22)};
config.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

config.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead
//}}}

// //Is the given date a holiday?
//{{{
function calendarIsHoliday(date)
{
 var longHoliday = date.formatString("0DD/0MM/YYYY");
 var shortHoliday = date.formatString("0DD/0MM");

 for(var i = 0; i < config.macros.calendar.holidays.length; i++) {
   if(config.macros.calendar.holidays[i] == longHoliday || config.macros.calendar.holidays[i] == shortHoliday) {
     return true;
   }
 }
 return false;
}
//}}}

// //The main entry point - the macro handler.
// //Decide what sort of calendar we are creating (month or year, and which month or year)
// // Create the main calendar container and pass that to sub-ordinate functions to create the structure.
// ELS 2005.10.30: added creation and use of "tbody" for IE compatibility and fixup for year >1900//
// ELS 2005.10.30: fix year calculation for IE's getYear() function (which returns '2005' instead of '105')//
//{{{
config.macros.calendar.handler = function(place,macroName,params)
{
   var calendar = createTiddlyElement(place, "table", null, "calendar", null);
   var tbody = createTiddlyElement(calendar, "tbody", null, null, null);
   var today = new Date();
   var year = today.getYear();
   if (year<1900) year+=1900;
   if (params[0] == "thismonth")
  {
      cacheReminders(new Date(year, today.getMonth(), 1, 0, 0), 31);
      createCalendarOneMonth(tbody, year, today.getMonth());
  } 
  else if (params[0] == "lastmonth") {
      var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
      cacheReminders(new Date(year, month, 1, 0, 0), 31);
      createCalendarOneMonth(tbody, year, month);
   }
   else if (params[0] == "nextmonth") {
      var month = today.getMonth()+1; if (month>11) { month=0; year++; }
      cacheReminders(new Date(year, month, 1, 0, 0), 31);
      createCalendarOneMonth(tbody, year, month);
   }
   else {
      if (params[0]) year = params[0];
      if(params[1])
      {
         cacheReminders(new Date(year, params[1]-1, 1, 0, 0), 31);
         createCalendarOneMonth(tbody, year, params[1]-1);
      }
      else
      {
         cacheReminders(new Date(year, 0, 1, 0, 0), 366);
         createCalendarYear(tbody, year);
      }
   }
  window.reminderCacheForCalendar = null;
}
//}}}
//{{{
//This global variable is used to store reminders that have been cached
//while the calendar is being rendered.  It will be renulled after the calendar is fully rendered.
window.reminderCacheForCalendar = null;
//}}}
//{{{
function cacheReminders(date, leadtime)
{
  if (window.findTiddlersWithReminders == null)
    return;
  window.reminderCacheForCalendar = {};
  var leadtimeHash = [];
  leadtimeHash [0] = 0;
  leadtimeHash [1] = leadtime;
  var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);
  for(var i = 0; i < t.length; i++) {
    //just tag it in the cache, so that when we're drawing days, we can bold this one.
     window.reminderCacheForCalendar[t[i]["matchedDate"]] = "reminder:" + t[i]["params"]["title"]; 
  }
}
//}}}
//{{{
function createCalendarOneMonth(calendar, year, mon)
{
  var row = createTiddlyElement(calendar, "tr", null, null, null);
  createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);
  row = createTiddlyElement(calendar, "tr", null, null, null);
  createCalendarDayHeader(row, 1);
  createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}

//{{{
function createCalendarMonth(calendar, year, mon)
{
  var row = createTiddlyElement(calendar, "tr", null, null, null);
  createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, false, year, mon);
  row = createTiddlyElement(calendar, "tr", null, null, null);
  createCalendarDayHeader(row, 1);
  createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}

//{{{
function createCalendarYear(calendar, year)
{
  var row;
  row = createTiddlyElement(calendar, "tr", null, null, null);
  var back = createTiddlyElement(row, "td", null, null, null);
  var backHandler = function() {
      removeChildren(calendar);
      createCalendarYear(calendar, year-1);
    };
  createTiddlyButton(back, "<", "Previous year", backHandler);
  back.align = "center";

  var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);
  yearHeader.align = "center";
  yearHeader.setAttribute("colSpan", 19);

  var fwd = createTiddlyElement(row, "td", null, null, null);
  var fwdHandler = function() {
    removeChildren(calendar);
    createCalendarYear(calendar, year+1);
  };
  createTiddlyButton(fwd, ">", "Next year", fwdHandler);
  fwd.align = "center";

  createCalendarMonthRow(calendar, year, 0);
  createCalendarMonthRow(calendar, year, 3);
  createCalendarMonthRow(calendar, year, 6);
  createCalendarMonthRow(calendar, year, 9);
}
//}}}

//{{{
function createCalendarMonthRow(cal, year, mon)
{
  var row = createTiddlyElement(cal, "tr", null, null, null);
  createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);
  createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);
  createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);
  row = createTiddlyElement(cal, "tr", null, null, null);
  createCalendarDayHeader(row, 3);
  createCalendarDayRows(cal, year, mon);
}
//}}}

//{{{
function createCalendarMonthHeader(cal, row, name, nav, year, mon)
{
  var month;
  if(nav) {
    var back = createTiddlyElement(row, "td", null, null, null);
    back.align = "center";
    back.style.background = config.macros.calendar.monthbg;

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

    var backYearHandler = function() {
      var newyear = year-1;
      removeChildren(cal);
      cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
      createCalendarOneMonth(cal, newyear, mon);
    };
    createTiddlyButton(back, "<<", "Previous year", backYearHandler);
*/
    var backMonHandler = function() {
      var newyear = year;
      var newmon = mon-1;
      if(newmon == -1) { newmon = 11; newyear = newyear-1;}
      removeChildren(cal);
      cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
      createCalendarOneMonth(cal, newyear, newmon);
    };
    createTiddlyButton(back, "<", "Previous month", backMonHandler);


    month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
//    month.setAttribute("colSpan", 3);
    month.setAttribute("colSpan", 5);

    var fwd = createTiddlyElement(row, "td", null, null, null);
    fwd.align = "center";
    fwd.style.background = config.macros.calendar.monthbg; 

//    fwd.setAttribute("colSpan", 2);
    var fwdMonHandler = function() {
      var newyear = year;
      var newmon = mon+1;
      if(newmon == 12) { newmon = 0; newyear = newyear+1;}
      removeChildren(cal);
      cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
      createCalendarOneMonth(cal, newyear, newmon);
    };
    createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);
/*
    var fwdYear = createTiddlyElement(row, "td", null, null, null);
    var fwdYearHandler = function() {
      var newyear = year+1;
      removeChildren(cal);
      cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
      createCalendarOneMonth(cal, newyear, mon);
    };
    createTiddlyButton(fwd, ">>", "Next year", fwdYearHandler);
*/
  } else {
    month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
    month.setAttribute("colSpan", 7);
  }
  month.align = "center";
  month.style.background = config.macros.calendar.monthbg;
}
//}}}

//{{{
function createCalendarDayHeader(row, num)
{
  var cell;
  for(var i = 0; i < num; i++) {
    for(var j = 0; j < 7; j++) {
      var d = j + (config.options.txtCalFirstDay - 0);
      if(d > 6) d = d - 7;
      cell = createTiddlyElement(row, "td", null, null, config.macros.calendar.daynames[d]);

      if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))
        cell.style.background = config.macros.calendar.weekendbg;
    }
  }
}
//}}}

//{{{
function createCalendarDays(row, col, first, max, year, mon)
{
  var i;
  for(i = 0; i < col; i++) {
    createTiddlyElement(row, "td", null, null, null);
  }
  var day = first;
  for(i = col; i < 7; i++) {
    var d = i + (config.options.txtCalFirstDay - 0);
    if(d > 6) d = d - 7;
    var daycell = createTiddlyElement(row, "td", null, null, null);
    var isaWeekend = ((d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))? true:false);

    if(day > 0 && day <= max) {
      var celldate = new Date(year, mon, day);
      // ELS 2005.10.30: use <<date>> macro's showDate() function to create popup
      if (window.showDate) {
        showDate(daycell,celldate,"popup","DD","DD-MMM-YYYY",true, isaWeekend); 
      } else {
        if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
        var title = celldate.formatString(config.macros.calendar.tiddlerformat);
        if(calendarIsHoliday(celldate)) {
          daycell.style.background = config.macros.calendar.holidaybg;
        }
        if(window.findTiddlersWithReminders == null) {
          var link = createTiddlyLink(daycell, title, false);
          link.appendChild(document.createTextNode(day));
        } else {
          var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
        }
      }
    }
    day++;
  }
}
//}}}

// //We've clicked on a day in a calendar - create a suitable pop-up of options.
// //The pop-up should contain:
// // * a link to create a new entry for that date
// // * a link to create a new reminder for that date
// // * an <hr>
// // * the list of reminders for that date
//{{{
function onClickCalendarDate(e)
{
  var button = this;
  var date = button.getAttribute("title");
  var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));

  date = dat.formatString(config.macros.calendar.tiddlerformat);
  var popup = createTiddlerPopup(this);
  popup.appendChild(document.createTextNode(date));
  var newReminder = function() {
    var t = store.getTiddlers(date);
    displayTiddler(null, date, 2, null, null, false, false);
    if(t) {
      document.getElementById("editorBody" + date).value += "\n<<reminder day:" + dat.getDate() +
                                                                                         " month:" + (dat.getMonth()+1) +
                                                                                         " year:" + (dat.getYear()+1900) + " title: >>";
    } else {
      document.getElementById("editorBody" + date).value = "<<reminder day:" + dat.getDate() +
                                                                                       " month:" + (dat.getMonth()+1) +
                                                                                       " year:" + (dat.getYear()+1900) + " title: >>";
    }
  };
  var link = createTiddlyButton(popup, "New reminder", null, newReminder); 
  popup.appendChild(document.createElement("hr"));

  var t = findTiddlersWithReminders(dat, [0,14], null, 1);
  for(var i = 0; i < t.length; i++) {
    link = createTiddlyLink(popup, t[i].tiddler, false);
    link.appendChild(document.createTextNode(t[i].tiddler));
  }
}
//}}}

//{{{
function calendarMaxDays(year, mon)
{
 var max = config.macros.calendar.monthdays[mon];
 if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {
 max++;
 }
 return max;
}
//}}}

//{{{
function createCalendarDayRows(cal, year, mon)
{
 var row = createTiddlyElement(cal, "tr", null, null, null);

 var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
 if(first1 < 0) first1 = first1 + 7;
 var day1 = -first1 + 1;
 var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
 if(first2 < 0) first2 = first2 + 7;
 var day2 = -first2 + 1;
 var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
 if(first3 < 0) first3 = first3 + 7;
 var day3 = -first3 + 1;

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

 while(day1 <= max1 || day2 <= max2 || day3 <= max3) {
 row = createTiddlyElement(cal, "tr", null, null, null);
 createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
 createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;
 createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;
 }
}
//}}}

//{{{
function createCalendarDayRowsSingle(cal, year, mon)
{
 var row = createTiddlyElement(cal, "tr", null, null, null);

 var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
 if(first1 < 0) first1 = first1+ 7;
 var day1 = -first1 + 1;
 var max1 = calendarMaxDays(year, mon);

 while(day1 <= max1) {
 row = createTiddlyElement(cal, "tr", null, null, null);
 createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
 }
}
//}}}

// //ELS 2005.10.30: added styles
//{{{
setStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { font-size:10pt; text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }", "calendarStyles");
//}}}
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/site.php?next=change%20access" width=100% height=200px>
</iframe>
</html>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/site.php?next=change%20group" width=100% height=200px>
</iframe>
</html>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/user.php?next=change%20email" width=100% height=200px>
</iframe>
</html>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/user.php?next=change%20password" width=100% height=200px>
</iframe>
</html>
/***
|''Name:''|ChangeModePlugin|
|''Description:''|Change template and styleSheet|
|''Credits:''|SaqImtiaz for is PresentationPlugin|
|''Version:''|0.0.4|
|''Date:''|Jun 5, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#changeModePlugin|
|''Usage:''|{{{<<changeMode [newMode]>>}}}<br>{{{newMode: if omitted the default mode is applied}}}|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.ChangeModePlugin = 
{
	major: 0, minor: 0, revision: 4, 
	date: new Date("Jun 9, 2007"),
	source: 'http://tiddlywiki.bidix.info/#ChangeModePlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

// From SaqImtiaz's PresentationPlugin
//---------------------------------------------------
TiddlyWiki.prototype.isTiddler= function (title) 
{
	return store.tiddlerExists(title) || store.isShadowTiddler(title);
};

TiddlyWiki.prototype.removeNotification = function(title,fn) 
{
	for (var i=0; i<this.namedNotifications.length; i++)
	if((this.namedNotifications[i].name == title) && (this.namedNotifications[i].notify == fn))
 		this.namedNotifications.splice(i,1);
};

Story.prototype.chooseTemplateForTiddler_core = Story.prototype.chooseTemplateForTiddler;

Story.prototype.chooseTemplateForTiddler = function(title,template)
{
	if (!template)
 		template = DEFAULT_VIEW_TEMPLATE;
 	var mode = config.macros.changeMode.currentMode;
 	if (template == DEFAULT_VIEW_TEMPLATE) {
 		if (store.isTiddler(mode+"ViewTemplate"))
 			return mode+"ViewTemplate";
 	} else if (template == DEFAULT_EDIT_TEMPLATE) {
 		if (store.isTiddler(mode+"EditTemplate"))
 			return mode+"EditTemplate";
 	}
 	return this.chooseTemplateForTiddler_core(title,template);
}


Story.prototype.lewcidrefreshAllTiddlers = function() 
{
	var place = document.getElementById(this.container);
 	var e = place.firstChild;
 	if(!e) return;
 	this.refreshTiddler(e.getAttribute("tiddler"),null,true);
 	while((e = e.nextSibling) != null)
 		this.refreshTiddler(e.getAttribute("tiddler"),null,true);
}
//---------------------------------------------------
// manage different modes
// 
// config.macros.changeMode.initMode: the name of the initial Mode
// config.macros.changeMode.readOnlyModes: array containing readOnly mode (no Backstage and readOnly)
//

config.macros.changeMode = 
{
	currentMode: '',	// defaultMode
	initMode: 'Reader',
	readOnlyModes : ['Reader'],
	noBackstage : ['Reader', 'Author'],
	singlePageMode: ['Reader', 'Author'],
	lingo: {
		label: "%0 Mode",
		prompt: "Change the current mode to '%0'",
		modeName: {
			Author: 'Author',
			Reader: 'Reader',
			'': '(default)'
		}
	},
	handler: function(place,macroName,params) {
		var newMode = (params[0] ? params[0]: ""); // default to ''
		var newModeName = (this.lingo.modeName[newMode] ? this.lingo.modeName[newMode]: newMode); // default to ''
		var label = this.lingo.label.format([newModeName]);
		var prompt = this.lingo.prompt.format([newModeName]);
		createTiddlyButton(place, label, prompt, function() {config.macros.changeMode.action(newMode);}, null, null, null);		
	},	
	action: function(template) {
		config.macros.changeMode.applyMode(template);
	},
	defaults: [
		{name: "StyleSheet", notify: refreshStyles},
		{name: "PageTemplate", notify: refreshPageTemplate}
	],	
	applyMode: function (newMode) {
		var oldMode = this.currentMode;
		var oldStyleElement = document.getElementById(oldMode+"StyleSheet");
		if (oldStyleElement) {
			oldStyleElement.parentNode.removeChild(oldStyleElement);
		}
		// change Palette
		if (store.isTiddler(newMode + 'ColorPalette')) {
			var tiddler = new Tiddler('ColorPalette');
			tiddler.tags.push('admin');
			if (!newMode) {
				if (store.isTiddler('defaultColorPalette'))
					tiddler.text = store.getTiddlerText('defaultColorPalette');
				else
					tiddler.text = config.shadowTiddlers['ColorPalette'];
				} else {
				tiddler.text = store.getTiddlerText(newMode + 'ColorPalette');
			}
			store.addTiddler(tiddler);
		}
		for (var i=0; i< this.defaults.length; i++)
		{
			var name = this.defaults[i]["name"];
			var newElement = store.isTiddler(newMode + name) ? newMode + name : name;
			store.removeNotification(oldMode + name, this.defaults[i]["notify"]);
			store.addNotification(newElement,this.defaults[i]["notify"]);
			store.notify(newElement); //just one do blanket notify instead?
		}
		if (backstage && !backstage.button)
			backstage.init();
		// change readOnly
		if (this.readOnlyModes.indexOf(newMode) == -1) {
			readOnly = false;
		}
		else {
			readOnly = true;
		}	
		// change backstage display
		if (backstage && backstage.button) {
			if (this.noBackstage.indexOf(newMode) == -1) {
				backstage.button.style.display = "block";
			}
			else {
				backstage.hide();
				backstage.button.style.display = "none";
			}
		// change singlePageMode
		if (this.singlePageMode.indexOf(newMode) == -1) {
			config.options.chkSinglePageMode = false;
		}
		else {
			config.options.chkSinglePageMode= true;
		}	

		}
			
		
		this.currentMode = newMode;
		story.lewcidrefreshAllTiddlers ();
		// store.refreshPalette();
		store.notifyAll();
		},
	init: function() {
		if (!store.isTiddler('defaultColorPalette'))
			config.shadowTiddlers['defaultColorPalette'] = config.shadowTiddlers['ColorPalette'];
		config.macros.changeMode.applyMode(this.initMode);
	}
}

config.paramifiers.mode = {
	onconfig: function(mode) {
		if (mode == 'false')
			config.macros.changeMode.initMode = null;
		else
			config.macros.changeMode.initMode = mode;	
	}
};


//}}}

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
Tags all TiddlyHome commands. 

There are commands for :
* <<tag User>>
* <<tag Site>>
/*{{{*/

body {
	background:[[ColorPalette::Background]];
	margin:0 auto;
	font-size: 85%;
	color: [[ColorPalette::Foreground]];
	position: relative;
	font-family: Helvetica, Arial, sans-serif; 
}


h1,h2,h3,h4,h5 {
	font-weight: normal;
	padding-left: 0;
	color: [[ColorPalette::TertiaryDark]];
	background: transparent;
}

h1 {font-size: 1.5em; font-weight: normal;border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2 {font-size: 1.3em; border-bottom:0px;}
h3 {font-size: 1.1em; border-bottom:0px;}
h4 {font-size: 1em;}
h5 {font-size: .9em;}


ul, ul ul, ul ul ul {
list-style-image: url(http://tiddlyhome.bidix.info/_th/images/square.gif) ;
}

a { 
	color: [[ColorPalette::PrimaryMid]]; 
}

a:hover {
	color: [[ColorPalette::PrimaryMid]]; 
	background:transparent; 
	border-bottom:1px solid [[ColorPalette::PrimaryMid]]; 
}

.button {
	color: [[ColorPalette::PrimaryMid]]; 
	font-weight:bold; 
}

#header {
	background: [[ColorPalette::Background]];
	padding: 0 0 0 0.4em; 
	height:1%;
}


.siteTitle {
	padding:  1.5em 0 0 0;
	font-weight: normal;
	font-size: 3em;
	color: [[ColorPalette::TertiaryDark]] ; 
}

.siteSubtitle {
	width: 33em;
	padding: 0.3em 0em 0.2em 1em; 
	font-weight: bold;
	font-size: 1em;
	background: [[ColorPalette::PrimaryMid]]; 
	color: [[ColorPalette::Background]]; 
}


#displayArea {
	margin-left:0.5em; 
	margin-right:17.3em; 
	margin-top:3em; 
	padding-top:0em; 
	padding-bottom:10px;
	padding-left: 1em;
}

/*}}}*/


/***
!!Sidebar
***/
/*{{{*/

#sidebar {
	position:absolute; 
	width: 14em;
	border-left:1px solid [[ColorPalette::TertiaryLight]]; 
	padding-left:15px;
	margin-top:0.5em; 
	font-size:1em;
	line-height:1.5em; 
	font-family: Arial,em sans-serif; 
	background-color: [[ColorPalette::Background]];
}

#sidebar a {
	display: inline;
	font-weight: normal;
}

#sidebar h1,#sidebar h2,#sidebar h3,#sidebar h4,#sidebar h5 {
	font-weight: normal;
	margin-bottom:0em;
}


#sidebar h1 {
	margin-left:-0.5em; 
	margin-bottom:0em;
}

#sidebar hr {
	border:0; 
	border-bottom:1px solid [[ColorPalette::TertiaryLight]]; 
	margin: 1em 0; 
	margin-left:-0.5em;
}

#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}

/*}}}*/



/***
!!viewer
***/
/*{{{*/
.title { 
	font-size: 1.5em; 
	font-weight: normal;
	color: [[ColorPalette::TertiaryDark]]; 
	background:transparent; 
	margin: 0; 
	margin-bottom: .5em;
	padding:0;
}

.viewer {
	line-height:1.5em; 
	}

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

.externalLink {font-weight:bold;}
.externalLink:hover {border:none;}

.toolbar { visibility:hidden; }
.selected .toolbar { visibility:visible; }

.tagged, .tagging { float:left; }
.tagged li, .tagging li { display:inline; }  
.tagged, .tagging { background:transparent  !important; border:0  !important; }
.tagged .button {color: [[ColorPalette::TiertiaryPale]] !important; }

/*}}}*/


/***
!!Editor
***/

/*{{{*/
.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}

/*}}}*/

/***
!!TopMenu
***/
/*{{{*/

#topMenu { 
	positon:relative; float:right; display:inline; 
	margin-left:3em; 
	margin-top:1em;
	padding: 0.8em 0em;
}

#topMenu br {display:none; }
#topMenu a, #topMenu .tiddlyLink, #topMenu .button {
	margin:0 1em; 
	color: [[ColorPalette::Foreground]];
	margin-right:0;
	margin-left:2em; 
	font-size: 18px; 
	font-family: Helvetica, sans-serif;
	font-weight: normal;
	font-style: normal;


}
#topMenu a:hover, #topMenu .activebutton {
	border-bottom:5px 
	solid [[ColorPalette::PrimaryMid]];
}

.calendar, .calendar table, .calendar th, .calendar tr, .calendar td { font-size:12pt; text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }


/*}}}*/

/*{{{*/


@media print {
#topMenu {display: none ! important;}
}

/*}}}*/


GettingStarted
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/site.php?next=delete" width=100% height=200px>
</iframe>
</html>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/user.php?next=delete" width=100% height=200px>
</iframe>
</html>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/site.php?next=display" width=100% height=200px>
</iframe>
</html>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/user.php?next=display" width=100% height=200px>
</iframe>
</html>

To install TiddlyHome to your own site :
#[[download|TiddlyHomePackage_0.1.3.zip]] the full package
#unzip and move the TiddlyHome folder in its final location
#go to this file at your own new TiddlyHome at [[Initialize your own TiddlyHome]]
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.6 (2006-09-16)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2006 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description

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

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

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

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

!Code
***/
//{{{

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

 // Perform the action
 var actionName = parameter.actionName ? parameter.actionName : "addToList";
 var action = config.macros.forEachTiddler.actions[actionName];
 if (!action) {
 this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
 return;
 }

 var actionHandler = action.handler;
 actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};

// ---------------------------------------------------------------------------
// The actions 
// ---------------------------------------------------------------------------

// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
 // Parse the parameter
 var p = 0;

 // Check for extra parameters
 if (parameter.length > p) {
 config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
 return;
 }

 // Perform the action.
 var list = document.createElement("ul");
 place.appendChild(list);
 for (var i = 0; i < tiddlers.length; i++) {
 var tiddler = tiddlers[i];
 var listItem = document.createElement("li");
 list.appendChild(listItem);
 createTiddlyLink(listItem, tiddler.title, true);
 }
};

abego.parseNamedParameter = function(name, parameter, i) {
 var beginExpression = null;
 if ((i < parameter.length) && parameter[i] == name) {
 i++;
 if (i >= parameter.length) {
 throw "Missing text behind '%0'".format([name]);
 }
 
 return config.macros.forEachTiddler.paramEncode(parameter[i]);
 }
 return null;
}

// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
 // Parse the parameter
 var p = 0;
 if (p >= parameter.length) {
 this.handleError(place, "Missing expression behind 'write'.");
 return;
 }

 var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
 p++;

 // Parse the "begin" option
 var beginExpression = abego.parseNamedParameter("begin", parameter, p);
 if (beginExpression !== null) 
 p += 2;
 var endExpression = abego.parseNamedParameter("end", parameter, p);
 if (endExpression !== null) 
 p += 2;
 var noneExpression = abego.parseNamedParameter("none", parameter, p);
 if (noneExpression !== null) 
 p += 2;

 // Parse the "toFile" option
 var filename = null;
 var lineSeparator = undefined;
 if ((p < parameter.length) && parameter[p] == "toFile") {
 p++;
 if (p >= parameter.length) {
 this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
 return;
 }
 
 filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
 p++;
 if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
 p++;
 if (p >= parameter.length) {
 this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
 return;
 }
 lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
 p++;
 }
 }
 
 // Check for extra parameters
 if (parameter.length > p) {
 config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
 return;
 }

 // Perform the action.
 var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
 var count = tiddlers.length;
 var text = "";
 if (count > 0 && beginExpression)
 text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
 
 for (var i = 0; i < count; i++) {
 var tiddler = tiddlers[i];
 text += func(tiddler, context, count, i);
 }
 
 if (count > 0 && endExpression)
 text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);

 if (count == 0 && noneExpression) 
 text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
 

 if (filename) {
 if (lineSeparator !== undefined) {
 lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
 text = text.replace(/\n/mg,lineSeparator);
 }
 saveFile(filename, convertUnicodeToUTF8(text));
 } else {
 var wrapper = createTiddlyElement(place, "span");
 wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
 }
};


// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
 return {
 place : placeParam, 
 whereClause : whereClauseParam, 
 sortClause : sortClauseParam, 
 sortAscending : sortAscendingParam, 
 script : scriptText,
 actionName : actionNameParam, 
 actionParameter : actionParameterParam,
 tiddlyWikiPath : tiddlyWikiPathParam,
 inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
 viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
 };
};

// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of 
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
 if (!idPrefix) {
 idPrefix = "store";
 }
 var lenPrefix = idPrefix.length;
 
 // Read the content of the given file
 var content = loadFile(this.getLocalPath(path));
 if(content === null) {
 throw "TiddlyWiki '"+path+"' not found.";
 }
 
 // Locate the storeArea div's
 var posOpeningDiv = content.indexOf(startSaveArea);
 var posClosingDiv = content.lastIndexOf(endSaveArea);
 if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
 throw "File '"+path+"' is not a TiddlyWiki.";
 }
 var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
 
 // Create a "div" element that contains the storage text
 var myStorageDiv = document.createElement("div");
 myStorageDiv.innerHTML = storageText;
 myStorageDiv.normalize();
 
 // Create all tiddlers in a new TiddlyWiki
 // (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
 var tiddlyWiki = new TiddlyWiki();
 var store = myStorageDiv.childNodes;
 for(var t = 0; t < store.length; t++) {
 var e = store[t];
 var title = null;
 if(e.getAttribute)
 title = e.getAttribute("tiddler");
 if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
 title = e.id.substr(lenPrefix);
 if(title && title !== "") {
 var tiddler = tiddlyWiki.createTiddler(title);
 tiddler.loadFromDiv(e,title);
 }
 }
 tiddlyWiki.dirty = false;

 return tiddlyWiki;
};


 
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
// 
// (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
 var script = context["script"];
 var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
 var fullText = (script ? script+";" : "")+functionText+";theFunction;";
 return eval(fullText);
};

// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
 var result = [];
 var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
 tiddlyWiki.forEachTiddler(function(title,tiddler) {
 if (func(tiddler, context, undefined, undefined)) {
 result.push(tiddler);
 }
 });
 return result;
};

// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
 var message = "Extra parameter behind '"+actionName+"':";
 for (var i = firstUnusedIndex; i < parameter.length; i++) {
 message += " "+parameter[i];
 }
 this.handleError(place, message);
};

// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
 var result = 
 (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
 ? 0
 : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
 ? -1 
 : +1; 
 return result;
};

// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
 var result = 
 (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
 ? 0
 : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
 ? +1 
 : -1; 
 return result;
};

// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
 // To avoid evaluating the sortClause whenever two items are compared 
 // we pre-calculate the sortValue for every item in the array and store it in a 
 // temporary property ("forEachTiddlerSortValue") of the tiddlers.
 var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
 var count = tiddlers.length;
 var i;
 for (i = 0; i < count; i++) {
 var tiddler = tiddlers[i];
 tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
 }

 // Do the sorting
 tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);

 // Delete the temporary property that holds the sortValue. 
 for (i = 0; i < tiddlers.length; i++) {
 delete tiddlers[i].forEachTiddlerSortValue;
 }
};


// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
 displayMessage(message);
};

// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
 var message ="<<"+macroName;
 for (var i = 0; i < params.length; i++) {
 message += " "+params[i];
 }
 message += ">>";
 displayMessage(message);
};


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

// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
 if (place) {
 this.createErrorElement(place, exception);
 } else {
 throw exception;
 }
};

// Internal.
//
// Encodes the given string.
//
// Replaces 
// "$))" to ">>"
// "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
 var reGTGT = new RegExp("\\$\\)\\)","mg");
 var reGT = new RegExp("\\$\\)","mg");
 return s.replace(reGTGT, ">>").replace(reGT, ">");
};

// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
// 
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
 // Remove any location part of the URL
 var hashPos = originalPath.indexOf("#");
 if(hashPos != -1)
 originalPath = originalPath.substr(0,hashPos);
 // Convert to a native file format assuming
 // "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
 // "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
 // "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
 // "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
 var localPath;
 if(originalPath.charAt(9) == ":") // pc local file
 localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
 else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
 localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
 else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
 localPath = unescape(originalPath.substr(7));
 else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
 localPath = unescape(originalPath.substr(5));
 else // pc network file
 localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\"); 
 return localPath;
};

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

//============================================================================
// End of forEachTiddler Macro
//============================================================================


//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
 var n = prefix.length;
 return (this.length >= n) && (this.slice(0, n) == prefix);
};



//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
 var n = suffix.length;
 return (this.length >= n) && (this.right(n) == suffix);
};


//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
 return this.indexOf(substring) >= 0;
};

//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or 
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
 for (var i = 0; i < this.length; i++) {
 if (this[i] == item) {
 return i;
 }
 }
 return -1;
};

//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false. 
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
 return (this.indexOf(item) >= 0);
};

//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements 
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
 for(var i = 0; i < items.length; i++) {
 if (this.contains(items[i])) {
 return true;
 }
 }
 return false;
};


//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
// 
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null] 
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
 for(var i = 0; i < items.length; i++) {
 if (!this.contains(items[i])) {
 return false;
 }
 }
 return true;
};


} // of "install only once"

// Used Globals (for JSLint) ==============
// ... DOM
/*global document */
// ... TiddlyWiki Core
/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink, 
 displayMessage, endSaveArea, hasClass, loadFile, saveFile, 
 startSaveArea, store, wikify */
//}}}


/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])

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 abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/

/***
|''Name:''|GenerateRssByTagPlugin|
|''Description:''|Only tiddlers with a specific tag are inluded in the RSSFeed. If no tiddlers are selected then works as before. (see ticket #270: http://trac.tiddlywiki.org/tiddlywiki/ticket/270). <br>RssTag: <<option txtRssTag>>|
|''Version:''|1.0.2|
|''Date:''|Apr 20, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#GenerateRssByTagPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.GenerateRssByTagPlugin = {
	major: 1, minor: 0, revision: 2, 
	date: new Date("Apr 20, 2007"),
	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0 (Beta 5)'
};

if (!window.bidix) window.bidix = {}; // bidix namespace

bidix.generateRssByTag = function()
{
	var s = [];
	var d = new Date();
	var u = store.getTiddlerText("SiteUrl");
	// Assemble the header
	s.push("<" + "?xml version=\"1.0\"" + " encoding='UTF-8' " + "?" + ">");
	s.push("<rss version=\"2.0\">");
	s.push("<channel>");
	s.push("<title" + ">" + wikifyPlain("SiteTitle").htmlEncode() + "</title" + ">");
	if(u)
		s.push("<link>" + u.htmlEncode() + "</link>");
	s.push("<description>" + wikifyPlain("SiteSubtitle").htmlEncode() + "</description>");
	s.push("<language>en-us</language>");
	s.push("<copyright>Copyright " + d.getFullYear() + " " + config.options.txtUserName.htmlEncode() + "</copyright>");
	s.push("<pubDate>" + d.toGMTString() + "</pubDate>");
	s.push("<lastBuildDate>" + d.toGMTString() + "</lastBuildDate>");
	s.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
	s.push("<generator>TiddlyWiki " + version.major + "." + version.minor + "." + version.revision + "</generator>");
	// The body
	var tiddlers;
	if (config.options.txtRssTag && store.getTaggedTiddlers(config.options.txtRssTag).length > 0)
		tiddlers = store.getTaggedTiddlers(config.options.txtRssTag,"modified");
	else
		tiddlers = store.getTiddlers("modified","[[excludeLists]]");
	var n = config.numRssItems > tiddlers.length ? 0 : tiddlers.length-config.numRssItems;
	for (var t=tiddlers.length-1; t>=n; t--)
		s.push(tiddlers[t].saveToRss(u));
	// And footer
	s.push("</channel>");
	s.push("</rss>");
	// Save it all
	return s.join("\n");
};

//
// Initializations
//
bidix.generateRss = generateRss; // backup core version
generateRss = bidix.generateRssByTag; // install new one
config.options.txtRssTag = "toRSS"; // default RssTag. use <<option txtRssTag>> to overwritte
merge(config.optionsDesc,{txtRssTag: "Only tiddlers with this tag will be included in the RSS Feed."});
//}}}
[img[http://tiddlyhome.bidix.info/_th/images/TiddlyHomeLogo.32.jpg][http://tiddlyhome.bidix.info/]] TiddlyHome is a package design as an infrastructure for multi-user and multi-site TiddlyWiki hosting service based on UploadPlugin. 

TiddlyHome <<tiddler TiddlyHomeVersion>> is in beta stage and use TiddlyWiki <<version>>.

!!How does it works ?
To use TiddlyHome it is really easy. All is done from this page.
#''First Register'' If you had not already done, register yourself as a [[New user]]. <<tag [[User]]>> commands let you to view,  change or delete your personal informations.
#''Next Create a site''. Each site has an ''owner'' and is ''private'' or ''public''. A ''group'' of user can also be specified to edit a site (and access it if it is private). Ready to create a [[New site]] ?  <<tag [[Site]]>> command can be used to manage access to your site.
#''Enjoy'' your new Web Hosted ~TiddlyWiki at http://TiddlyHome.bidix.info/YourSite/
!!Try it
Not sure how it works ? Try it here*. http://TiddlyHome.bidix.info/ is a SandBox setup. 

(*) I reserve the right to stop this service at any time or delete sites or users if my TiddlyHome service exceeds my hosting limits.
!!Setup your own ~TiddlyHome
*see [[Requirements]]
*[[Download and install package]]
*[[Initialize your own TiddlyHome]]
!![[Stay tuned]]
<<tiddler [[Stay tuned]]>>
!!How to navigate
*TopMenu
**GettingStarted : Entry point
**<<tag User>> : User Command Menu
**<<tag Site>> : Site Command Menu
**<<tag Docs>> : Documentaton on TiddlyHome
**<<tag Dev>> : Development status 
**<<tag About>> : Informations about TiddlyHome
*MainMenu
**<<search>> : Incremental search in articles
**[[home|GettingStarted]] : Entry point
**[[Index|News]] : News list
**[[Latest news]] : Extract of the latest news 
**[[Help]] : This article.
**<<changeMode Author>> : Switch between ''Reader Mode'' and ''Author Mode''.
!!Stay tuned
<<tiddler [[Stay tuned]]>>
/***
| Name|HideWhenPlugin|
| Description|Allows conditional inclusion/exclusion in templates|
| Version|3.0 ($Rev: 1845 $)|
| Date|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|
| Source|http://mptw.tiddlyspot.com/#HideWhenPlugin|
| Author|Simon Baird <simon.baird@gmail.com>|
| [[License]]|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{

window.removeElementWhen = function(test,place) {
	if (test) {
		removeChildren(place);
		place.parentNode.removeChild(place);
	}
};

merge(config.macros,{

	hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( eval(paramString), place);
	}},

	showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !eval(paramString), place);
	}},

	hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAll(params), place);
	}},

	showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAll(params), place);
	}},

	hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAny(params), place);
	}},

	showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAny(params), place);
	}},

	hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAll(params), place);
	}},

	showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAll(params), place);
	}},

	hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
	}},

	showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
	}}

});

//}}}

<<forEachTiddler
 where
 'tiddler.tags.contains("Changes") /*&& tiddler.tags.contains("toRSS")*/' 
 sortBy
 'store.getValue(tiddler,"created")'
 descending
 write
 '"\n!![["+tiddler.title+"]] \n" +
 tiddler.text;'
>>
//If you are not at your own TiddlyHome go immediately to it.//

If you are at your own TiddlyHome go to your new own ~TiddlyHome [[admin/|_th/admin/]] site.
 
/***
|''Name:''|IsDirtyPlugin|
|''Description:''|When the TiddlyWiki needs to be saved the tiddler named IsDirty contains ' * ' else it is empty. IsDirty tiddler is also appended in front of the browser page title.<br>Hint: Put it in front of your SiteTitle in your PageTemplate or in your MainMenu as an indicator.<br>For now IsDirty: <<tiddler IsDirty>>|
|''Version:''|1.0.1|
|''Date:''|Mar 20, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#IsDirtyPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.IsDirtyPlugin = {
	major: 1, minor: 0, revision: 1, 
	date: new Date("Mar 20, 2007"),
	source: 'http://tiddlywiki.bidix.info/#IsDirtyPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.setDirty = TiddlyWiki.prototype.setDirty;
bidix.initIsDirty = function()
{
	var tags = "[[excludeLists]] [[excludeSearch]]";
	var tiddler = store.getTiddler("IsDirty");
	if (!tiddler) {
		tiddler = new Tiddler("IsDirty");
		//tiddler.set(title,text,modifier,modified,tags,created,fields)
		tiddler.set(null,null,null,null,tags,null,null);
		store.addTiddler(tiddler);
	}
	tiddler.set(null,"",null,null,null,null,null);
	return tiddler;
};

TiddlyWiki.prototype.setDirty = function(dirty)
{
	var indic = " * ";
	var oldDirty = this.isDirty ();
	bidix.setDirty.apply(this,arguments);
	var tiddler = bidix.initIsDirty();
	if (dirty)
		tiddler.set(null,indic,null,null,null,null,null);
	else
		tiddler.set(null," ",null,null,null,null,null);
	story.refreshTiddler(tiddler.title);
	store.notify(tiddler.title, true);	
	refreshPageTitle();
};

bidix.refreshPageTitle = function()
{
	document.title = wikifyPlain("IsDirty") + wikifyPlain("SiteTitle") + " - " + wikifyPlain("SiteSubtitle");
};

bidix.core.refreshPageTitle = refreshPageTitle ;
refreshPageTitle  = bidix.refreshPageTitle;
bidix.initIsDirty();
//}}}
<<forEachTiddler
 where
 'tiddler.tags.contains("toRSS") /*&& tiddler.tags.contains("toRSS")*/' 
 sortBy
 'store.getValue(tiddler,"created")'
 descending
 write
 '"\n@@font-size:1.5em;[["+tiddler.title+"]]@@@@color:#999; - " + Date.convertFromYYYYMMDDHHMM(store.getValue(tiddler,"created")).formatString("YYYY/0MM/0DD")+" - "+tiddler.modifier+"@@\n" +
 "{{excerpt{\n" + 
 (tiddler.text.match("/%%/") ?
 tiddler.text.substr(0,tiddler.text.indexOf("/%%/")) : 
 tiddler.text.substr(0,300)) + 
 " ...\n[[more ...|"+tiddler.title+"]]\n----\n}}}";'
>>
<<tiddler BSDOpenSourceLicense>>
//{{{
//thanks Simon!
Array.prototype.tiddlerList = function(listFormat,max) {
	var output = "";
	if (!listFormat) listFormat = "'[[' + tiddler.title + ']] - ' + tiddler.created.formatString('0DD/0MM/YY') + ' - ' + tiddler.modifier + '\\n'";
        if (!max) var max = this.length;
	if (this.length > 0 && this[0] instanceof Tiddler) {
		for (var i=0;i<max;i++) {
			var tiddler = this[i];
			output += eval(listFormat);
		}
	}
	return output;
}

// tag, sorted, listformat, max(0), noReverse(true)
config.macros.listByTag = {};
config.macros.listByTag.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
    	params[0]  = (params[0] ? params[0] : tiddler.title);
    	var tiddlers = store.getTaggedTiddlers(params[0],params[1]);
    	if (params[3] == 0) params[3] = null;
    	if (! params[4])
    	    	tiddlers = tiddlers.reverse();
 	wikify(tiddlers.tiddlerList(params[2],params[3]),place,null,tiddler);
};
//}}}
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 }
 return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
[[home|GettingStarted]]
[[Index|News]]
[[Latest news]]
----
<<changeMode Reader>>
<<tiddler IsDirty>><<changeMode Author>>
----
<<tiddler [[About site]]>>
<style type="text/css">#bidix_copyright {display:none;}</style>
<div id="bidix_copyright">
Welcome to TiddlyHome. 
TiddlyHome is a <a href="http://www.tiddlywiki.com">TiddlyWiki</a> written by <a href="http://bidix.info">BidiX</a> and hosted at <a href="http://tiddlyhome.bidix.info"/>TiddlyHome.bidix.info</a>.
Copyright &copy; 2007 BidiX  (http://BidiX.info)
</div>
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<link rel="shortcut icon" href="http://TiddlyHome.bidix.info/_th/images/favicon.ico" type="image/vnd.microsoft.icon" />
<link rel="icon" href="http://TiddlyHome.bidix.info/_th/images/favicon.ico" type="image/vnd.microsoft.icon" /> 
<!--}}}-->
This new release of TiddlyHome is a bug fix only release. It is the [[Ticket 5|Tickets]] correction.

Read [[Password Management in TiddlyHome on Windows]] for un important security notice on Windows.

Get the full package [[here|TiddlyHomePackage_0.0.2.zip]]
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/site.php?next=new" width=100% height=200px>
</iframe>
</html>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/user.php?next=new" width=100% height=200px>
</iframe>
</html>

!Description
A vertical TiddlyWiki for publishing.
!Features
Version 1.2.0
*mode management
**<<changeMode Reader>>: browse and navigate into the content in readOnly mode and SinglePageMode .  
**<<changeMode Author>>: for managing content (tiddlers, tags and perhaps Menus) and publishing (Save to web) the TiddlyWiki.
**<<changeMode>>: is the default mode when start:safe or plugin errors. This mode has the basic TiddlyWiki presentation and behaviour.
*SinglePageMode and ReadOnly for Reader
*StyleSheet reader oriented
*All [[admin]] stuff masked to reader and author
*Tweaks to ease navigation :
**an admin tag for all admin stuff
**Triangle added to tag button to indicate popup
**new lists ('timeline' 'all' 'tags') without tiddlers or tags tagged 'admin'
**[[systemList]]
**[[systemTool]]
**Latest [[News]]
*AutoWeave in Author mode
*Localizable
**See NewsWikiFR
!Components
all tagged NewsWiki :
*ChangeModePlugin
*SinglePageModePlugin
*NewsWikiTweaks
*IsDirtyPlugin
*SinglePageModePlugin
*CalendarPlugin
*AutoWeavePluginPatched
*''[[admin]] tag'' : has the special meanning to hide to Reader and Author 
*''[[systemList]]'' : List all tiddlers tagged with it
*''[[systemTool]]'' : in tiddler view, hide subtitle (modifier, created, modified) 
*''<mode><tiddler>'' (like AuthorStyleSheet, ReaderStyleSheet, StyleSheet ...)
!Sources
*Sample : 
**http://TiddlyHome.bidix.info/
**http://TiddlyHomeFR.bidix.info/
*Empty : 
**http://TiddlyHome.bidix.info/systemServer/NewsWiki
**http://TiddlyHome.bidix.info/systemServer/NewsWikiFR
!toDo
*--[[toRelease]]--
*--French version--
*--In French Version, [[locale.fr-FR]] is loaded after NewsWikiTweaks. NewsWikiTweaksFR should require local.fr-FR--
!History
!![[2007/06/05]]
*Version 1.0.0
!!2007/07/28
*Version 1.2.0
|URL:|http://tiddlyhome.bidix.info/systemServer/NewsWiki.html|
|Description|Repository for NewsWiki system ressources |
|Author:|BidiX|
/***
|''Name:''|NewsWikiTweaks|
|''Description:''|Some tweaks for NewsWiki|
|''Version:''|0.0.1|
|''Date:''|Jun 11, 2007|
|''Source:''|http://TiddlyWiki.bidix.info/#NewsWikiTweaks|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/

/***
!Options
***/
//{{{
//Options
config.options.chkAnimate = false;
config.options.txtRssTag = 'toRSS';
//}}}
/***
!tag
***/
//{{{
merge(config.views.wikified.tag,{
 labelNoTags: "",
 labelTags: ""});
/*
merge(config.macros.tagging,{
 label: "",
 labelNotTag: "",
 tooltip: ""});
*/


createTagButton = function(place,tag,excludeTiddler)
{
	var triangle = 	" "+glyph("downTriangle");
	var theTag = createTiddlyButton(place,tag+triangle,config.views.wikified.tag.tooltip.format([tag]),onClickTag);
	theTag.setAttribute("tag",tag);
	if(excludeTiddler)
		theTag.setAttribute("tiddler",excludeTiddler);
	return theTag;
}


onClickTag = function(e)
{
	if(!e) var e = window.event;
	var theTarget = resolveTarget(e);
	var popup = Popup.create(this);
	var tag = this.getAttribute("tag");
	var title = this.getAttribute("tiddler");
	if(popup && tag) {
		var tagged = store.getTaggedTiddlers(tag);
		var titles = [];
		var li,r;
		for(r=0;r<tagged.length;r++) {
			if(tagged[r].title != title)
				titles.push(tagged[r].title);
		}
		var lingo = config.views.wikified.tag;
		if(titles.length > 0) {
			// var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
			// openAll.setAttribute("tag",tag);
			// createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
			for(r=0; r<titles.length; r++) {
				createTiddlyLink(createTiddlyElement(popup,"li"),titles[r],true);
			}
		} else {
			createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),lingo.popupNone.format([tag]));
		}
		createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
		if (!config.options.chkSinglePageMode) {
			var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
			openAll.setAttribute("tag",tag);
		}
		// createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
		var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);
		createTiddlyText(h,lingo.openTag.format([tag]));
	}
	Popup.show();
	e.cancelBubble = true;
	if(e.stopPropagation) e.stopPropagation();
	return false;
}


config.macros.tagChooser.onClick = function(e)
{
	if(!e) var e = window.event;
	var lingo = config.views.editor.tagChooser;
	var popup = Popup.create(this);
	var tags = store.getTags("[[admin]]");
	if(tags.length == 0)
		createTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone);
	for(var t=0; t<tags.length; t++) {
		var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),config.macros.tagChooser.onTagClick);
		theTag.setAttribute("tag",tags[t][0]);
		theTag.setAttribute("tiddler",this.getAttribute("tiddler"));
	}
	Popup.show();
	e.cancelBubble = true;
	if(e.stopPropagation) e.stopPropagation();
	return false;
};



//}}}
/***
!tabs
***/
//{{{
config.macros.list.user= {};
config.macros.list.user.handler = function(params)
{
	return store.reverseLookup("tags","admin",false,"title");
};

config.macros.userTimeline = {};
config.macros.userTimeline.handler = function(place,macroName,params)
{
	var field = params[0] ? params[0] : "modified";
	var tiddlers = store.reverseLookup("tags","admin",false,field);
	var lastDay = "";
	var last = params[1] ? tiddlers.length-Math.min(tiddlers.length,parseInt(params[1])) : 0;
	for(var t=tiddlers.length-1; t>=last; t--) {
		var tiddler = tiddlers[t];
		var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);
		if(theDay != lastDay) {
			var theDateList = document.createElement("ul");
			place.appendChild(theDateList);
			createTiddlyElement(theDateList,"li",null,"listTitle",tiddler[field].formatString(config.macros.timeline.dateFormat));
			lastDay = theDay;
		}
		var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink");
		theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true));
	}
};

//}}}
/***
!Shadow tiddlers
***/
//{{{
config.shadowTiddlers.GettingStarted = 
	"To get started with this blank NewsWiki, you'll need to change mode to <<changeMode Author>> or <<changeMode>>\n\n" +
	config.shadowTiddlers.GettingStarted;
//}}}

/***
!others
***/
//{{{
config.macros.version.handler = function(place)
{
	createTiddlyElement(place,"span",null,null,version.major + "." + version.minor + "." + version.revision + (version.beta ? " (beta " + version.beta + ")" : "") + (version.build ? " (build #" + version.build + ")" : ""));
};


//}}}
[img[http://tiddlyhome.bidix.info/_th/images/TiddlyHomeLogo.32.jpg][http://tiddlyhome.bidix.info/]] TiddlyHome is hosting PDCI's temporary web site.

[img[http://tiddlyhome.bidix.info/_th/images/PDCI.jpeg][http://tiddlyhome.bidix.info/PDCI]]

[[Partners for Democratic Change International (PDCI)|http://tiddlyhome.bidix.info/PDCI/]] is a global partnership of fifteen independent, local organizations in Europe, the Americas and the Middle East that work to advance civil society, good governance and a culture of change and conflict management worldwide.

TiddlyHome doesn't manage properly password on windows as it does on Linux and OSX.

!!Password management in TiddlyHome
To manage password, TiddlyHome uses the PHP crypt() function to :
*encode password when it is first provided
*verify password for the different operations on sites
Password is then stored in a .htpasswd file that is compatible with Apache format

!!Password management in Apache
To manage password, Apache uses the system crypt() function to encode and verify password except on Windows.

On Windows Apache uses a proprietary MD5 modified algorithm to encode and verify password.

Even if TiddlyHome will use the htpasswd.exe command provided with Apache on Windows, TiddlyHome will be unable to verify password for the different operations on sites.

!!If you can, don't use TiddlyHome on Windows
It's my recommendation : @@Don't use Apache and TiddlyHome on Windows@@, for safety reason you should prefer Linux or OSX.

!!No encrypted password on Windows and only on Windows
If you still want to use TiddlyHome on Windows, for maintaining the compatibility between TiddlyHome and Apache, password are not encrypted (they are in plain text).

But it is only on Windows. On other operating system they are encrypted with the standard crypt() system function.

/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
	major: 1, minor: 0, revision: 2, 
	date: new Date("Apr 19, 2007"),
	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
	coreVersion: '2.2.0 (Beta 5)'
};

config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");

merge(config.macros.option.types, {
	'pas': {
		elementType: "input",
		valueField: "value",
		eventName: "onkeyup",
		className: "pasOptionInput",
		typeValue: config.macros.option.passwordInputType,
		create: function(place,type,opt,className,desc) {
			// password field
			config.macros.option.genericCreate(place,'pas',opt,className,desc);
			// checkbox linked with this password "save this password on this computer"
			config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);			
			// text savePasswordCheckboxLabel
			place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
		},
		onChange: config.macros.option.genericOnChange
	}
});

merge(config.optionHandlers['chk'], {
	get: function(name) {
		// is there an option linked with this chk ?
		var opt = name.substr(3);
		if (config.options[opt]) 
			saveOptionCookie(opt);
		return config.options[name] ? "true" : "false";
	}
});

merge(config.optionHandlers, {
	'pas': {
 		get: function(name) {
			if (config.options["chk"+name]) {
				return encodeCookie(config.options[name].toString());
			} else {
				return "";
			}
		},
		set: function(name,value) {config.options[name] = decodeCookie(value);}
	}
});

// need to reload options to load passwordOptions
loadOptionsCookie();

/*
if (!config.options['pasPassword'])
	config.options['pasPassword'] = '';

merge(config.optionsDesc,{
		pasPassword: "Test password"
	});
*/
//}}}
Background: #fff
Foreground: #333
PrimaryPale: #FFBFBF
PrimaryLight: #BF2323
PrimaryMid: #BF2323
PrimaryDark: #660000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #ff0000
<<viewPalette>>
<<search>>
[[home|GettingStarted]]
[[Index|News]]
[[Latest news]]
----
[[Help]]
<html><a href=download.php class='button'>download</a></html>
<<tiddler IsDirty>><<changeMode Author>>
----
<<tiddler [[About site]]>>
<!--{{{-->
<div id='page'>
	<div id='header' class='header'>
 		<div id='topMenu' refresh='content' tiddler='TopMenu'></div> 
 		<div id='title'>
 			<div class='siteTitle' refresh='content' tiddler='SiteTitle'></div>
 			<div class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></div>
 		</div>
	</div>
	<div id='sidebar'>
		<div id='sidebarOptions' refresh='content' tiddler='ReaderMainMenu'></div>
	</div>
	<div id='displayArea'>
		<div id='messageArea'></div>
		<div id='tiddlerDisplay'></div>
	</div>
</div>
<!--}}}-->
[[CommunStyleSheet]]
/***
!!page
***/
/*{{{*/
#page { 
	border-left: 1px solid [[ColorPalette::TertiaryLight]]; 
	padding: 0 30px 0 30px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 0px;
	width: 65em;
	position: relative;
	text-align: left;
	background-color: [[ColorPalette::Background]];
	color: [[ColorPalette::Foreground]];
 
}

/*}}}*/

<!--{{{-->
<div class='title'>
	<span class='title' macro='view title'></span>
	<!--<span macro="miniTag">--></span>
</div>

</div>
<div macro="hideWhenTaggedAny systemTool systemList">
	<span class = "subtitle"><span macro='view created date [[0DD/0MM/YYYY]]'></span> - <span macro='view modifier'></span></span>
	<div class='tagged' macro='tags'></div>
	<div class='tagClear'></div>
</div>
<div class='viewer' macro='view text wikified'></div>
<div macro="showWhenTagged systemList">
	<div class='viewer' macro="listByTag '' created  ''"></div>
</div>
<!--}}}-->
Certainly not really restrictive.

ServerSide  :
*[[Apache|http://httpd.apache.com]] web server
*[[PHP|http://www.php.net]]

ClientSide :
*TiddlyWiki
*UploadPlugin
/***
|Name|SinglePageModePlugin|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Version|2.2.3|
|Author|Eric Shulman - ELS Design Studios|
|[[License]]|http://www.TiddlyTools.com/#LegalStatements <<br>>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler(), Story.prototype.displayTiddlers()|
|Description|Display tiddlers one at a time with automatic update of URL (permalink).  Also, option to always open tiddlers at top of page|

Normally, as you click on the links in TiddlyWiki, more and more tiddlers are displayed on the page. The order of this tiddler display depends upon when and where you have clicked. Some people like this non-linear method of reading the document, while others have reported that when many tiddlers have been opened, it can get somewhat confusing.

!!!!!Usage
<<<
SinglePageMode allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one item displayed at a time.  When SinglePageMode is enabled, the title of the current tiddler is automatically displayed in the browser window's titlebar and the browser's location URL is updated with a 'permalink' for the current tiddler so that it is easier to create a browser 'bookmark' for the current tiddler.

Even when SinglePageMode is disabled (i.e., displaying multiple tiddlers is permitted), you can reduce the potential for confusion by enable TopOfPageMode, which forces tiddlers to always open at the top of the page instead of being displayed following the tiddler containing the link that was clicked.
<<<
!!!!!Configuration
<<<
When installed, this plugin automatically adds checkboxes in the AdvancedOptions tiddler so you can enable/disable the plugin behavior.  For convenience, these checkboxes are also included here:

<<option chkSinglePageMode>> Display one tiddler at a time
<<option chkTopOfPageMode>> Always open tiddlers at the top of the page
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''SinglePageModePlugin'' (tagged with <<tag [[systemConfig]]>>)
^^documentation and javascript for SinglePageMode handling^^

When installed, this plugin automatically adds checkboxes in the ''shadow'' AdvancedOptions tiddler so you can enable/disable this behavior.  However, if you have customized your AdvancedOptions, you will need to ''manually add these checkboxes to your customized tiddler.''
<<<
!!!!!Revision History
<<<
''2007.02.06 [2.2.3]'' in Story.prototype.displayTiddler(), use convertUnicodeToUTF8() for correct I18N string handling when creating URL hash string from tiddler title (based on bug report from BidiX)
''2007.01.08 [2.2.2]'' use apply() to invoke hijacked core functions
''2006.07.04 [2.2.1]'' in hijack for displayTiddlers(), suspend TPM as well as SPM so that DefaultTiddlers displays in the correct order.
''2006.06.01 [2.2.0]'' added chkTopOfPageMode (TPM) handling
''2006.02.04 [2.1.1]'' moved global variable declarations to config.* to avoid FireFox 1.5.0.1 crash bug when assigning to globals
''2005.12.27 [2.1.0]'' hijack displayTiddlers() so that SPM can be suspended during startup while displaying the DefaultTiddlers (or #hash list).  Also, corrected initialization for undefined SPM flag to "false", so default behavior is to display multiple tiddlers
''2005.12.27 [2.0.0]'' Update for TW2.0
''2005.11.24 [1.1.2]'' When the back and forward buttons are used, the page now changes to match the URL.  Based on code added by Clint Checketts
''2005.10.14 [1.1.1]'' permalink creation now calls encodeTiddlyLink() to handle tiddler titles with spaces in them
''2005.10.14 [1.1.0]'' added automatic setting of window title and location bar ('auto-permalink').  feature suggestion by David Dickens.
''2005.10.09 [1.0.1]'' combined documentation and code in a single tiddler
''2005.08.15 [1.0.0]'' Initial Release
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].
Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts
<<<
!!!!!Code
***/
//{{{
version.extensions.SinglePageMode= {major: 2, minor: 2, revision: 3, date: new Date(2007,2,6)};

if (config.options.chkSinglePageMode==undefined) config.options.chkSinglePageMode=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSinglePageMode>> Display one tiddler at a time";

if (config.options.chkTopOfPageMode==undefined) config.options.chkTopOfPageMode=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkTopOfPageMode>> Always open tiddlers at the top of the page";

config.SPMTimer = 0;
config.lastURL = window.location.hash;
function checkLastURL()
{
	if (!config.options.chkSinglePageMode)
		{ window.clearInterval(config.SPMTimer); config.SPMTimer=0; return; }
	if (config.lastURL == window.location.hash)
		return;
	// var tiddlerName = convertUTF8ToUnicode(decodeURI(window.location.hash.substr(1)));
	var tiddlerName = decodeURI(window.location.hash.substr(1));
	tiddlerName=tiddlerName.replace(/\[\[/,"").replace(/\]\]/,""); // strip any [[ ]] bracketing
	if (tiddlerName.length) story.displayTiddler(null,tiddlerName,1,null,null);
}

if (Story.prototype.SPM_coreDisplayTiddler==undefined) Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
{
	if (config.options.chkSinglePageMode) {
		// window.location.hash = encodeURIComponent(convertUnicodeToUTF8(String.encodeTiddlyLink(title)));
		window.location.hash = encodeURIComponent(String.encodeTiddlyLink(title));
		config.lastURL = window.location.hash;
		document.title = wikifyPlain("IsDirty") + wikifyPlain("SiteTitle") + " - " + title;
		story.closeAllTiddlers();
		if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
	}
	if (config.options.chkTopOfPageMode) { story.closeTiddler(title); window.scrollTo(0,0); srcElement=null; }
	this.SPM_coreDisplayTiddler.apply(this,arguments);
}

if (Story.prototype.SPM_coreDisplayTiddlers==undefined) Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;
Story.prototype.displayTiddlers = function(srcElement,titles,template,unused1,unused2,animate,slowly)
{
	// suspend single-page mode when displaying multiple tiddlers
	var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
	var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
	this.SPM_coreDisplayTiddlers.apply(this,arguments);
	config.options.chkSinglePageMode=saveSPM; config.options.chkTopOfPageMode=saveTPM;
}
//}}}
Available Site commands:
Multi-site & multi-user hosting service package for ~TiddlyWiki 
[img[http://TiddlyHome.bidix.info/_th/images/TiddlyHomeLogo.64.jpg]]&nbsp;&nbsp;&nbsp;~TiddlyHome
http://tiddlyhome.bidix.info/
!!TiddlyHome Project
Home: http://code.google.com/p/bidix/
Source: http://bidix.googlecode.com/svn/
*RSS Feed [img[http://www.mozilla.org/images/feed-icon-14x14.png][http://tiddlyhome.bidix.info/index.xml]] : http://tiddlyhome.bidix.info/index.xml
*[[News page|http://tiddlyhome.bidix.info/news.php]] : http://tiddlyhome.bidix.info/news.php
*Email BidiX for information
<<list user>>
//You should define your own [[Terms of Service]]//
#--Change ''Group'' with ''Author Team'' everywhere in Site attribute label--
#--Always add Site ''Owner'' to ''Author Team''--
#--Bug in Sidebar in ''Author Mode'' : some lines don't display. For now, work around : reselect ''Author Mode''--
#--tag ColorPalette with <<tag admin>> in ChangeModePlugin--
#--TiddlyHome isn't working on Windows. See [[Password Management in TiddlyHome on Windows]]--
[img[http://tiddlyhome.bidix.info/_th/images/TiddlyHomeLogo.32.jpg][http://tiddlyhome.bidix.info/]] TiddlyHome is a package design as an infrastructure for multi-user and multi-site TiddlyWiki hosting service based on UploadPlugin. 

TiddlyHome <<tiddler TiddlyHomeVersion>> is in beta stage and use TiddlyWiki <<version>>.

The main fetaures are :
*[[BSD open source license|BSDOpenSourceLicense]]
*written in [[PHP]], no database
*Based on [[UploadPlugin|http://tiddlywiki.bidix.info/#UploadPluginDoc]]
*All [[User]] management in [[.htpasswd]]
*All control access in [[.htaccess]]
*All admin tasks from a dedicated TiddlyWiki
*User Options and [[Site]] Options accessible from TiddlyWiki
* and much more ...
The next step will be :
*GroupAuthoring support

All comments, feedback and enquiries to [[TiddlyHome @ bidix.info|mailto:tiddlyhome@bidix.info]]

Enjoy,

-- BidiX
This new release of TiddlyHome includes some enhancements :
*TiddlyWiki core is externalise in _th/lib/twcore.js
*download.php and store.php maintain the single file paradigm when the tiddlywiki is "detached'" from is TiddlyHome
*proxy.php is full functional allowing importTiddlers to work in the same domain or by using an allowedsites.txt. Usefull to upgrade when online.
This new release of TiddlyHome includes only the new TiddlyWiki 2.2.5 core.

Get it at http://TiddlyHome.bidix.info/TiddlyHomePackage_0.1.1.zip
Changes :
*_th/lib/twcore.js : TiddlyWiki 2.3.0 core<br>From now all TiddlyHome hosted TiddlyWikis use this new release.
*MarkupPreBody : Content display in the //info:// google request like in http://www.google.com/search?q=info:tiddlywiki.bidix.info
[[Get it |TiddlyHomePackage_0.1.2.zip]]
It is only an Update release.
Changes :
*New site uses templates in SingleFileMode. No more core extracted.
* All templates uses :
** Core 2.4.1
** UploadTiddlerPlugin V 1.2.1
** UploadPlugin V 4.1.4
** _th/lib/storeTiddler.php 
A TiddlyWiki is prepared for TiddlyHome with TiddlyHomeSetupPlugin.

This plugin ensures that you have UploadToHomeMacro  and UploadPlugin loaded and sets up the TiddlyHomeParameters and HomeParameters ShadowTiddlers. When you create your TiddlyHome site, these ShadowTiddlers are automatically filled with the TiddlyHome URL, the site and the username.

If you want to change parameters edit those ShadowTiddlers.

If you want to set up your own TiddlyWiki for TiddlyHome :
#import UploadToHomeMacro, UploadPlugin and TiddlyHomeSetupPlugin from TiddlyHome
#edit TiddlyHomeSetupPlugin and give your accurate parameters
Tags all ressources usefull for a TiddlyHome site.

TiddlyHome provides also ShadowedTiddlers that can be overwritten :
* TiddlyHomeParameters
* TiddlyHomeSidebar
|URL:|$rootUrl$_th/templates/ressources.html|
|Description| Repository for TiddlyHome ressources|
|Author:|BidiX|
/***
|''Name:''|TiddlyHomeSetupPlugin|
|''Description:''|Check and setup all components|
|''Version:''|1.1.0|
|''Date:''|Aug 04, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#TiddlyHomeSetupPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|UploadToHomeMacro|
***/
//{{{

version.extensions.TiddlyHomeSetupPlugin = {
	major: 1, minor: 1, revision: 0,
	date: new Date("Aug 04, 2007"),
	source: 'http://tiddlywiki.bidix.info/#TiddlyHomeSetupPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info)',
	coreVersion: '2.2.0'
};

if (!window.bidix) window.bidix = {}; // bidix namespace

bidix.checkPlugin = function(plugin, major, minor, revision) {
	var ext = version.extensions[plugin];
	if (!
		(ext  && 
			((ext.major > major) || 
			((ext.major == major) && (ext.minor > minor))  ||
			((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
			// write error in PluginManager
			if (pluginInfo)
				pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
			eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
	}
};

bidix.getParamsFromTiddler = function(tiddlerTitle, sliceNames) {
	tiddlerTitle = (tiddlerTitle ? tiddlerTitle:this.messages.homeParamsTiddler);
	if (!store.tiddlerExists(tiddlerTitle) && !store.isShadowTiddler(tiddlerTitle)) {
		throw(config.macros.uploadToHome.messages.tiddlerNotFound.toString().format([tiddlerTitle]));
	}
	return sliceValues = store.getTiddlerSlices(tiddlerTitle,sliceNames);
};


bidix.initOption = function(name,value) {
	if (!config.options[name])
		config.options[name] = value;
};

bidix.checkPlugin('UploadPlugin',4,1,0);
config.macros.upload.authenticateUser = false; // authentication check by .htaccess

// default TiddlyHomeParameters in shadows
// user can overide this
merge(config.shadowTiddlers,{
	'TiddlyHomeParameters':[
	"|owner:|BidiX|",
	"|site:|TiddlyHome|",
	"|url:|http://TiddlyHome.bidix.info/|",
	"|rootUrl:|http://TiddlyHome.bidix.info/|"
	].join("\n")});
// get config from TiddlyHomeParameters
config.tiddlyHome = {};
merge(config.tiddlyHome, bidix.getParamsFromTiddler('TiddlyHomeParameters',['user','site','url','rootUrl']));
config.shadowTiddlers.TiddlyHomeParameters += [
	"\n!Usefull url for your site",
	"* " + config.tiddlyHome.url + "backup: List of backup files",
	"* " + config.tiddlyHome.url + "download.php : to download thisTiddlyWiki",
	"* " + config.tiddlyHome.url + "index.xml : your RSSFeed",
	"* " + config.tiddlyHome.url + "news.php : to display your RSSFeed",
	"!Access and change data",
	"* " + config.tiddlyHome.rootUrl + "Site : Site properties",
	"* " + config.tiddlyHome.rootUrl + "#User : User properties",
	"!More Information on TiddlyHome",
	"* " + config.tiddlyHome.rootUrl + " for your hosting service",
	"*http://TiddlyHome.bidix.info/ for BidiX's TiddlyHome Package"
	].join("\n");

// add TiddlyHomeSidebar in SideBarOptions
config.shadowTiddlers.SideBarOptions = config.shadowTiddlers.SideBarOptions.replace(/(<<saveChanges>>)/,
	"$1<<tiddler TiddlyHomeSidebar>>");

merge(config.shadowTiddlers,{
	// link to favicon.ico
	'MarkupPreHead':	[
		"<!--{{{-->",
		"<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>",
		"<link rel=\"shortcut icon\"href=\"" + 
			config.tiddlyHome.rootUrl + 
			"_th/images/favicon.ico\" type=\"image/vnd.microsoft.icon\" />",
		"<link rel=\"icon\" href=\"" + 
			config.tiddlyHome.rootUrl + 
			"_th/images/favicon.ico\" type=\"image/vnd.microsoft.icon\" /> ",
		"<!--}}}-->"
	].join("\n"),
	'SiteProxy':	[
		"proxy.php?url="
	].join("\n"),
	'SiteUrl':	config.tiddlyHome.url,

	// tweaks to UploadToHomeMacro parameters
	'HomeParameters': [
"|UploadUserName:||",
"|UploadStoreUrl:|" + config.tiddlyHome.url + "store.php|",
"|UploadDir:|.|",
"|UploadFilename:|index.html|",
"|UploadBackupDir:|backup|"
	].join("\n"),
	'TiddlyHomeSidebar':[
 		"<<uploadToHome>><html><a href=" + 
			config.tiddlyHome.url + "download.php class='button'>download</a></html>"
			].join("\n")
});

// Options tweaks
//config.options.txtUserName = config.tiddlyHome.user;
config.options.pasUploadPassword = '';
config.options.txtBackupFolder = "backup";
config.options.chkSaveBackups = true;
config.options.chkAutoSave = false;
config.options.chkRegExpSearch = false;
config.options.chkCaseSensitiveSearch = false;
config.options.chkAnimate = false;
config.options.chkGenerateAnRssFeed = true;
config.options.chkSaveEmptyTemplate = false;


//}}}
|URL:|http://TiddlyHome.bidix.info/systemServer/TiddlyHomeSystem.html|
|Description|Repository for TiddlyHome system ressources |
|Author:|BidiX|
0.1.3
<<tiddler TiddlyWikiEN>>
~TiddlyWiki is a powerful [[wiki|http://en.wikipedia.org/wiki/Wiki]] in a single html file which possesses all the features needed to manage and to outline personal notes in an efficient way.

No facility is required. You only need to download an empty ~TiddlyWiki on your desktop to start to use it. It can be stored on USB stick. To send it  just attached it to mail. You can also upload it on web server to publish a whole site.

For details visit [[www.TiddlyWiki.com|http://www.tiddlywiki.com]].

^^Version: <<version>>^^
~TiddlyWiki est un puissant [[wiki|http://fr.wikipedia.org/wiki/Wiki]] dans un simple fichier html qui possède toutes les caractéristiques pour gérer et présenter des notes personnelles d'une manière efficace.

Il ne nécessite aucune installation. Il suffit de sauvegarder un ~TiddlyWiki vide sur son bureau-écran pour commencer à l'utiliser. Il peut être copier sur une clé USB. Pour l'envoyer il suffit de le mettre en pièce jointe d'un courriel. En le téléchargeant sur un site web vous publier un site complet.

Pour plus d'information visiter [[www.TiddlyWiki.com|http://www.tiddlywiki.com]].

^^Version: <<version>>^^
GettingStarted <<tag User>> <<tag Site>> <<tag Docs>> <<tag Dev>> <<tag About>>
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 07/06/2007 15:24:13 | BidiX | [[/|http://tiddlyhome.bidix.info/home/#NewsWiki]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 07/06/2007 15:58:43 | BidiX | [[index.20070607.155435.html|http://tiddlyhome.bidix.info/home/backup/index.20070607.155435.html#GettingStarted]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 08/06/2007 23:42:50 | BidiX | [[/|http://tiddlyhome.bidix.info/home/#%5B%5BUsefull%20URL%20for%20a%20site%5D%5D]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 10/06/2007 10:58:49 | BidiX | [[/|http://tiddlyhome.bidix.info/home/#GettingStarted]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 28/06/2007 11:46:18 | Bruno Dillet | [[/|http://tiddlyhome.bidix.info/home/#GettingStarted]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 23/07/2007 22:40:54 | BidiX | [[/|http://tiddlyhome.bidix.info/home/#%5B%5BPDCI%20temporary%20web%20site%5D%5D]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 24/07/2007 08:08:40 | BidiX | [[/|http://tiddlyhome.bidix.info/home/#%5B%5BTiddlyHome%20isn't%20working%20on%20Windows%5D%5D]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 24/07/2007 22:35:40 | BidiX | [[/|http://tiddlyhome.bidix.info/home/#Tickets]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup | ok |
| 24/07/2007 22:36:23 | BidiX | [[/|http://tiddlyhome.bidix.info/home/#%5B%5BPassword%20Management%20in%20TiddlyHome%20on%20Windows%5D%5D]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup |
| 26/07/2007 23:01:12 | BidiX | [[index.html|file:///Users/bruno/Sites/TiddlyHome/index.html#2007%2F06%2F05]] | [[store.php|http://tiddlyhome.bidix.info/home/store.php]] | . | [[index.html | http://tiddlyhome.bidix.info/home/index.html]] | backup | ok |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.4|
|''Date:''|2008-08-11|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 4,
	date: new Date("2008-08-11"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

//
// Environment
//

if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;	// true to activate both in Plugin and UploadService
	
//
// Upload Macro
//

config.macros.upload = {
// default values
	defaultBackupDir: '',	//no backup
	defaultStoreScript: "store.php",
	defaultToFilename: "index.html",
	defaultUploadDir: ".",
	authenticateUser: true	// UploadService Authenticate User
};
	
config.macros.upload.label = {
	promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
	promptParamMacro: "Save and Upload this TiddlyWiki in %0",
	saveLabel: "save to web", 
	saveToDisk: "save to disk",
	uploadLabel: "upload"	
};

config.macros.upload.messages = {
	noStoreUrl: "No store URL in parmeters or options",
	usernameOrPasswordMissing: "Username or password missing"
};

config.macros.upload.handler = function(place,macroName,params) {
	if (readOnly)
		return;
	var label;
	if (document.location.toString().substr(0,4) == "http") 
		label = this.label.saveLabel;
	else
		label = this.label.uploadLabel;
	var prompt;
	if (params[0]) {
		prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0], 
			(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
	} else {
		prompt = this.label.promptOption;
	}
	createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};

config.macros.upload.action = function(params)
{
		// for missing macro parameter set value from options
		if (!params) params = {};
		var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
		var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
		var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
		var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
		var username = params[4] ? params[4] : config.options.txtUploadUserName;
		var password = config.options.pasUploadPassword; // for security reason no password as macro parameter	
		// for still missing parameter set default value
		if ((!storeUrl) && (document.location.toString().substr(0,4) == "http")) 
			storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
		if (storeUrl.substr(0,4) != "http")
			storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
		if (!toFilename)
			toFilename = bidix.basename(window.location.toString());
		if (!toFilename)
			toFilename = config.macros.upload.defaultToFilename;
		if (!uploadDir)
			uploadDir = config.macros.upload.defaultUploadDir;
		if (!backupDir)
			backupDir = config.macros.upload.defaultBackupDir;
		// report error if still missing
		if (!storeUrl) {
			alert(config.macros.upload.messages.noStoreUrl);
			clearMessage();
			return false;
		}
		if (config.macros.upload.authenticateUser && (!username || !password)) {
			alert(config.macros.upload.messages.usernameOrPasswordMissing);
			clearMessage();
			return false;
		}
		bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password); 
		return false; 
};

config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir) 
{
	if (!storeUrl)
		return null;
		var dest = bidix.dirname(storeUrl);
		if (uploadDir && uploadDir != '.')
			dest = dest + '/' + uploadDir;
		dest = dest + '/' + toFilename;
	return dest;
};

//
// uploadOptions Macro
//

config.macros.uploadOptions = {
	handler: function(place,macroName,params) {
		var wizard = new Wizard();
		wizard.createWizard(place,this.wizardTitle);
		wizard.addStep(this.step1Title,this.step1Html);
		var markList = wizard.getElement("markList");
		var listWrapper = document.createElement("div");
		markList.parentNode.insertBefore(listWrapper,markList);
		wizard.setValue("listWrapper",listWrapper);
		this.refreshOptions(listWrapper,false);
		var uploadCaption;
		if (document.location.toString().substr(0,4) == "http") 
			uploadCaption = config.macros.upload.label.saveLabel;
		else
			uploadCaption = config.macros.upload.label.uploadLabel;
		
		wizard.setButtons([
				{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption, 
					onClick: config.macros.upload.action},
				{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
				
			]);
	},
	options: [
		"txtUploadUserName",
		"pasUploadPassword",
		"txtUploadStoreUrl",
		"txtUploadDir",
		"txtUploadFilename",
		"txtUploadBackupDir",
		"chkUploadLog",
		"txtUploadLogMaxLine"		
	],
	refreshOptions: function(listWrapper) {
		var opts = [];
		for(i=0; i<this.options.length; i++) {
			var opt = {};
			opts.push();
			opt.option = "";
			n = this.options[i];
			opt.name = n;
			opt.lowlight = !config.optionsDesc[n];
			opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
			opts.push(opt);
		}
		var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
		for(n=0; n<opts.length; n++) {
			var type = opts[n].name.substr(0,3);
			var h = config.macros.option.types[type];
			if (h && h.create) {
				h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
			}
		}
		
	},
	onCancel: function(e)
	{
		backstage.switchTab(null);
		return false;
	},
	
	wizardTitle: "Upload with options",
	step1Title: "These options are saved in cookies in your browser",
	step1Html: "<input type='hidden' name='markList'></input><br>",
	cancelButton: "Cancel",
	cancelButtonPrompt: "Cancel prompt",
	listViewTemplate: {
		columns: [
			{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
			{name: 'Option', field: 'option', title: "Option", type: 'String'},
			{name: 'Name', field: 'name', title: "Name", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'} 
			]}
};

//
// upload functions
//

if (!bidix.upload) bidix.upload = {};

if (!bidix.upload.messages) bidix.upload.messages = {
	//from saving
	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
	backupSaved: "Backup saved",
	backupFailed: "Failed to upload backup file",
	rssSaved: "RSS feed uploaded",
	rssFailed: "Failed to upload RSS feed file",
	emptySaved: "Empty template uploaded",
	emptyFailed: "Failed to upload empty template file",
	mainSaved: "Main TiddlyWiki file uploaded",
	mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
	//specific upload
	loadOriginalHttpPostError: "Can't get original file",
	aboutToSaveOnHttpPost: 'About to upload on %0 ...',
	storePhpNotFound: "The store script '%0' was not found."
};

bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
	var callback = function(status,uploadParams,original,url,xhr) {
		if (!status) {
			displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
			return;
		}
		if (bidix.debugMode) 
			alert(original.substr(0,500)+"\n...");
		// Locate the storeArea div's 
		var posDiv = locateStoreArea(original);
		if((posDiv[0] == -1) || (posDiv[1] == -1)) {
			alert(config.messages.invalidFileError.format([localPath]));
			return;
		}
		bidix.upload.uploadRss(uploadParams,original,posDiv);
	};
	
	if(onlyIfDirty && !store.isDirty())
		return;
	clearMessage();
	// save on localdisk ?
	if (document.location.toString().substr(0,4) == "file") {
		var path = document.location.toString();
		var localPath = getLocalPath(path);
		saveChanges();
	}
	// get original
	var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
	var originalPath = document.location.toString();
	// If url is a directory : add index.html
	if (originalPath.charAt(originalPath.length-1) == "/")
		originalPath = originalPath + "index.html";
	var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
	var log = new bidix.UploadLog();
	log.startUpload(storeUrl, dest, uploadDir,  backupDir);
	displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
	if (bidix.debugMode) 
		alert("about to execute Http - GET on "+originalPath);
	var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

bidix.upload.uploadRss = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		if(status) {
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
			bidix.upload.uploadMain(params[0],params[1],params[2]);
		} else {
			displayMessage(bidix.upload.messages.rssFailed);			
		}
	};
	// do uploadRss
	if(config.options.chkGenerateAnRssFeed) {
		var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
		var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
		var rssString = generateRss();
		// no UnicodeToUTF8 conversion needed when location is "file" !!!
		if (document.location.toString().substr(0,4) != "file")
			rssString = convertUnicodeToUTF8(rssString);	
		bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
	} else {
		bidix.upload.uploadMain(uploadParams,original,posDiv);
	}
};

bidix.upload.uploadMain = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		var log = new bidix.UploadLog();
		if(status) {
			// if backupDir specified
			if ((params[3]) && (responseText.indexOf("backupfile:") > -1))  {
				var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
				displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
			}
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
			store.setDirty(false);
			log.endUpload("ok");
		} else {
			alert(bidix.upload.messages.mainFailed);
			displayMessage(bidix.upload.messages.mainFailed);
			log.endUpload("failed");			
		}
	};
	// do uploadMain
	var revised = bidix.upload.updateOriginal(original,posDiv);
	bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};

bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
	var localCallback = function(status,params,responseText,url,xhr) {
		url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
		if (xhr.status == 404)
			alert(bidix.upload.messages.storePhpNotFound.format([url]));
		if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
			alert(responseText);
			if (responseText.indexOf("Debug mode") >= 0 )
				responseText = responseText.substring(responseText.indexOf("\n\n")+2);
		} else if (responseText.charAt(0) != '0') 
			alert(responseText);
		if (responseText.charAt(0) != '0')
			status = null;
		callback(status,params,responseText,url,xhr);
	};
	// do httpUpload
	var boundary = "---------------------------"+"AaB03x";	
	var uploadFormName = "UploadPlugin";
	// compose headers data
	var sheader = "";
	sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
	sheader += uploadFormName +"\"\r\n\r\n";
	sheader += "backupDir="+uploadParams[3] +
				";user=" + uploadParams[4] +
				";password=" + uploadParams[5] +
				";uploaddir=" + uploadParams[2];
	if (bidix.debugMode)
		sheader += ";debug=1";
	sheader += ";;\r\n"; 
	sheader += "\r\n" + "--" + boundary + "\r\n";
	sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
	sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
	sheader += "Content-Length: " + data.length + "\r\n\r\n";
	// compose trailer data
	var strailer = new String();
	strailer = "\r\n--" + boundary + "--\r\n";
	data = sheader + data + strailer;
	if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
	var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
	if (!posDiv)
		posDiv = locateStoreArea(original);
	if((posDiv[0] == -1) || (posDiv[1] == -1)) {
		alert(config.messages.invalidFileError.format([localPath]));
		return;
	}
	var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
				store.allTiddlersAsHtml() + "\n" +
				original.substr(posDiv[1]);
	var newSiteTitle = getPageTitle().htmlEncode();
	revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
	revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
	revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
	revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
	revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
	return revised;
};

//
// UploadLog
// 
// config.options.chkUploadLog :
//		false : no logging
//		true : logging
// config.options.txtUploadLogMaxLine :
//		-1 : no limit
//      0 :  no Log lines but UploadLog is still in place
//		n :  the last n lines are only kept
//		NaN : no limit (-1)

bidix.UploadLog = function() {
	if (!config.options.chkUploadLog) 
		return; // this.tiddler = null
	this.tiddler = store.getTiddler("UploadLog");
	if (!this.tiddler) {
		this.tiddler = new Tiddler();
		this.tiddler.title = "UploadLog";
		this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
		this.tiddler.created = new Date();
		this.tiddler.modifier = config.options.txtUserName;
		this.tiddler.modified = new Date();
		store.addTiddler(this.tiddler);
	}
	return this;
};

bidix.UploadLog.prototype.addText = function(text) {
	if (!this.tiddler)
		return;
	// retrieve maxLine when we need it
	var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
	if (isNaN(maxLine))
		maxLine = -1;
	// add text
	if (maxLine != 0) 
		this.tiddler.text = this.tiddler.text + text;
	// Trunck to maxLine
	if (maxLine >= 0) {
		var textArray = this.tiddler.text.split('\n');
		if (textArray.length > maxLine + 1)
			textArray.splice(1,textArray.length-1-maxLine);
			this.tiddler.text = textArray.join('\n');		
	}
	// update tiddler fields
	this.tiddler.modifier = config.options.txtUserName;
	this.tiddler.modified = new Date();
	store.addTiddler(this.tiddler);
	// refresh and notifiy for immediate update
	story.refreshTiddler(this.tiddler.title);
	store.notify(this.tiddler.title, true);
};

bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {
	if (!this.tiddler)
		return;
	var now = new Date();
	var text = "\n| ";
	var filename = bidix.basename(document.location.toString());
	if (!filename) filename = '/';
	text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
	text += config.options.txtUserName + " | ";
	text += "[["+filename+"|"+location + "]] |";
	text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
	text += uploadDir + " | ";
	text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
	text += backupDir + " |";
	this.addText(text);
};

bidix.UploadLog.prototype.endUpload = function(status) {
	if (!this.tiddler)
		return;
	this.addText(" "+status+" |");
};

//
// Utilities
// 

bidix.checkPlugin = function(plugin, major, minor, revision) {
	var ext = version.extensions[plugin];
	if (!
		(ext  && 
			((ext.major > major) || 
			((ext.major == major) && (ext.minor > minor))  ||
			((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
			// write error in PluginManager
			if (pluginInfo)
				pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
			eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
	}
};

bidix.dirname = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(0, lastpos);
	} else {
		return filePath.substring(0, filePath.lastIndexOf("\\"));
	}
};

bidix.basename = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("#")) != -1) 
		filePath = filePath.substring(0, lastpos);
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(lastpos + 1);
	} else
		return filePath.substring(filePath.lastIndexOf("\\")+1);
};

bidix.initOption = function(name,value) {
	if (!config.options[name])
		config.options[name] = value;
};

//
// Initializations
//

// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);

// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");

//optionsDesc
merge(config.optionsDesc,{
	txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
	txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
	txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
	txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
	txtUploadUserName: "Upload Username",
	pasUploadPassword: "Upload Password",
	chkUploadLog: "do Logging in UploadLog (default: true)",
	txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});

// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');


// Backstage
merge(config.tasks,{
	uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");


//}}}

/***
|''Name:''|UploadTiddlerPlugin|
|''Description:''|Upload a tiddler and Update a remote TiddlyWiki |
|''Version:''|1.2.1|
|''Date:''|2008-08-19|
|''Source:''|http://tiddlywiki.bidix.info/#UploadTiddlerPlugin|
|''Usage:''|Uses {{{uploadOptions>>}}}<br>with those UploadTiddler Options : <br>chkUploadTiddler: <<option chkUploadTiddler>><br>txtUploadTiddlerStoreUrl: <<option txtUploadTiddlerStoreUrl>>|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.3.0|
***/
//{{{
version.extensions.UploadTiddlerPlugin = {
	major: 1, minor: 2, revision: 1, 
	date: new Date("2008-08-11"),
	source: 'http://tiddlywiki.bidix.info/#UploadTiddlerPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.3.0'
};

if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;
bidix.uploadTiddler = {
	messages: {
		aboutToSaveTiddler: "About to update tiddler '%0'...",
		storeTiddlerNotFound: "Script store tiddler '%0' not found",
		tiddlerSaved: "Tiddler '%0' updated in '%1'"
	},
	upload: function(title,tiddler,oldTitle) {
		var callback = function(status,params,responseText,url,xhr) {
			if (xhr.status == 404) {
				alert(bidix.uploadTiddler.messages.storeTiddlerNotFound.format([url]));
				return;
			}
			if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
				alert(responseText);
				if (responseText.indexOf("Debug mode") >= 0 )
					responseText = responseText.substring(responseText.indexOf("\n\n")+2);
			} else if (responseText.charAt(0) != '0') 
				alert(responseText);
			else 
				displayMessage(bidix.uploadTiddler.messages.tiddlerSaved.format([params[0], params[1]]));
				store.setDirty(false);
			}

		if ((config.options['chkUploadTiddler']) && (document.location.toString().substr(0,4) == "http")){
			displayMessage(bidix.uploadTiddler.messages.aboutToSaveTiddler.format([title]));
			var ExtTiddler = null;
			var html = null;
			if (tiddler) {
				ExtTiddler = store.getSaver().externalizeTiddler(store,tiddler);
				html = wikifyStatic(tiddler.text,null,tiddler).htmlEncode();
			}
			var form = "title="+encodeURIComponent(title);
			form = form + "&tiddler="+(ExtTiddler?encodeURIComponent(ExtTiddler):'');
			form = form + "&html="+(html?encodeURIComponent(html):'');
			var filename = (config.options['txtUploadFilename']?config.options['txtUploadFilename']:'index.html');
			form = form +"&oldTitle="+encodeURIComponent(oldTitle);
			form = form +"&fileName="+encodeURIComponent(filename);
			form = form +"&backupDir="+encodeURIComponent(config.options['txtUploadBackupDir']);
			form = form +"&user="+encodeURIComponent(config.options['txtUploadUserName']);
			form = form +"&password="+encodeURIComponent(config.options['pasUploadPassword']);
			form = form +"&uploadir="+encodeURIComponent(config.options['txtUploadDir']);
			form = form +"&debug="+encodeURIComponent(0);
			var storeScript = (config.options.txtUploadTiddlerStoreUrl 
								? config.options.txtUploadTiddlerStoreUrl : 'storeTiddler.php');
			var r = doHttp("POST",storeScript,form+"\n",'application/x-www-form-urlencoded',
				config.options['txtUploadUserName'],config.options['pasUploadPassword'],callback,Array(title,filename),null);
		}
	}
}
TiddlyWiki.prototype.saveTiddler_bidix = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(oldTitle,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
	var tiddler = TiddlyWiki.prototype.saveTiddler_bidix.apply(this,arguments);
	var title = (newTitle?newTitle:oldTitle);
	if (oldTitle == title)
		oldTitle = '';
	bidix.uploadTiddler.upload(title, tiddler, oldTitle);
}
TiddlyWiki.prototype.removeTiddler_bidix =TiddlyWiki.prototype.removeTiddler;
TiddlyWiki.prototype.removeTiddler = function(title) {
	TiddlyWiki.prototype.removeTiddler_bidix.apply(this,arguments);
	bidix.uploadTiddler.upload(title, null);
}

//
// Initializations
//

bidix.initOption = function(name,value) {
	if (!config.options[name])
		config.options[name] = value;
};

// styleSheet
setStylesheet('.txtUploadTiddlerStoreUrl {width: 22em;}',"uploadTiddlerPluginStyles");

//optionsDesc
merge(config.optionsDesc,{
	txtUploadTiddlerStoreUrl: "Url of the UploadTiddlerService script (default: storeTiddler.php)",
	chkUploadTiddler: "Do per Tiddler upload using txtUploadTiddlerStoreUrl (default: false)"
});

// Options Initializations
bidix.initOption('txtUploadTiddlerStoreUrl','');
bidix.initOption('chkUploadTiddler','');

// add options in backstage UploadOptions
if (config.macros.uploadOptions) {
	if (config.macros.uploadOptions.options) {
		config.macros.uploadOptions.options.push("txtUploadTiddlerStoreUrl","chkUploadTiddler");
	}
}

//}}}

/***
|''Name:''|UploadToHomeMacro|
|''Description:''|Save TiddlyWiki using HomeParameters tiddler|
|''Version:''|0.0.2|
|''Date:''|May 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadToHomeMacro|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (#2125)|
|''Requires:''|UploadPlugin|
|''Usage:''|{{{<<uploadToHome [HomeParameters]>>}}}<br>{{{HomeParameters:}}} optional - Tiddler with upload parameters in slices (see HomeParameters).|
***/
//{{{
version.extensions.UploadToHomeMacro = {
	major: 0, minor: 0, revision: 2,
	date: new Date("May 19, 2007"),
	source: 'http://tiddlywiki.bidix.info/#UploadToHomeMacro',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0 (#3125)'
};

//
// Environment
//

if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;	// true to activate both in Plugin and UploadService
bidix.checkPlugin("UploadPlugin", 4, 1, 0);

//
// uploadUsing Macro
//

config.macros.uploadToHome = {
	handler: function(place,macroName,params) {
		if (readOnly)
			return;
		var label;
		if (document.location.toString().substr(0,4) == "http") 
			label = config.macros.upload.label.saveLabel;
		else
			label = config.macros.upload.label.uploadLabel;
		var prompt;
		var homeParams = (params[0] ? params[0]:this.messages.homeParamsTiddler);
		if (store.tiddlerExists(homeParams) || store.isShadowTiddler(homeParams)) {
			prompt = this.messages.prompt.toString().format([homeParams]);
		} else {
			throw(this.messages.tiddlerNotFound.toString().format([homeParams]));
		}
		var prompt = this.messages.prompt.toString().format([homeParams]);
		createTiddlyButton(place, label, prompt, function() {config.macros.uploadToHome.action(homeParams);}, null, null, this.accessKey);		
	},
	
	action: function(homeParams) {
		homeParams = (homeParams ? homeParams : config.macros.uploadToHome.messages.homeParamsTiddler);
		if (!store.tiddlerExists(homeParams) && !store.isShadowTiddler(homeParams)) {
			throw(config.macros.uploadToHome.messages.tiddlerNotFound.toString().format([homeParams]));
		}
		config.macros.upload.action(config.macros.uploadToHome.getParamsFromTiddler(homeParams));
	},
	
	getParamsFromTiddler: function(tiddlerTitle) {
		tiddlerTitle = (tiddlerTitle ? tiddlerTitle:this.messages.homeParamsTiddler);
		if (!store.tiddlerExists(tiddlerTitle) && !store.isShadowTiddler(tiddlerTitle)) {
			throw(config.macros.uploadToHome.messages.tiddlerNotFound.toString().format([tiddlerTitle]));
		}
		var sliceNames = [
			"UploadStoreUrl",
			"UploadFilename",
			"UploadBackupDir",
			"UploadDir",
			"UploadUserName"
			//"UploadPassword", // no password in tiddlers
		];
		var sliceValues = store.getTiddlerSlices(tiddlerTitle,sliceNames);
		var parameters = [];
		for(var i=0; i<sliceNames.length; i++) {
			parameters.push(sliceValues[sliceNames[i]]);
		}
		return parameters;
	},
	
	messages: {
		homeParamsTiddler: "HomeParameters",
		prompt: "Save and Upload this TiddlyWiki using parameters in  '%0' tiddler",
		tiddlerNotFound: "Tiddler %0 not found"
	},
	initAtLoad: function () {
		// install Shadowed HomeParameters
		var storeUrl;
		if ((document.location.toString().substr(0,4) == "http")) 
			storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
		else
			storeUrl = config.macros.upload.defaultStoreScript;
		var shadowedHomeParameters = (config.shadowTiddlers['HomeParameters']?config.shadowTiddlers['HomeParameters']:'');
		shadowedHomeParameters += [
			"|UploadUserName:|"+config.options['txtUploadUserName']+"|",
			"|UploadStoreUrl:|"+storeUrl+"|",
			"|UploadDir:|.|",
			"|UploadFilename:|index.html|",
			"|UploadBackupDir:||"
			].join("\n");
		merge(config.shadowTiddlers,{'HomeParameters':	shadowedHomeParameters});
		// install Backstage uploadToHome
		merge(config.tasks,{
			uploadToHome: {text: "uploadToHome", tooltip: "Upload using '" + this.messages.homeParamsTiddler + "' tiddler", action: this.action}
		});
		config.backstageTasks.push("uploadToHome");
				
	}
};

config.macros.uploadToHome.initAtLoad();

//}}}
Each site hosted in a TiddlyHome provides this URL :
*http://TiddlyHome.bidix.info/YourSite/backup : List of backup files
*http://TiddlyHome.bidix.info/YourSite/download.php : to download your TiddlyWiki
*http://TiddlyHome.bidix.info/YourSite/index.xml : your RSSFeed
*http://TiddlyHome.bidix.info/YourSite/news.php : to display your RSSFeed
Available User commands:
<<allTags [[admin]]>>
<<userTimeline>>
<html>
<iframe style="border: 1px; background: #eee;" src="_th/lib/user.php?next=verify" width=100% height=200px>
</iframe>
</html>