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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

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

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which 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>>
Based on TiddlyWiki 1.2.39 (beta 1)\n\n[[Download here.|/versions/1.2.39(b1).5.zexp]]\n\nMajor Changes:\n* Fixed bug in modified date when ZiddlyWiki was inside a Plone site.
Based on TiddlyWiki 1.2.39 (beta 1)\n\n[[Download here.|/versions/1.2.39(b1).4.zexp]]\n\nMajor Changes:\n* Fixed bug preventing creation of a tiddler with a title that contained no ASCII characters.
Based on TiddlyWiki 1.2.39 (beta 1)\n\n[[Download here.|/versions/1.2.39(b1).3.zexp]]\n\nMajor Changes:\n* Removed all skins (more about that [[here|http://ziddlywiki.com/forum/#NewZWDirection]]).\n* Removed all images.\n* Versions are back.
ZiddlyWiki is a hosted non-linear personal/public/collaborative micro-content wiki/blog based on TiddlyWiki. The "Z" stands for [[Zope]] -- the powerful server-side platform on which ZiddlyWiki runs. \n\nYou can get a feel for ZW in the [[Sandbox|/sandbox]].\n\nWhen you're ready to join the revolution, you can GetYourOwn.\n\nZiddlyWiki is a community free software project, and depends on your bug-fixes and feature contributions! See ZiddlyBugs and ZiddlyContributions for more info.
Zope is an open source application server for building content management systems, intranets, portals, and custom applications. Zope is written in Python, a highly-productive, object-oriented scripting language.\n\nhttp://zope.org
/***\nThis tiddler is a special status tiddler. It is a DTML script that interrogates Zope about the status of your tiddlers. The variables below are dynamic and this tiddler is reloaded when you login. Editing this tiddler through ZiddlyWiki will break your ZiddlyWiki. (If you need to make modifications, edit it in the ZMI)\n***/\n//{{{\nif(typeof zw == "undefined") var zw = {};\nzw.loggedIn = false;\nzw.anonEdit = false;\nzw.isAdmin = false;\nzw.latestTiddler = 119038806946;\nzw.username = 'Anonymous User';\nconfig.options.txtUserName = 'Anonymous User';\nzw.serverUrl = "http://zw.mcelrath.org/ziddlywiki.com";\nversion.extensions.ZiddlyWiki = '1';\nzw.tiddlerList = {\n"AJAX": "878.7151.38480.2986",\n"ActiveUsersMacro": "878.7151.38480.2986",\n"AnonymousEditing": "878.7151.38480.2986",\n"AutoRefresh": "878.7151.38480.2986",\n"CookieAuthentication": "878.7151.38480.2986",\n"CopyTiddlerPlugin": "878.7151.38480.2986",\n"CopyTiddlers": "878.7151.38480.2986",\n"CreateALogin": "878.7151.38480.2986",\n"DefaultTiddlers": "878.7151.38480.2986",\n"EasterEggLinks": "878.7151.38480.2986",\n"FeatureRequests": "878.7151.38480.2986",\n"FreeZope": "878.7151.38480.2986",\n"GetYourOwn": "880.32920.53259.36590",\n"GetZope": "878.7151.38480.2986",\n"HideYourZW": "878.7151.38480.2986",\n"ImageShack": "878.7151.38480.2986",\n"ImportAndExport": "878.7151.38480.2986",\n"ImportTiddlyWiki": "878.7151.38480.2986",\n"ImportZiddlyWiki": "878.7151.38480.2986",\n"InstallScript": "878.7151.38480.2986",\n"JavascriptShellStyleSheet": "878.7151.38480.2986",\n"JeremyRuston": "878.7151.38480.2986",\n"ListTagMacro": "878.7151.38480.2986",\n"LogoutLink": "878.7151.38480.2986",\n"MainMenu": "878.7151.38480.2986",\n"MajorFeatures": "878.7151.38480.2986",\n"MakeBackups": "878.7151.38480.2986",\n"MessageOnLoginTrick": "878.7151.38480.2986",\n"MultipleZWs": "878.7151.38480.2986",\n"News": "878.7151.38480.2986",\n"Objectis": "878.7151.38480.2986",\n"OptionsPanel": "878.7151.38480.2986",\n"PageTemplate.old": "878.7151.38480.2986",\n"PrivateTiddlers": "878.7151.38480.2986",\n"ProtectedTiddlers": "878.7151.38480.2986",\n"SaveChanges": "878.7151.38480.2986",\n"ServerSideWiki": "878.7151.38480.2986",\n"SiteSubtitle": "878.7151.38480.2986",\n"SiteTitle": "878.7151.38480.2986",\n"SpecialTags": "878.7151.38480.2986",\n"StyleSheet.old": "878.7151.38480.2986",\n"SvenTissot": "878.7151.38480.2986",\n"TiddlerBackup": "878.7151.38480.2986",\n"TiddlerCleanup": "878.7151.38480.2986",\n"TiddlerLocks": "878.7151.38480.2986",\n"TiddlyWiki": "878.7151.38480.2986",\n"TimelineDateFormatPlugin": "878.7151.38480.2986",\n"UpgradeZiddlyWiki": "878.7151.38480.2986",\n"Unauthorized to list tiddler": "","Version 1.2.36": "878.7151.38480.2986",\n"Version 1.2.39.1": "878.7151.38480.2986",\n"Version 1.2.39(b1).3": "878.7151.38480.2986",\n"Version 1.2.39(b1).4": "878.7151.38480.2986",\n"Version 1.2.39(b1).5": "878.7151.38480.2986",\n"Version 2.0.0.1": "878.7151.38480.2986",\n"Version 2.0.0.10": "878.7151.38480.2986",\n"Version 2.0.0.11": "878.7151.38480.2986",\n"Version 2.0.0.12": "878.7151.38480.2986",\n"Version 2.0.0.2": "878.7151.38480.2986",\n"Version 2.0.0.3": "878.7151.38480.2986",\n"Version 2.0.0.4": "878.7151.38480.2986",\n"Version 2.0.0.5": "878.7151.38480.2986",\n"Version 2.0.0.6": "878.7151.38480.2986",\n"Version 2.0.0.7": "878.7151.38480.2986",\n"Version 2.0.0.8": "878.7151.38480.2986",\n"Version 2.0.0.9": "878.7151.38480.2986",\n"Version 2.0.10.1": "878.7151.38480.2986",\n"Version 2.0.11.2": "878.7151.38480.2986",\n"Version 2.0.11.3": "878.7151.38480.2986",\n"Version 2.0.11.4": "878.7151.38480.2986",\n"Version 2.0.2.1": "878.7151.38480.2986",\n"Version 2.0.2.2": "878.7151.38480.2986",\n"Version 2.0.2.3": "878.7151.38480.2986",\n"Version 2.0.2.4": "878.7151.38480.2986",\n"Version 2.0.3.1": "878.7151.38480.2986",\n"Version 2.0.3.2": "878.7151.38480.2986",\n"Version 2.0.6.1": "878.7151.38480.2986",\n"Version 2.0.6.2": "878.7151.38480.2986",\n"Versions": "878.7151.38480.2986",\n"ViewTemplate": "878.7151.38480.2986",\n"WebDAV": "878.7151.38480.2986",\n"WebDAV on Linux": "878.7151.38480.2986",\n"Wiki": "878.7151.38480.2986",\n"ZiddlyBlue": "878.7151.38480.2986",\n"ZiddlyBugs": "878.7151.38480.2986",\n"ZiddlyContributions": "878.7151.38480.2986",\n"ZiddlyTricks": "878.7151.38480.2986",\n"ZiddlyWiki": "878.7151.38480.2986",\n"Zope": "878.7151.38480.2986",\n"ZopeAuthentication": "878.7151.38480.2986",\n"ZopeErrorLog": "878.7151.38480.2986",\n"ZopeManagementInterface": "878.7151.38480.2986",\n"ZopeRevisions": "878.7151.38480.2986",\n"test ZiddlyBlue": "878.7151.38480.2986",\n"timmorgan": "878.7151.38480.2986",\n};\n//}}}\n
ZiddlyWiki has a Subversion repository for managing contributions, which is hosted at the [[main TiddlyWiki Trac site|http://trac.tiddlywiki.org]]. If you've found a bug or have an idea for a new feature, please try to fix/implement it yourself and submit it for inclusion in the next release. The instructions here rely on the [[Subversion|http://subversion.tigris.org/]] and [[GNU wget|http://www.gnu.org/software/wget/]] (and wput) tools, which should be readily installable on any UNIX/MacOSX system, or under [[Cygwin|http://www.cygwin.com/]] on windows.\n\nFirst, get yourself a copy of the latest code. This will create the {{{ZiddlyWiki}}} directory\n{{{\nsvn co http://svn.tiddlywiki.org/Trunk/association/serversides/ZiddlyWiki\n}}}\nSecond, import your changes into this directory. From the directory containing {{{ZiddlyWiki}}} above, run:\n{{{\nwget -nv -nH -r ftp://user:pass@host:8021/ZiddlyWiki\n}}}\nreplace {{{user}}} with your Zope username, {{{pass}}} with the corresponding Zope password, and {{{host}}} with the host that's running zope. In this command, the {{{ftp://}}} URL points to the directory {{{ZiddlyWiki}}} in the root of your zope installation. Change it also if you've stored it somewhere else in your Zope installation. The port 8021 is the default port on which Zope runs its FTP server. If for some reason yours is on another port, change that too.\n\nThen you may change to the {{{ZiddlyWiki}}} directory and run:\n{{{\nsvn diff\n}}}\nwhich will show you a diff-formatted list of the changes you've made. Please save this to a file\n{{{\nsvn diff > my_changes.patch\n}}}\nand send it to {{{TiddlyWikiDev@googlegroups.com}}}. You can also post it to the group [[on the web|http://groups.google.com/group/TiddlyWikiDev]].\n\nIf you want to make regular contributions, you should request your own contributor directory in the TiddlyWikiDev group so that the maintainers can easily merge your changes into the main tree.\n\nFinally, we can go the other direction too and upload changes from the svn repository to a working Zope installation. You will want to do this if for some crazy reason you prefer to edit scripts in a text editor rather than on the zope server, or you have used {{{svn update}}} to import the latest changes from the official repository, or {{{svn merge}}} to merge changes from another repository.\n{{{\nfind ZiddlyWiki -type f -not -path \s*.svn\s* | wput -nv -nc -u -i - ftp://user:pass@host:8021/\n}}}\nAgain the same comments above apply to the contents of the {{{ftp://}}} url. This command will update the directory {{{ZiddlyWiki}}} living in the root of your zope installation, assuming the directory from which this command is run contains a directory {{{ZiddlyWiki}}}. The {{{find}}} command generates a list of files, ignoring the directories {{{.svn}}} which Subversion uses for version control, and passes this list to wput.\n\nThese commands are obviously cumbersome to type, you may want to put them into a small script so you don't have to re-type the whole thing.\n\nGood Luck! We look forward to your contributions!
The [[Zope]] Management Interface is accessed by appending "/manage" to the end of your Zope instance URL.\n\n* http://yourdomain.com/manage\n* http://yourname.freezope.org/manage
//{{{\n//replaces toolbar buttons with icons.\n//for each command that you want to use an icon, add a line like the following in a systemConfig tiddler, specifying the icon image location:\n//config.commands.editTiddler.imgLoc= "jump.bmp";\n//No need to edit the ViewTemplate! If an image location is specified, then the icon will be used for that command!\n\nconfig.macros.toolbar.createCommand = function(place,commandName,tiddler,theClass)\n{\n if(typeof commandName != "string")\n {\n var c = null;\n for(var t in config.commands)\n if(config.commands[t] == commandName)\n c = t;\n commandName = c;\n }\n if((tiddler instanceof Tiddler) && (typeof commandName == "string"))\n {\n var title = tiddler.title;\n var command = config.commands[commandName];\n var ro = tiddler.isReadOnly();\n var shadow = store.isShadowTiddler(title) && !store.tiddlerExists(title);\n var text = ro && command.readOnlyText ? command.readOnlyText : command.text;\n var tooltip = ro && command.readOnlyTooltip ? command.readOnlyTooltip : command.tooltip;\n if((!ro || (ro && !command.hideReadOnly)) && !(shadow && command.hideShadow))\n {\n var btn = createTiddlyButton(null,text,tooltip,this.onClickCommand);\n btn.setAttribute("commandName", commandName);\n btn.setAttribute("tiddler", title);\n if(theClass)\n addClass(btn,theClass);\n place.appendChild(btn);\n if(command.imgLoc)\n btn.innerHTML = "<img src='"+command.imgLoc+"'>";\n\n }\n }\n}\n\nsetStylesheet(".toolbarImg {vertical-align: middle; cursor:pointer;}\sn","commandIconStyles"); \n//}}}
Starting with [[Version 2.0.2.1]], ZiddlyWiki now automatically queries the server for updated tiddlers every minute. This allows you to keep the page open without constantly refreshing to see if someone else has made changes. This, combined with TiddlerLocks, should encourage even more collaborative editing.\n\nThis feature actually //saves bandwidth//, because only new tiddler content is being sent back. The query sent every minute is very small, too. Thus, rather than a visitor constantly refreshing a 150KB+ web page, only tiddlers are sent across the wire. And in case someone leaves their browser window open on their always-connected PC at their summer home in Iceland, the feature turns itself off after thirty minutes.
Derived from [[this|http://www.squarefree.com/shell/?ignoreReferrerFrom=shell1.4]]\nstore.fetchTiddler("Test").revisionKey\ntime(f, n)\n<html>\n<div>\n Features: autocompletion of property names with Tab, multiline input with Shift+Enter, input history with (Ctrl+) Up/Down, \n <a accesskey="M" href="javascript:jsshell.go('scope(Math); mathHelp();');" title="Accesskey: M">Math</a>\n</div>\n<div>\nValues and functions: ans, print(string), \n <a accesskey="P" href="javascript:jsshell.go('props(ans)')" title="Accesskey: P">props(object)</a>, \n <a accesskey="B" href="javascript:jsshell.go('blink(ans)')" title="Accesskey: B">blink(node)</a>, \n <a href="javascript:jsshell.go('wikify(ans)')">wikify(text)</a>\n <a href="javascript:jsshell.go('print(ans)')">print(text)</a>\n <a accesskey="C" href="javascript:jsshell.go('clear()')" title="Accesskey: C">clear()</a>, \n load(scriptURL), \n scope(object)</div>\n<div class="shell">\n <div id="output"></div>\n <div><textarea id="input" class="input" wrap="off" onkeydown="jsshell.inputKeydown(event)" rows="1"></textarea></div>\n</div>\n</html><script>\n\nsetStylesheet(store.getRecursiveTiddlerText("JavascriptShellStyleSheet","",10));\n\nwindow.jsshell = {}; // Put our functions in the global namespace.\n\nwindow.jsshell.refocus = function()\n{\n jsshell._in.blur(); // Needed for Mozilla to scroll correctly.\n jsshell._in.focus();\n}\n\nwindow.jsshell.initTarget = function()\n{\n window.print = jsshell.shellCommands.print;\n}\n\n// Unless the user is selected something, refocus the textbox.\n// (requested by caillon, brendan, asa)\nwindow.jsshell.keepFocusInTextbox = function(e) \n{\n var g = e.srcElement ? e.srcElement : e.target; // IE vs. standard\n \n while (!g.tagName)\n g = g.parentNode;\n var t = g.tagName.toUpperCase();\n if (t=="A" || t=="INPUT")\n return;\n \n if (window.getSelection) {\n // Mozilla\n if (String(window.getSelection()))\n return;\n }\n else if (document.getSelection) {\n // Opera? Netscape 4?\n if (document.getSelection())\n return;\n }\n else {\n // IE\n if ( document.selection.createRange().text )\n return;\n }\n \n jsshell.refocus();\n}\n\n//function inputKeydown(e) {\nwindow.jsshell.inputKeydown = function(e) {\n // Use onkeydown because IE doesn't support onkeypress for arrow keys\n\n //alert(e.keyCode + " ^ " + e.keycode);\n\n if (e.shiftKey && e.keyCode == 13) { // shift-enter\n // don't do anything; allow the shift-enter to insert a line break as normal\n } else if (e.keyCode == 13) { // enter\n // execute the input on enter\n try { jsshell.go(); } catch(er) { alert(er); };\n setTimeout(function() { jsshell._in.value = ""; }, 0); // can't preventDefault on input, so clear it later\n } else if (e.keyCode == 38) { // up\n // go up in history if at top or ctrl-up\n if (e.ctrlKey || jsshell.caretInFirstLine(jsshell._in))\n jsshell.hist(true);\n } else if (e.keyCode == 40) { // down\n // go down in history if at end or ctrl-down\n if (e.ctrlKey || jsshell.caretInLastLine(jsshell._in))\n jsshell.hist(false);\n } else if (e.keyCode == 9) { // tab\n jsshell.tabcomplete();\n setTimeout(function() { jsshell.refocus(); }, 0); // refocus because tab was hit\n } else { }\n\n setTimeout(jsshell.recalculateInputHeight, 0);\n \n //return true;\n};\n\nwindow.jsshell.caretInFirstLine = function(textbox)\n{\n // IE doesn't support selectionStart/selectionEnd\n if (textbox.selectionStart == undefined)\n return true;\n\n var firstLineBreak = textbox.value.indexOf("\sn");\n\n return ((firstLineBreak == -1) || (textbox.selectionStart <= firstLineBreak));\n}\n\nwindow.jsshell.caretInLastLine = function(textbox)\n{\n // IE doesn't support selectionStart/selectionEnd\n if (textbox.selectionEnd == undefined)\n return true;\n\n var lastLineBreak = textbox.value.lastIndexOf("\sn");\n \n return (textbox.selectionEnd > lastLineBreak);\n}\n\nwindow.jsshell.recalculateInputHeight = function()\n{\n var rows = jsshell._in.value.split(/\sn/).length\n + 1 // prevent scrollbar flickering in Mozilla\n + (window.opera ? 1 : 0); // leave room for scrollbar in Opera\n\n if (jsshell._in.rows != rows) // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0.\n jsshell._in.rows = rows;\n}\n\nwindow.jsshell.println = function(s, type)\n{\n if((s=String(s)))\n {\n var newdiv = document.createElement("div");\n newdiv.appendChild(document.createTextNode(s));\n newdiv.className = type;\n jsshell._out.appendChild(newdiv);\n return newdiv;\n }\n}\n\nwindow.jsshell.printWithRunin = function(h, s, type)\n{\n var div = jsshell.println(s, type);\n var head = document.createElement("strong");\n head.appendChild(document.createTextNode(h + ": "));\n div.insertBefore(head, div.firstChild);\n}\n\nwindow.jsshell.shellCommands = \n{\nload : function load(url)\n{\n var s = document.createElement("script");\n s.type = "text/javascript";\n s.src = url;\n document.getElementsByTagName("head")[0].appendChild(s);\n jsshell.println("Loading " + url + "...", "message");\n},\n\nclear : function clear()\n{\n jsshell._out.innerHTML = "";\n},\n\nwikify : function wikify(text)\n{\n window.wikify(text, jsshell._out);\n},\n\nprint : function print(s) { jsshell.println(s, "print"); },\n\n// the normal function, "print", shouldn't return a value\n// (suggested by brendan; later noticed it was a problem when showing others)\npr : function pr(s) \n{ \n jsshell.shellCommands.print(s); // need to specify shellCommands so it doesn't try window.print()!\n return s;\n},\n\nprops : function props(e, onePerLine)\n{\n if (e === null) {\n jsshell.println("props called with null argument", "error");\n return;\n }\n\n if (e === undefined) {\n jsshell.println("props called with undefined argument", "error");\n return;\n }\n\n var ns = ["Methods", "Fields", "Unreachables"];\n var as = [[], [], []]; // array of (empty) arrays of arrays!\n var p, j, i; // loop variables, several used multiple times\n\n var protoLevels = 0;\n\n for (p = e; p; p = p.__proto__)\n {\n for (i=0; i<ns.length; ++i)\n as[i][protoLevels] = [];\n ++protoLevels;\n }\n\n for(var a in e)\n {\n // Shortcoming: doesn't check that VALUES are the same in object and prototype.\n\n var protoLevel = -1;\n try\n {\n for (p = e; p && (a in p); p = p.__proto__)\n ++protoLevel;\n }\n catch(er) { protoLevel = 0; } // "in" operator throws when param to props() is a string\n\n var type = 1;\n try\n {\n if ((typeof e[a]) == "function")\n type = 0;\n }\n catch (er) { type = 2; }\n\n as[type][protoLevel].push(a);\n }\n\n function times(s, n) { return n ? s + times(s, n-1) : ""; }\n\n for (j=0; j<protoLevels; ++j)\n for (i=0;i<ns.length;++i)\n if (as[i][j].length) \n jsshell.printWithRunin(\n ns[i] + times(" of prototype", j), \n (onePerLine ? "\sn\sn" : "") + as[i][j].sort().join(onePerLine ? "\sn" : ", ") + (onePerLine ? "\sn\sn" : ""), \n "propList"\n );\n},\n\nblink : function blink(node)\n{\n if (!node) throw("blink: argument is null or undefined.");\n if (node.nodeType == null) throw("blink: argument must be a node.");\n if (node.nodeType == 3) throw("blink: argument must not be a text node");\n if (node.documentElement) throw("blink: argument must not be the document object");\n\n function setOutline(o) { \n return function() {\n if (node.style.outline != node.style.bogusProperty) {\n // browser supports outline (Firefox 1.1 and newer, CSS3, Opera 8).\n node.style.outline = o;\n }\n else if (node.style.MozOutline != node.style.bogusProperty) {\n // browser supports MozOutline (Firefox 1.0.x and older)\n node.style.MozOutline = o;\n }\n else {\n // browser only supports border (IE). border is a fallback because it moves things around.\n node.style.border = o;\n }\n }\n } \n \n function focusIt(a) {\n return function() {\n a.focus(); \n }\n }\n\n if (node.ownerDocument) {\n var windowToFocusNow = (node.ownerDocument.defaultView || node.ownerDocument.parentWindow); // Moz vs. IE\n if (windowToFocusNow)\n setTimeout(focusIt(windowToFocusNow.top), 0);\n }\n\n for(var i=1;i<7;++i)\n setTimeout(setOutline((i%2)?'3px solid red':'none'), i*100);\n\n setTimeout(focusIt(window), 800);\n setTimeout(focusIt(jsshell._in), 810);\n},\n\ntime: function (f, n) { \n var start = new Date(); \n if (typeof n != typeof undefined) { \n for (var i = 0; i < n; i++) { f(); } } \n else { f(); } \n var stop = new Date(); \n return stop - start; \n},\n\nscope : function scope(sc)\n{\n if (!sc) sc = {};\n jsshell._scope = sc;\n jsshell.println("Scope is now " + sc + ". If a variable is not found in this scope, window will also be searched. New variables will still go on window.", "message");\n},\n\nmathHelp : function mathHelp()\n{\n jsshell.printWithRunin("Math constants", "E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2", "propList");\n jsshell.printWithRunin("Math methods", "abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan", "propList");\n},\n\nans : undefined\n};\n\n\nwindow.jsshell.hist = function(up)\n{\n // histList[0] = first command entered, [1] = second, etc.\n // type something, press up --> thing typed is now in "limbo"\n // (last item in histList) and should be reachable by pressing \n // down again.\n\n var L = jsshell.histList.length;\n\n if (L == 1)\n return;\n\n if (up)\n {\n if (jsshell.histPos == L-1)\n {\n // Save this entry in case the user hits the down key.\n jsshell.histList[jsshell.histPos] = jsshell._in.value;\n }\n\n if (jsshell.histPos > 0)\n {\n jsshell.histPos--;\n // Use a timeout to prevent up from moving cursor within new text\n // Set to nothing first for the same reason\n setTimeout(\n function() {\n jsshell._in.value = ''; \n jsshell._in.value = jsshell.histList[jsshell.histPos];\n var caretPos = jsshell._in.value.length;\n if (jsshell._in.setSelectionRange) \n jsshell._in.setSelectionRange(caretPos, caretPos);\n },\n 0\n );\n }\n } \n else // down\n {\n if (jsshell.histPos < L-1)\n {\n jsshell.histPos++;\n jsshell._in.value = jsshell.histList[jsshell.histPos];\n }\n else if (jsshell.histPos == L-1)\n {\n // Already on the current entry: clear but save\n if (jsshell._in.value)\n {\n jsshell.histList[jsshell.histPos] = jsshell._in.value;\n ++jsshell.histPos;\n jsshell._in.value = "";\n }\n }\n }\n}\n\nwindow.jsshell.tabcomplete = function()\n{\n /*\n * Working backwards from s[from], find the spot\n * where this expression starts. It will scan\n * until it hits a mismatched ( or a space,\n * but it skips over quoted strings.\n * If stopAtDot is true, stop at a '.'\n */\n function findbeginning(s, from, stopAtDot)\n {\n /*\n * Complicated function.\n *\n * Return true if s[i] == q BUT ONLY IF\n * s[i-1] is not a backslash.\n */\n function equalButNotEscaped(s,i,q)\n {\n if(s.charAt(i) != q) // not equal go no further\n return false;\n\n if(i==0) // beginning of string\n return true;\n\n if(s.charAt(i-1) == '\s\s') // escaped?\n return false;\n\n return true;\n }\n\n var nparens = 0;\n var i;\n for(i=from; i>=0; i--)\n {\n if(s.charAt(i) == ' ')\n break;\n\n if(stopAtDot && s.charAt(i) == '.')\n break;\n \n if(s.charAt(i) == ')')\n nparens++;\n else if(s.charAt(i) == '(')\n nparens--;\n\n if(nparens < 0)\n break;\n\n // skip quoted strings\n if(s.charAt(i) == '\s'' || s.charAt(i) == '\s"')\n {\n //dump("skipping quoted chars: ");\n var quot = s.charAt(i);\n i--;\n while(i >= 0 && !equalButNotEscaped(s,i,quot)) {\n //dump(s.charAt(i));\n i--;\n }\n //dump("\sn");\n }\n }\n return i;\n }\n\n // XXX should be used more consistently (instead of using selectionStart/selectionEnd throughout code)\n // XXX doesn't work in IE, even though it contains IE-specific code\n function getcaretpos(inp)\n {\n if(inp.selectionEnd != null)\n return inp.selectionEnd;\n \n if(inp.createTextRange)\n {\n var docrange = document.selection.createRange();\n var inprange = inp.createTextRange();\n if (inprange.setEndPoint)\n {\n inprange.setEndPoint('EndToStart', docrange);\n return inprange.text.length;\n }\n }\n\n return inp.value.length; // sucks, punt\n }\n\n function setselectionto(inp,pos)\n {\n if(inp.selectionStart) {\n inp.selectionStart = inp.selectionEnd = pos;\n }\n else if(inp.createTextRange) {\n var docrange = document.selection.createRange();\n var inprange = inp.createTextRange();\n inprange.move('character',pos);\n inprange.select();\n }\n else { // err...\n /*\n inp.select();\n if(document.getSelection())\n document.getSelection() = "";\n */\n }\n }\n // get position of cursor within the input box\n var caret = getcaretpos(jsshell._in);\n\n if(caret) {\n //dump("----\sn");\n var dotpos, spacepos, complete, obj;\n //dump("caret pos: " + caret + "\sn");\n // see if there's a dot before here\n dotpos = findbeginning(jsshell._in.value, caret-1, true);\n //dump("dot pos: " + dotpos + "\sn");\n if(dotpos == -1 || jsshell._in.value.charAt(dotpos) != '.') {\n dotpos = caret;\n//dump("changed dot pos: " + dotpos + "\sn");\n }\n\n // look backwards for a non-variable-name character\n spacepos = findbeginning(jsshell._in.value, dotpos-1, false);\n //dump("space pos: " + spacepos + "\sn");\n // get the object we're trying to complete on\n if(spacepos == dotpos || spacepos+1 == dotpos || dotpos == caret)\n {\n // try completing function args\n if(jsshell._in.value.charAt(dotpos) == '(' ||\n (jsshell._in.value.charAt(spacepos) == '(' && (spacepos+1) == dotpos))\n {\n var fn,fname;\n var from = (jsshell._in.value.charAt(dotpos) == '(') ? dotpos : spacepos;\n spacepos = findbeginning(jsshell._in.value, from-1, false);\n\n fname = jsshell._in.value.substr(spacepos+1,from-(spacepos+1));\n //dump("fname: " + fname + "\sn");\n try {\n with(window)\n with(jsshell._scope)\n with(jsshell.shellCommands)\n fn = eval(fname);\n }\n catch(er) {\n //dump('fn is not a valid object\sn');\n return;\n }\n if(fn == undefined) {\n //dump('fn is undefined');\n return;\n }\n if(fn instanceof Function)\n {\n // Print function definition, including argument names, but not function body\n if(!fn.toString().match(/function .+?\s(\s) +\s{\sn +\s[native code\s]\sn\s}/))\n jsshell.println(fn.toString().match(/function .+?\s(.*?\s)/), "tabcomplete");\n }\n\n return;\n }\n else\n obj = window;\n }\n else\n {\n var objname = jsshell._in.value.substr(spacepos+1,dotpos-(spacepos+1));\n //dump("objname: |" + objname + "|\sn");\n try {\n with(jsshell._scope)\n with(window)\n obj = eval(objname);\n }\n catch(er) {\n jsshell.printError(er); \n return;\n }\n if(obj == undefined) {\n // sometimes this is tabcomplete's fault, so don't print it :(\n // e.g. completing from "print(document.getElements"\n // jsshell.println("Can't complete from null or undefined expression " + objname, "error");\n return;\n }\n }\n //dump("obj: " + obj + "\sn");\n // get the thing we're trying to complete\n if(dotpos == caret)\n {\n if(spacepos+1 == dotpos || spacepos == dotpos)\n {\n // nothing to complete\n //dump("nothing to complete\sn");\n return;\n }\n\n complete = jsshell._in.value.substr(spacepos+1,dotpos-(spacepos+1));\n }\n else {\n complete = jsshell._in.value.substr(dotpos+1,caret-(dotpos+1));\n }\n //dump("complete: " + complete + "\sn");\n // ok, now look at all the props/methods of this obj\n // and find ones starting with 'complete'\n var matches = [];\n var bestmatch = null;\n for(var a in obj)\n {\n //a = a.toString();\n //XXX: making it lowercase could help some cases,\n // but screws up my general logic.\n if(a.substr(0,complete.length) == complete) {\n matches.push(a);\n ////dump("match: " + a + "\sn");\n // if no best match, this is the best match\n if(bestmatch == null)\n {\n bestmatch = a;\n }\n else {\n // the best match is the longest common string\n function min(a,b){ return ((a<b)?a:b); }\n var i;\n for(i=0; i< min(bestmatch.length, a.length); i++)\n {\n if(bestmatch.charAt(i) != a.charAt(i))\n break;\n }\n bestmatch = bestmatch.substr(0,i);\n ////dump("bestmatch len: " + i + "\sn");\n }\n ////dump("bestmatch: " + bestmatch + "\sn");\n }\n }\n bestmatch = (bestmatch || "");\n ////dump("matches: " + matches + "\sn");\n var objAndComplete = (objname || obj) + "." + bestmatch;\n //dump("matches.length: " + matches.length + ", jsshell.tooManyMatches: " + jsshell.tooManyMatches + ", objAndComplete: " + objAndComplete + "\sn");\n if(matches.length > 1 && (jsshell.tooManyMatches == objAndComplete || matches.length <= 10)) {\n\n jsshell.printWithRunin("Matches: ", matches.join(', '), "tabcomplete");\n jsshell.tooManyMatches = null;\n }\n else if(matches.length > 10)\n {\n jsshell.println(matches.length + " matches. Press tab again to see them all", "tabcomplete");\n jsshell.tooManyMatches = objAndComplete;\n }\n else {\n jsshell.tooManyMatches = null;\n }\n if(bestmatch != "")\n {\n var sstart;\n if(dotpos == caret) {\n sstart = spacepos+1;\n }\n else {\n sstart = dotpos+1;\n }\n jsshell._in.value = jsshell._in.value.substr(0, sstart)\n + bestmatch\n + jsshell._in.value.substr(caret);\n setselectionto(jsshell._in,caret + (bestmatch.length - complete.length));\n }\n }\n}\n\nwindow.jsshell.printQuestion = function(q)\n{\n jsshell.println(q, "input");\n}\n\nwindow.jsshell.printAnswer = function(a)\n{\n if (a !== undefined) {\n jsshell.println(a, "normalOutput");\n jsshell.shellCommands.ans = a;\n }\n}\n\nwindow.jsshell.printError = function(er)\n{ \n var lineNumberString;\n\n lastError = er; // for debugging the shell\n if (er.name)\n {\n // lineNumberString should not be "", to avoid a very wacky bug in IE 6.\n lineNumberString = (er.lineNumber != undefined) ? (" on line " + er.lineNumber + ": ") : ": ";\n jsshell.println(er.name + lineNumberString + er.message, "error"); // Because IE doesn't have error.toString.\n }\n else\n jsshell.println(er, "error"); // Because security errors in Moz /only/ have toString.\n}\n\nwindow.jsshell.go = function(s)\n{\n jsshell._in.value = jsshell.question = s ? s : jsshell._in.value;\n\n if (jsshell.question == "")\n return;\n\n jsshell.histList[jsshell.histList.length-1] = jsshell.question;\n jsshell.histList[jsshell.histList.length] = "";\n jsshell.histPos = jsshell.histList.length - 1;\n \n // Unfortunately, this has to happen *before* the JavaScript is run, so that \n // print() output will go in the right place.\n jsshell._in.value='';\n jsshell.recalculateInputHeight();\n jsshell.printQuestion(jsshell.question);\n\n if (window.closed) {\n jsshell.printError("Target window has been closed.");\n return;\n }\n \n try { ("jsshell" in window) }\n catch(er) {\n jsshell.printError("The JavaScript Shell cannot access variables in the target window. The most likely reason is that the target window now has a different page loaded and that page has a different hostname than the original page.");\n return;\n }\n\n if (!("jsshell" in window))\n initTarget(); // silent\n\n // Evaluate Shell.question using _win's eval (this is why eval isn't in the |with|, IIRC).\n// window.location.href = "javascript:try{ jsshell.printAnswer(eval('with(jsshell._scope) with(jsshell.shellCommands) {' + jsshell.question + String.fromCharCode(10) + '}')); } catch(er) { jsshell.printError(er); }; setTimeout(jsshell.refocus, 0); void 0";\n try { \n jsshell.printAnswer(eval(\n 'with(jsshell._scope) with(jsshell.shellCommands) {' \n + jsshell.question + String.fromCharCode(10) + \n '}')); \n } catch(er) { \n jsshell.printError(er); \n }; \n setTimeout(jsshell.refocus, 0);\n}\n\nwindow.jsshell.histList = [""]; \nwindow.jsshell.histPos = 0; \nwindow.jsshell._scope = {}; \nwindow.jsshell.question;\nwindow.jsshell._in;\nwindow.jsshell._out;\nwindow.jsshell.tooManyMatches = null;\nwindow.jsshell.lastError = null;\n\njsshell._in = document.getElementById("input");\njsshell._out = document.getElementById("output");\n\njsshell.initTarget();\n\njsshell.recalculateInputHeight();\njsshell.refocus();\n\n</script>\n
<!--{{{-->\n<div class='header'>\n<div class='headerShadow'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;\n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;\n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n</div>\n<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>\n<div id='sidebar'>\n<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\n<div id='ZiddlyFormats' refresh='content' tiddler='ZiddlyFormats'></div>\n<div id='ZiddlyPowered' refresh='content' tiddler='ZiddlyPowered'></div>\n</div>\n<div id='displayArea'>\n<div id='messageArea'></div>\n<div id='tiddlerDisplay'></div>\n</div>\n<!--}}}-->\n
In the [[Zope]] Management Interface, add a "Site Error Log" to the root level of your Zope instance. This will allow you to find the cause of errors.
The [[davfs|http://dav.sourceforge.net/]] project allows you to mount any WebDAV-based site as if it were a local filesystem. Once installed, you can run:\n{{{\nmount -t davfs http://your.site.here/tiddlers /tiddler_path\n}}}\nwhere {{{http://your.site.here}}} should be replaced with the URL you normally use to access your ZiddlyWiki. The path {{{/tiddler_path}}} can be any directory on your system, which will appear as a directory full of your tiddlers once mounted. Note that this will require root privileges. You can add this to your {{{/etc/fstab}}} file with the option {{{user}}} to allow your tiddlers to be mounted without root privileges.\n\nOnce mounted, you can simply edit the files there. When you save in your editor, the changes are transmitted to the server, and will automatically appear in your ZiddlyWiki.
[[Version 2.0.11.4]] has been released.\n\n[[Version 2.0.11.3]] has been released.\n\n[[Version 2.0.11.2]] has been released.\n\nWith this version the maintainership has changed. Tim Morgan has retired and development has merged with the main TiddlyWiki systems at http://trac.tiddlywiki.org. We are thankful to retain hosting by [[Zettai|http://zettai.net]].\n
//a macro that shows currently-active users (based on current locks)//\n//only works with ZiddlyWiki 2.0.0.9+//\n//To use: {{{<<activeUsers>>}}}//\n\n{{{\nconfig.macros.activeUsers = {\n handler: function(place,macroName,params) {\n createTiddlyElement(place,'div','zw-current-users-list');\n ajax.get(zw.get_url(false)+"?action=get_locks", config.macros.activeUsers.update);\n setInterval('ajax.get(zw.get_url(false)+"?action=get_locks", config.macros.activeUsers.update)', 60000);\n },\n update: function(r) {\n var users = r.split('\sn');\n var elms = document.getElementsByTagName('div');\n if(r=='') {\n $('zw-current-users-list').innerHTML = '<em>none</em>';\n } else {\n $('zw-current-users-list').innerHTML = '';\n for(var j=0; j<users.length; j++) {\n createTiddlyLink(createTiddlyElement($('zw-current-users-list'), 'div'), users[j], true);\n }\n }\n }\n};\n}}}
{{{\n// allows one to get a list of tiddlers with <<list tag tagname>>\n// <<list tag tagname ExcludeTiddler>> will exclude named tiddler\n// <<list tag tag1+tag2+tag3>> will list tiddlers with all 3 tags\n// <<list tag tag1-tag2>> will list tag1 tiddlers without tag2\nconfig.macros.list.tag = {\n handler: function(params) {\n var tags=params[1].split(/[\s+\s-]/);\n var t=[];\n for(var i=0;i<tags.length;i++)\n t.push(store.reverseLookup("tags",tags[i],true,"title"));\n while(t.length>1){\n var i=params[1].indexOf('-')>-1 ? subtract(t[0],t[1]) : intersect(t[0],t[1]);\n if(t.length>2)t=[i].concat(t.slice(2));\n else t=[i];\n }\n var list=[];\n var t=t[0];\n for(var i=0;i<t.length;i++)\n if(!params[2]||t[i].title!=params[2]) list.push(t[i]);\n return list;\n }\n}\nfunction intersect(set1,set2) {\n var set=[];\n for(var i=0;i<set1.length;i++)\n for(var j=0;j<set2.length;j++)\n if(set1[i]==set2[j])\n set.push(set1[i]);\n return set;\n};\nfunction subtract(set1,set2) {\n var set=[];\n for(var i=0;i<set1.length;i++) {\n var f=false;\n for(var j=0;j<set2.length;j++)\n if(set1[i]==set2[j])f=true;\n if(!f)set.push(set1[i]);\n }\n return set;\n};\n}}}
Tiddlers tagged as "private" (see PrivateTiddlers) won't show up until someone logs on. It turns out that these tiddlers can be hidden within other tiddlers using the [[Tiddler Insertion Technique|http://www.tiddlywiki.com/#Macros]], and the content of the private tiddler will "pop up" on login. This can also be used to add additional info for editors within any other relevant Tiddler, including the MainMenu. The result can be a fairly different interface for edit-role visitors compared to visitors just browsing...\n\nSee how this tiddler behaves differently before and after logging in!\n\n<<tiddler PrivateLoginMessage>>
/***\n|''Name:''|Plugin: ZiddlyWiki|\n|''Description:''|Client-side component of the ZiddlyWiki server-side for TiddlyWiki|\n|''Version:''|1.0.0|\n|''Date:''|Sep 30, 2006|\n|''Source:''|http://ziddlywiki.com|\n|''Author:''|BobMcElrath|\n|''Email:''|my first name at my last name dot org|\n|''License:''|[[GPL open source license|http://www.gnu.org/licenses/gpl.html]]|\n|''~CoreVersion:''|2.1.0|\n!Description\nThis plugin is useful only in conjunction with the ZiddlyWiki server-side for\nTiddlyWiki. This plugin is automatically added to any TiddlyWiki downloaded\nfrom a ZiddlyWiki server, and should not be added by hand to your TiddlyWiki.\n\nIf you want to use the ZiddlyWiki server, install that first, and you will\nautomatically get this plugin.\n!My Server\nThis ZiddlyWiki lives at: \n{{{\n http://zw.mcelrath.org/ziddlywiki.com\n}}}\n!API\n{{{\n action=get\n}}}\n!Code\n***/\n//{{{\n// Place to store my junk\nif(typeof zw == "undefined") var zw = {};\nconfig.options.checkUnsavedChanges = false;\nconfig.options.confirmExit = false;\n//zw.ieurl = (navigator.appVersion.indexOf('MSIE') > -1) ? 'ie=1&' : '';\nzw.editingTiddlers = {};\nzw.dirty = false; // flag for when ZW was unable to save something\nzw.serverUrl = "http://zw.mcelrath.org/ziddlywiki.com";\n\nconfig.messages.loginToEdit = 'You must be logged in to make changes. Viewing source instead.';\nconfig.messages.errorDeleting = 'An error has occurred. Review your Zope error log for details.';\nconfig.messages.errorSaving = 'An error has occurred. Review your Zope error log for details. If you navigate away from this page now, you will lose your changes.';\nconfig.messages.protectedTiddler = 'You are not allowed to edit here. Click OK to view the source.';\nconfig.messages.lockedTiddler = 'This tiddler is currently being edited by %s. Please try again in a few minutes.';\nconfig.messages.lockedTiddlerYou = 'This tiddler is currently locked by you. Would you like to edit anyway?';\nconfig.messages.viewRevisionTooltip = 'View this revision.';\nconfig.messages.exportLinkLabel = 'export to file';\nconfig.messages.exportLinkPrompt = 'Export to a TiddlyWiki file';\nconfig.messages.importLinkLabel = 'import from file';\nconfig.messages.importLinkPrompt = 'Import from a TiddlyWiki file';\nconfig.messages.unsavedChangesWarning = 'Something has gone wrong and ZiddlyWiki was unable to save all changes to the server.\snIf you navigate away from this page, those changes will be lost.\snPress OK to save a backup to a local file.';\n\nconfig.views.wikified.toolbarRevisions = {text: "revisions", tooltip: "View another revision of this tiddler", popupNone: "No revisions"};\n\n// Shadow tiddlers that are protected\nconfig.protectedTiddlers = ['DefaultTiddlers', 'MainMenu'];\n\nconfig.replaceBodyCharacters = [\n [/‘/g, "'"],\n [/’/g, "'"],\n [/“/g, '"'],\n [/”/g, '"'],\n [/…/g, '...'],\n [/–/g, ' -- ']\n];\n\nconfig.macros.login = {\n label: 'login',\n prompt: 'Log into the system',\n sizeTextbox: 15,\n // FIXME onmouseover, etc... do these cause a problem? Add (?!onmouseover|onmouseout...)\n innerHTMLSafe: /^<div( ([a-zA-Z0-9_]+)="[^"]*")+>[^<>]*<\s/div>$/,\n handler: function(place) {\n if(zw.loggedIn) {\n var link = createTiddlyLink(place, zw.username, true);\n if(location.protocol == "file:") {\n link.innerHTML = zw.username + ' (offline)';\n } else {\n link.innerHTML = zw.username + ' (logged in)';\n createTiddlyButton(place, "logout", "Log out of the system", this.doLogout);\n }\n } else {\n // FIXME Only make login form if cookie-based login are enabled.\n var form = document.createElement("form");\n form.action = "?action=get&title=ZiddlyStatus";\n var u = createTiddlyElement(form, "input", "zw_username");\n u.value = "YourName";\n u.onclick = this.clearInput;\n u.size = this.sizeTextbox;\n u.onkeypress = this.enterSubmit;\n u.name = "__ac_name";\n var p = createTiddlyElement(form, "input", "zw_password");\n p.value = "password";\n p.size = this.sizeTextbox;\n p.onclick = this.clearInput;\n p.onkeypress = this.enterSubmit;\n p.name = "__ac_password";\n place.appendChild(form);\n createTiddlyButton(place,this.label,this.prompt,this.doLogin);\n }\n },\n clearInput: function(e) {\n var u = document.getElementById("zw_username");\n var p = document.getElementById("zw_password");\n if((e.target == u || e.target == p) && p.type != "password") { \n u.value = ''; \n p.value=''; \n p.type = "password";\n }\n },\n enterSubmit: function(e) {\n if(e.keyCode == 13 || e.keyCode == 10) config.macros.login.doLogin(e);\n },\n doLogin: function(e) {\n clearMessage();\n displayMessage('Logging in...');\n var u = document.getElementById("zw_username");\n var p = document.getElementById("zw_password");\n zw.loggingIn = true;\n ajax.post(zw.serverUrl.replace("http://","http://"+u.value+":"+p.value+"@")\n ,zw.addTiddler,\n "action=get&title=ZiddlyStatus&__ac_name="+u.value+"&__ac_password="+p.value);\n },\n doLogout: function(e) {\n clearMessage();\n displayMessage('Logging out...');\n zw.loggingIn=false;\n // FIXME this will fail if " " is a valid username\n ajax.post(zw.serverUrl.replace("http://","http:// :@")\n ,zw.addTiddler,\n "action=get&title=ZiddlyStatus&__ac_name=&__ac_password=");\n },\n statusChange: function() {\n var oldreadOnly = readOnly;\n config.options.chkHttpReadOnly = (zw.loggedIn || zw.anonEdit || location.protocol == "file:") ? false:true;\n readOnly = !zw.loggedIn;\n // Check for new tiddlers\n var numtofetch = 0;\n var missingtiddlers = "";\n for(var t in zw.tiddlerList) {\n if(!store.fetchTiddler(t.htmlDecode())) {\n numtofetch++;\n missingtiddlers += "\sn" + t;\n }\n }\n var fetched = 0;\n this.fetchlist = [];\n if(zw.tiddlerList.length == 0) {\n clearMessage();\n } else for(var t in zw.tiddlerList) {\n if(!store.fetchTiddler(t.htmlDecode())) {\n var callback = zw.addTiddler;\n this.fetchlist.push(t);\n if(++fetched == numtofetch) \n callback = config.macros.login.addLastTiddler;\n ajax.get('?action=get&title=' + encodeURIComponent(t.htmlDecode())\n + "&" + zw.no_cache(), callback)\n }\n }\n if(oldreadOnly != readOnly || numtofetch == 0) {\n refreshDisplay(["ViewTemplate", "EditTemplate"]);\n story.refreshAllTiddlers();\n refreshAll();\n }\n },\n doneLoginout: function() {\n var evalme = store.fetchTiddler("ZiddlyStatus").text;\n window.eval(evalme);\n readOnly = !zw.loggedIn;\n store.notify(["ZiddlyStatus"], true);\n if(!zw.loggedIn && zw.loggingIn) { // still not logged in.\n clearMessage();\n displayMessage("Authentication failed. Did you type your username and password correctly?");\n }\n if(!zw.loggingIn || (zw.loggedIn && zw.loggingIn)) clearMessage();\n return true;\n },\n addLastTiddler: function(str,status) {\n zw.addTiddler(str,status);\n refreshAll(); // Just redraw everything.\n }\n};\n// This causes our doneLogin method above to be called on startup.\nstore.addNotification("ZiddlyStatus", config.macros.login.statusChange);\n\n// Dynamically load a tiddler\nzw.loadTiddler = function(t) {\n var str = ajax.gets('?action=get&title=' + encodeURIComponent(t.htmlDecode())\n + "&" + zw.no_cache());\n return zw.addTiddler(str, 200);\n}\n\nzw.addTiddler = function(str,status) {\n var tiddler = new Tiddler();\n var d = document.createElement("div");\n if(!str.match(config.macros.login.innerHTMLSafe)) { \n if(!confirm("This tiddler appears to contain HTML and may be dangerous\sn\sn"+str)) \n return tiddler;\n }\n d.innerHTML = str; // FIXME dangerous -- response could contain <script>\n var title = store.getLoader().getTitle(store, d.firstChild);\n if(status == 404) { // not found\n store.zw_removeTiddler(title);\n } else if(status == 200) { // okay\n tiddler = store.getLoader().internalizeTiddler(store, tiddler, title, d.firstChild);\n tiddler.changed();\n store.addTiddler(tiddler);\n if(typeof store.getValue(title, "oldtitle") != "undefined") {\n store.setValue(title, "renamedSubTitle", \n "(renamed from "+store.getValue(title, "oldtitle")+")");\n }\n }\n if(tiddler.title == "ZiddlyStatus")\n config.macros.login.doneLoginout();\n refreshDisplay(title);\n return tiddler;\n}\n\nTiddler.prototype.getSubtitle = function() {\n var theModifier = this.modifier;\n if(!theModifier)\n theModifier = config.messages.subtitleUnknown;\n var theModified = this.modified;\n if(theModified)\n theModified = theModified.toLocaleString();\n else\n theModified = config.messages.subtitleUnknown;\n return(config.messages.tiddlerLinkTooltip.format([this.title,theModifier,\ntheModified]));\n\n}\n\nconfig.macros.ziddlyversion = {\n handler: function(place) {\n createTiddlyElement(place,"span",null,null,version.major + "." \n + version.minor + "." + version.revision \n + (version.beta ? "(b" + version.beta + ")" : "") + "." \n + version.extensions.ZiddlyWiki);\n }\n};\n\nconfig.macros.exportLink = {\n label: config.messages.exportLinkLabel,\n prompt: config.messages.exportLinkPrompt,\n handler: function(place) { \n if(location.protocol == "file:") {\n this.label = config.macros.saveChanges.label;\n this.prompt = config.macros.saveChanges.prompt;\n this.accessKey = config.macros.saveChanges.accessKey;\n config.macros.saveChanges.handler(place);\n } else {\n createTiddlyButton(place,this.label,this.prompt,function(){\n location.href='?action=export';return false;\n });\n }\n }\n};\n\nconfig.macros.importLink = {\n label: config.messages.importLinkLabel,\n prompt: config.messages.importLinkPrompt,\n handler: function(place) {\n if(zw.loggedIn || zw.anonEdit) {\n createTiddlyButton(place,this.label,this.prompt,function(){\n displayTiddler(null, "ImportTiddlers");\n });\n }\n }\n};\n\nTiddlyWiki.prototype.zw_removeTiddler = TiddlyWiki.prototype.removeTiddler;\nTiddlyWiki.prototype.removeTiddler = function(title) {\n displayMessage("Deleting '"+title+"' on server...");\n ajax.post(zw.serverUrl, zw.addTiddler, 'action=delete&title=' + encodeURIComponent(title) + '&' + zw.no_cache());\n return true;\n};\n\nTiddlyWiki.prototype.zw_saveTiddler = TiddlyWiki.prototype.saveTiddler;\nTiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags) {\n displayMessage("Saving '"+title+"'...");\n newBody = replaceBodyCharacters(newBody);\n var tiddler = this.zw_saveTiddler(title,newTitle,newBody,modifier,modified,tags);\n var callback = function(r,status){\n var newtiddler = zw.addTiddler(r,status);\n if(!newtiddler) {\n alert("ZiddlyWiki error: The tiddler '"+title+"' that I just tried to save\sn"\n +"doesn't exist after the save! Response ("+status+") was: \sn"+r);\n zw.dirty = true;\n } else if(newtiddler.escapeLineBreaks().htmlEncode() != tiddler.escapeLineBreaks().htmlEncode()) {\n alert("ZiddlyWiki error: Saved tiddler '"+title+"' is not the same as what was just saved."\n +"\sn-------------------before---------------------\sn"+tiddler.escapeLineBreaks().htmlEncode()\n +"\sn-------------------after----------------------\sn"+newtiddler.escapeLineBreaks().htmlEncode()\n );\n zw.dirty = true;\n }\n };\n// FIXME by using async ajax here, a reload timeout may come between the save\n// and the callback's return, which causes the tiddler to be double-rendered.\n ajax.post(zw.serverUrl, callback, 'action=save&oldtitle=' + encodeURIComponent(title) + '&title=' \n + encodeURIComponent(newTitle) + '&body=' + encodeURIComponent(newBody) + '&tags=' \n + encodeURIComponent(tags) + '&modified=' \n + encodeURIComponent((modified||store.fetchTiddler(title).modified).convertToYYYYMMDDHHMM()) \n + '&' + zw.no_cache());\n clearMessage();\n return tiddler;\n};\n\nfunction replaceBodyCharacters(body) {\n var chars = config.replaceBodyCharacters;\n for(var i=0; i<chars.length; i++) {\n body = body.replace(chars[i][0], chars[i][1]);\n }\n return body;\n};\n\nzw.no_cache = function() {return new String((new Date()).getTime())};\n\nconfig.commands.revisions = {\n text: config.views.wikified.toolbarRevisions.text,\n tooltip: config.views.wikified.toolbarRevisions.tooltip,\n popupNone: config.views.wikified.toolbarRevisions.popupNone,\n hideShadow: true,\n handler: function(event,src,title) {\n var popup = Popup.create(src);\n Popup.show(popup,false);\n var callback = function(r,status) {\n if(popup) {\n if(status != 200) {\n createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),\n config.views.wikified.toolbarRevisions.popupNone);\n } else {\n var revs = r.split('\sn');\n for(var i=0; i<revs.length; i++) {\n var parts = revs[i].split(' ');\n if(parts.length>1) {\n var modified = Date.convertFromYYYYMMDDHHMM(parts[0]);\n var key = parts[1];\n var modifier = parts[2];\n var button = createTiddlyButton(createTiddlyElement(popup,"li"), modified.toLocaleString() +" "+ modifier, \n config.messages.viewRevisionTooltip, \n function(){\n displayTiddlerRevision(this.getAttribute('tiddlerTitle'), \n this.getAttribute('revision'), this); \n return false;\n }, 'tiddlyLinkExisting tiddlyLink');\n button.setAttribute('tiddlerTitle', title);\n button.setAttribute('revision', key);\n var t = store.fetchTiddler(title);\n if(!t) alert("Attempt to find revisions for non-existant tiddler '"+title+"'!");\n if(t && (store.getValue(t, 'revision') == key))\n button.className = 'revisionCurrent';\n if(i == 0)\n this.latestRevision = key;\n }\n }\n }\n }\n };\n ajax.get('?action=get_revisions&title=' + encodeURIComponent(title.htmlDecode()) + '&' + zw.no_cache(), callback);\n event.cancelBubble = true;\n if (event.stopPropagation) event.stopPropagation();\n return true;\n }\n}\n\nfunction displayTiddlerRevision(title, revision, src, updateTimeline) {\n var tiddler = store.fetchTiddler(title);\n// We already have the latest version\n if(tiddler && store.getValue(tiddler, 'revision') == revision) return;\n displayMessage("Loading revision information for '"+title+"'...");\n revision = revision ? '&revision=' + revision : '';\n ajax.get('?action=get&title=' + encodeURIComponent(title.htmlDecode()) + revision \n + '&' + zw.no_cache(), displayTiddlerRevisionCallback)\n};\n\nfunction displayTiddlerRevisionCallback(str,status) {\n store.suspendNotifications(); // To prevent multiple redraws\n var tiddler = zw.addTiddler(str,status);\n store.setValue(tiddler.title, "historicalSubTitle", "");\n if(tiddler.tags.contains('deleted'))\n store.setValue(tiddler.title, "historicalSubTitle", \n store.getValue(tiddler.title, "historicalSubTitle")+" (deleted)");\n if(latestRevision != store.getValue(tiddler.title, "revision"))\n store.setValue(tiddler.title, "historicalSubTitle", \n store.getValue(tiddler.title, "historicalSubTitle")+" (historical revision)");\n store.setValue(tiddler.title, "latestRevision", latestRevision);\n story.refreshTiddler(tiddler.title, DEFAULT_VIEW_TEMPLATE, true);\n store.resumeNotifications();\n clearMessage();\n}\n\nTiddler.prototype.isReadOnly = function() {\n if(store.getValue(this.title, "readonly") == "true") return true;\n if(zw.isAdmin) return false;\n if(zw.loggedIn && this.modifier == zw.username) return false;\n if(location.protocol == "file:") return false;\n return isProtectedTiddler(this.title) || !(zw.anonEdit || zw.loggedIn);\n};\n\n// Add the protected tag to tiddlers in config.protectedTiddlers\nTiddler.prototype.zw_set = Tiddler.prototype.set;\nTiddler.prototype.set = function(title,text,modifier,modified,tags,created) {\n if(!tags) tags = [];\n if(typeof tags == "string") tags = tags.readBracketedList();\n if(!store.tiddlerExists(title) && store.isShadowTiddler(title)) {\n for(var i=0;i<config.protectedTiddlers.length;i++) {\n if(config.protectedTiddlers[i] == title) {\n tags.push('protected');\n break;\n }\n }\n }\n return this.zw_set(title, text, modifier, modified, tags, created);\n}\n\nconfig.commands.editTiddler.zw_handler = config.commands.editTiddler.handler;\nconfig.commands.editTiddler.handler = function(event,src,title) {\n if(readOnly) {\n this.zw_handler(event,src,title);\n } else {\n displayMessage("Loading '"+title+"'...");\n var obj = this;\n var callback = function(r,status) {\n clearMessage();\n if(status == 404) { // doesn't exist (might be a shadow tiddler)\n zw.editingTiddlers[title] = true;\n obj.zw_handler(event,src,title);\n } else if(status == 200) {\n var tiddler = zw.addTiddler(r,status);\n if(tiddler.tags.indexOf('deleted') != -1) // Remove the deleted tag on edit\n tiddler.tags.splice(tiddler.tags.indexOf('deleted'),1);\n zw.editingTiddlers[tiddler.title] = true;\n obj.zw_handler(event,src,tiddler.title);\n } else if(status == 503) { // "Temporarily Unavailable" Conflict\n if(r == zw.username) {\n if(confirm(config.messages.lockedTiddlerYou)) {\n var str = ajax.gets('?action=unlock&title=' + encodeURIComponent(title)\n + "&" + zw.no_cache());\n zw.addTiddler(str, 200);\n return obj.handler(event,src,title);\n }\n } else {\n alert(config.messages.lockedTiddler.replace(/%s/g, r));\n }\n } else if(status == 403) {\n // Lock failed, we must not be logged in, or something changed underneath us.\n zw.loggedIn = false;\n zw.isAdmin = false;\n readOnly = true;\n zw.loadTiddler("ZiddlyStatus");\n //refreshDisplay(["SideBarOptions","ViewTemplate", "EditTemplate"]);\n //story.refreshAllTiddlers();\n alert(config.messages.loginToEdit);\n config.commands.editTiddler.zw_handler(event,src,title);\n } else {\n alert("Server returned a response I don't understand:\sn\sn"+k);\n }\n };\n var rev = "";\n if(store.getValue(title, "latestRevision") != "undefined")\n rev = "revision="+store.getValue(title, "revision");\n ajax.post(zw.serverUrl, callback, 'action=lock&title=' + encodeURIComponent(title) + '&' + rev + '&' + zw.no_cache());\n }\n return false;\n};\n\nconfig.commands.saveTiddler.zw_handler = config.commands.saveTiddler.handler;\nconfig.commands.saveTiddler.handler = function(event,src,title) {\n if(zw.isAdmin \n || (zw.loggedIn || zw.anonEdit) && !isProtectedTiddler(title)\n || (isProtectedTiddler(title) && zw.loggedIn && this.modifier == zw.username)) {\n zw.editingTiddlers[title] = false;\n return this.zw_handler(event,src,title);\n } else {\n config.commands.cancelTiddler.zw_handler(null,null,title);\n }\n return false;\n};\n\nconfig.commands.deleteTiddler.zw_handler = config.commands.deleteTiddler.handler;\nconfig.commands.deleteTiddler.handler = function(event,src,title) {\n if(zw.isAdmin \n || (zw.loggedIn || zw.anonEdit) && !isProtectedTiddler(title)\n || (isProtectedTiddler(title) && zw.loggedIn && this.modifier == zw.username)) {\n zw.editingTiddlers[title] = false;\n return this.zw_handler(event,src,title);\n } else {\n config.commands.cancelTiddler.zw_handler(null,null,title);\n }\n return false;\n};\n\nconfig.commands.cancelTiddler.zw_handler = config.commands.cancelTiddler.handler;\nconfig.commands.cancelTiddler.handler = function(event,src,title) {\n if(!config.options.chkHttpReadOnly) {\n if(zw.editingTiddlers[title]) {\n var str = ajax.gets('?action=unlock&title=' + encodeURIComponent(title) + "&" + zw.no_cache());\n zw.addTiddler(str, 200);\n }\n zw.editingTiddlers[title] = false;\n }\n return this.zw_handler(event,src,title);\n};\n\nfunction isProtectedTiddler(title) {\n var tiddler = store.fetchTiddler(title);\n if(!tiddler) { // Must be a shadow\n for(var i=0;i<config.protectedTiddlers.length;i++) {\n if(config.protectedTiddlers[i] == title) return true;\n }\n }\n if(tiddler && tiddler.tags) {\n for(var i=0;i<tiddler.tags.length;i++) {\n if(tiddler.tags[i] == 'protected') return true;\n }\n }\n return false;\n};\n\nzw.refresh_count = 0;\nzw.refresh_tiddlers = function() {\n zw.refresh_count++;\n if(zw.refresh_count > 30) { // thirty minutes\n clearInterval(zw.refresh_interval_id);\n } else {\n ajax.get(zw.serverUrl + '?action=refresh&latest=' + zw.latestTiddler, zw.refresh_tiddlers_callback);\n }\n};\n\n// If there are unsaved changes, force the user to confirm before exitting\nfunction confirmExit()\n{\n hadConfirmExit = true;\n if(zw.dirty) return config.messages.confirmExit;\n}\n\n// Give the user a chance to save changes before exitting\nfunction checkUnsavedChanges()\n{\n if(zw.dirty && window.hadConfirmExit === false)\n {\n if(confirm(config.messages.unsavedChangesWarning))\n saveChanges();\n }\n}\n\nTiddler.prototype.isReadOnly = function() {\n return readOnly || store.getValue(this.title, "readonly");\n}\n\n// Receives a list of updated tiddler [timestamp, [title, modified, revision], ...]\n// If TW supports higher resolution modification stamps (currently: 1 minute) we can use\n// that as an identifier instead of revision\nzw.refresh_tiddlers_callback = function(tiddlers) {\n if(tiddlers == '') return;\n tiddlers = tiddlers.split('\sn\sn');\n zw.latestTiddler = parseInt(tiddlers[0]);\n for(var i=1; i<tiddlers.length; i++) {\n var l = tiddlers[i].split('\sn'); // [title, modified, revision]\n if(!zw.editingTiddlers[l[0]]) // FIXME if it's being edited and we just found out someone else modified it, we should issue a warning.\n displayTiddlerRevision(l[0], l[2], null, true);\n }\n};\n\nif(location.protocol != "file:")\n zw.refresh_interval_id = setInterval('zw.refresh_tiddlers()', 60000); // refresh every minute\n\n// mini/ajax.js - http://timmorgan.org/mini\n\nfunction $(e){if(typeof e=='string')e=document.getElementById(e);return e};\nfunction collect(a,f){var n=[];for(var i=0;i<a.length;i++){var v=f(a[i]);if(v!=null)n.push(v)}return n};\n\nvar ajax={};\najax.x=function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}};\najax.serialize=function(f){var g=function(n){return f.getElementsByTagName(n)};var nv=function(e){if(e.name)return encodeURIComponent(e.name)+'='+encodeURIComponent(e.value);else return ''};var i=collect(g('input'),function(i){if((i.type!='radio'&&i.type!='checkbox')||i.checked)return nv(i)});var s=collect(g('select'),nv);\nvar t=collect(g('textarea'),nv);return i.concat(s).concat(t).join('&');};\najax.send=function(u,f,m,a){var x=ajax.x();x.open(m,u,true);x.onreadystatechange=function(){if(x.readyState==4)f(x.responseText,x.status,x.statusText)};if(m=='POST')x.setRequestHeader('Content-type','application/x-www-form-urlencoded');x.send(a)};\najax.get=function(url,func){ajax.send(url,func,'GET')};\najax.gets=function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText};\najax.post=function(url,func,args){ajax.send(url,func,'POST',args)};\najax.posts=function(url,args){var x=ajax.x();x.open('POST',url,false);x.setRequestHeader('Content-type','application/x-www-form-urlencoded');x.send(args);return x.responseText};\najax.update=function(url,elm){var e=$(elm);var f=function(r){e.innerHTML=r};ajax.get(url,f)};\najax.submit=function(url,elm,frm){var e=$(elm);var f=function(r){e.innerHTML=r};ajax.post(url,f,ajax.serialize(frm))};\n\n//if(window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1)\n//window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n//window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserWrite");\n//window.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n\n//}}}\n
//Style Sheet for TW 2.0.0+ and adapations.//\n//Images are hosted at ImageShack.//\n//To use, just copy this tiddler and tag it systemConfig in your TW.//\n\n//This stylesheet does not conform to the usual TW way of doing things. Does someone want to convert it?\n\n{{{\n/*\nimg_bg = 'http://img328.imageshack.us/img328/9691/bg0fu.gif';\nimg_bg2 = 'http://img425.imageshack.us/img425/5238/bg21hi.gif';\nimg_bgs = 'http://img425.imageshack.us/img425/5997/bgs5hf.gif';\nvar img_ref = 'http://img159.imageshack.us/img159/1260/references1ca.gif';\nvar img_copy = 'http://img234.imageshack.us/img234/8866/copy0au.gif';\nvar img_jump = 'http://img234.imageshack.us/img234/7558/jump2sg.gif';\nvar img_del = 'http://img234.imageshack.us/img234/9875/delete0lm.gif';\nvar img_close = 'http://img234.imageshack.us/img234/1415/close7og.gif';\nvar img_edit = 'http://img234.imageshack.us/img234/775/edit8vi.gif';\nvar img_rev = 'http://img234.imageshack.us/img234/9517/history2ed.gif';\nvar img_perm = 'http://img234.imageshack.us/img234/5416/permalink6by.gif';\nvar img_save = 'http://img234.imageshack.us/img234/5746/save7ux.gif';\nvar img_cancel = 'http://img234.imageshack.us/img234/827/cancel2mv.gif';\nvar img_close_others = 'http://img234.imageshack.us/img234/7136/closeothers9lt.gif';\n*/\nimg_bg = '/images/bg0fu.gif';\nimg_bg2 = '/images/bg21hi.gif';\nimg_bgs = '/images/bgs5hf.gif';\nvar img_ref = '/images/references1ca.gif';\nvar img_copy = '/images/copy0au.gif';\nvar img_jump = '/images/jump2sg.gif';\nvar img_del = '/images/delete0lm.gif';\nvar img_close = '/images/close7og.gif';\nvar img_edit = '/images/edit8vi.gif';\nvar img_rev = '/images/history2ed.gif';\nvar img_perm = '/images/permalink6by.gif';\nvar img_save = '/images/save7ux.gif';\nvar img_cancel = '/images/cancel2mv.gif';\nvar img_close_others = '/images/closeothers9lt.gif';\n\n// improved to handle images\n/*\n_createTiddlyButton = createTiddlyButton;\ncreateTiddlyButton = function(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey) {\n var button = _createTiddlyButton(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey);\n if(theText && theText.match(/^<img/)) button.innerHTML = theText;\n return button;\n};\n*/\nconfig.shadowTiddlers.StyleSheet = 'body{font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; background:transparent url('+img_bg2+'); color:#fff;} .header{background-image:url('+img_bg+'); height: 22px; padding:5px; font-size:1.1em; font-weight:bold; color:#9f6; overflow:hidden;} .header .tiddlyLink{color:#9f6; text-decoration:none; font-size:1.1em;} #SiteSubtitle{font-weight:normal;font-size:0.9em;color:#9f6;} #SiteSubtitle .tiddlyLink{font-size:0.9em;color:#9f6;} #sitetitlebg{background:transparent url('+img_bgs+') repeat-x; height:15px;} .viewer pre{color:#666;} .button{border:none;color:#ff3;} a:hover{color:#252d93;} .tagged{background-color:transparent;} .listTitle,.tagged .listTitle{color:#fff;} .button:hover{background-color:#ff3;border:none;} .popup .tiddlyLink, #popup .tiddlyLink, #popup *{color:#ff3;} .popup .revisionCurrent, #popup .revisionCurrent{color:#ff3;} .tiddler .title{border-bottom:1px solid #390} #displayArea{margin-top:0px;} .tiddler{margin-top:0px;} #mainMenu{margin-top:20px;} #sidebar{margin-top:20px;} .tiddler .title{font-size:2em; margin-bottom:1px;} .tiddler .toolbar{width:175px; float:right; margin-top:5px;} h1,h2,h3,h4,h5,h6{background-color:transparent; margin-bottom:0px; margin-top:0px;} .viewer pre { color: #fff; background-color: #229; border: 1px solid #00c; }';\n\n//config.shadowTiddlers.StyleSheetColors = config.shadowTiddlers.StyleSheetColors.replace(/#703/g, '#9f6').replace(/#04b/g, '#ff3').replace(/#866/g, '#990').replace(/#8cf/g, '#3c49ed').replace(/#(eee)|(ddd)/g, '#3c49ed').replace(/#999/g, 'transparent').replace(/#18f/g, '#3c49ed');\n\nconfig.shadowTiddlers.PageTemplate = "<div class='header'>\sn<span refresh='content' tiddler='SiteTitle'></span> \sn::\sn<span refresh='content' tiddler='SiteSubtitle' id='SiteSubtitle'></span></div>\sn<div id='sitetitlebg'></div>\sn<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>\sn<div id='sidebar'>\sn<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\sn<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\sn</div>\sn<div id='displayArea'>\sn<div id='messageArea'></div>\sn<div id='tiddlerDisplay'></div>\sn</div>";\n\nconfig.commands.editTiddler.text = '<img src="' + img_edit + '"/>';\nconfig.commands.editTiddler.readOnlyText = '<img src="' + img_edit + '"/>';\nconfig.commands.closeTiddler.text = '<img src="' + img_close + '"/>';\nconfig.commands.closeOthers.text = '<img src="' + img_close_others + '"/>';\nconfig.commands.saveTiddler.text = '<img src="' + img_save + '"/>';\nconfig.commands.cancelTiddler.text = '<img src="' + img_cancel + '"/>';\nconfig.commands.deleteTiddler.text = '<img src="' + img_del + '"/>';\nconfig.commands.permalink.text = '<img src="' + img_perm + '"/>';\nconfig.commands.references.text = '<img src="' + img_ref + '"/>';\nconfig.commands.jump.text = '<img src="' + img_jump + '"/>';\nif(config.commands.revisions)\n config.commands.revisions.text = '<img src="' + img_rev + '"/>';\nif(config.commands.copyTiddler)\n config.commands.copyTiddler.text = '<img src="' + img_copy + '"/>';\n}}}\n
* Allow save to not pass zope id, and recompute it from title.\n* Fix race condition when saving.\n* Fix javascript error on editing shadow tiddlers.\n
<<tiddler TimMorgan>>
* If chkHttpReadOnly, do not attempt to unlock tiddlers on 'view'\n* Fix escaping to match the core. (WRT HTML entities &amp;quot;, &amp;lt;, &amp;gt;, &amp;amp;, <, >) WARNING -- this will require you to convert your tiddlers in Zope. A new script is provided for this: ZiddlyWiki/upgrade. Copy it to the location of your 'tiddlers' folder and run it like http://your.site/TiddlySite/upgrade. Do this only ONCE for each tiddlywiki site you're running, then delete the upgrade script.\n* When a tiddler tagged with 'private' is saved, the Zope permissions will be set to make it not accessable through http://your.site/TiddlySite/tiddlers/private_tiddler The above upgrade script will also add these permissions to any existing private tiddlers.\n* Set revisionKey on get and save (prevents ZiddlyWiki from reloading the tiddler you just edited).\n* Perform a redirect on save so that the user gets the revisionKey for the newly modified tiddler.\n* Remove editing locks if no changes are made.\n* Check to see if a WebDAV lock is held on tiddlers before editing.\n* Editing a tiddler that exists on the server but not in your browser will fetch the text from the server, rather than editing an empty tiddler.\n* Editing a tiddler that exists on the server but is deleted will display a message, and edit the text that is on the server. Cancelling the edit will leave it deleted.\n* Unset store.dirty after a tiddler is successfully saved, so the "Unsaved Changes" dialog isn't shown when the user leaves. This still needs some work -- it's still possible that the wiki in your browser was at some time unable to save to the server but the "Unsaved Changes" dialog won't appear.\n
ZiddlyWiki\nNews\nMajorFeatures
To get started with this blank ZiddlyWiki, you'll need to modify the following tiddlers:\n* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above\n* MainMenu: The menu (usually on the left)\n* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the ZiddlyWiki is opened\n
Because of limitations of basic HTTP auth, logging out programmatically is very very ugly and would confuse ZW users. To log out, just quit your web browser.\n\nIf you must have a logout link on your ZiddlyWiki, go to http://yourdomain.com/ZiddlyWiki/#SideBarOptions, click ''edit'', add the following code to the end, and click ''done''. But be warned; it's not pretty!\n\n{{{\n<<logout>>\n}}}\n\nDiscussion: http://ziddlywiki.com/forum/#LogoutLink
[[Zope]] provides built-in basic HTTP authentication, and ZiddlyWiki makes use of this feature to track and restrict tiddler modifications. To edit a ZiddlyWiki tiddler, you must be logged in as a user in Zope. Unless, of course, AnonymousEditing is turned on.
# Make sure your "tiddlers" folder is ''not'' inside your "~ZiddlyWiki" folder. If it is, get it out of there!\n# ''Delete'' the "~ZiddlyWiki" folder.\n# ImportZiddlyWiki.\n!Version 2.0.11.*\nThis release has some changes in the way tiddlers are stored. See [[Version 2.0.11.2]], [[Version 2.0.11.3]] and [[Version 2.0.11.4]] for details. (fixing escaping so you can edit tiddlers in the ZMI or with an external editor, and making private tiddlers inaccessable to the outside)\n\nThis will require you to convert your tiddlers in Zope. A new script is provided for this: ZiddlyWiki/upgrade. ''Make a backup copy of your {{{tiddlers}}} folder!'' Copy {{{upgrade}}} to the location of your 'tiddlers' folder and run it like http://your.site/TiddlySite/upgrade. Do this only ONCE for each tiddlywiki site you're running, then delete the upgrade script.
http://freezope.org\n\nFreeZope gives away free 5MB hosting accounts. It takes a day or two to be approved (a real person checks new accounts).\n\nCheck out the InstallScript to get ZW on your FZ!
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.9.zexp]]\n\nMajor Changes:\n* added "get_locks" action used by new ~ZW-only ActiveUsersMacro
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.8.zexp]]\n\nMajor Changes:\n* Fixed "global name '_inplacevar_' is not defined" error with newer versions of [[Zope]].
<!--{{{--> \n<link rel="alternate" type="application/rss+xml" title="RSS" href="?format=xml" /> \n<!--}}}-->
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.3.zexp]]\n\nMajor Changes:\n* Fixed improperly translated \sn when viewing older revisions.
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.2.zexp]]\n\nMajor Changes:\n* Hacked out automatic [[Zope]] <base> tag to fix IE's stylesheet problems.
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.1.zexp]]\n\nMajor Changes:\n//none//
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.7.zexp]]\n\nMajor Changes:\n* Removed the other half of the bogus revisions from the list.\n* Added cleanup code to add "modifed" date to all old-style tiddlers. This should fix quirk whereas an almost-edited tiddler will show up as having a newer "modified" date (happened on the ZiddlyWikiForum).
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.6.zexp]]\n\nMajor Changes:\n* Enhanced just-added feature to allow for editing of an older tiddler revision.\n* Cleaned up revisions list by removing half of the junk created by the new TiddlerLocks feature. Will take some thinking to get rid of the other half...
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.5.zexp]]\n\nMajor Changes:\n* Added TiddlerLocks mechanism to prevent simultaneous edits. May be a bit buggy in certain circumstances, but should be ready for a real ZW release (finally!).\n* When editing a tiddler, the server is queried for the most recent version to prevent edits being done on an old version.
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.4.zexp]]\n\nMajor Changes:\n* Fixed broken XML and YAML formats.
If you don't mind forking over a few bucks each month, paid [[Zope]] hosting by [[Zettai|http://zettai.net]] won't dissapoint. If you have a server and don't mind installing [[Zope]], read on...\n\n''Windows''\nHead over to [[zope.org|http://www.zope.org/Products/Zope]], download the Windows binary (exe) of Zope 2.x, and run it.\n\n''Linux''\nChances are good you can download, install and configure [[Zope]] 2.x with a few clicks using the native packaging software for your distribution. And there's always the install-from-source option; see [[zope.org|http://zope.org]] for that.\n\n''Mac''\n???\n\n----\n''Note:'' ZiddlyWiki is not a Zope 3.x product.
Especially when there are multiple authors on a ZW, not everyone has a sense of what can be linked-to. If the ZW or TW is structured around WikiWords, people can just use WikiWords "just in case" there's a link out there, or a link will be made down the road. But not everyone is compulsively habituated to use WikiWords, and some of us don't use them for more aesthetic reasons.\n\nSo: what you can do is to use the [[RedirectMacro|http://checkettsweb.com/styles/themes.htm#%5B%5BRedirect%20Macro%5D%5D]] to make links to important tiddlers appear even in the posts of people who don't think to make a link. Better yet, you can use [[ForEachTiddler|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin]] to set up RedirectMacro calls for the names of *all* tiddlers which have a certain tag. So, if you have tiddlers defining some key terms, and they're all tagged {{{definitions}}}, then you put the following in your MainMenu:\n{{{\n<<forEachTiddler\n where\n 'tiddler.tags.containsAny([["definitions"]])'\n write\n '"<<redirect \s""+tiddler.title+"\s" [["+tiddler.title+"]]$))\sn"'>>\n}}}
ZiddlyWiki bug reports should be entered into the [[TiddlyWiki Trac|http://trac.tiddlywiki.org/tiddlywiki]] system. When filing a new report, select {{{Component: ziddlywiki}}} so it's not confused with bugs against TiddlyWiki itself. If you don't have a Trac login, you can post a message about the bug in the [[TiddlyWikiDev|http://groups.google.com/group/TiddlyWikiDev]] google group. Bug reports with an attached patch are most likely to be noticed. See ZiddlyContributions for info on creating and contributing patches.
ZiddlyWiki can be exported to and imported from a TiddlyWiki file.\n\nTo export a ZW site, click the ''save to file'' link on the sidebar. You will be prompted to save the file locally.\n\nTo import a TiddlyWiki file into your ZW site, you must be logged in. Once logged in, click the ''update from file'' link on the sidebar. Browse for the file on your local computer. If you want ZW to delete tiddlers that exist on the server but not in the TW file, check the box labeled "Delete missing content." Now click the ''Import'' button.
Jeremy Ruston is the genius who created TiddlyWiki, the SelfContained ClientSide wiki system written in ~JavaScript, CSS, and HTML.\n\nhttp://osmosoft.com/
<<list tag versions>>
<<option chkRegExpSearch>> RegExp Search\n<<option chkCaseSensitiveSearch>> Case sensitive search\n<<option chkAnimate>> Enable animations\n<<option chkOpenInNewWindow>> Open links in new window\n<<option chkSaveEmptyTemplate>> Save empty template\n<<option chkToggleLinks>> Links close open tiddlers\n<<option chkConfirmDelete>> Confirm before deleting\n<<option chkForceMinorUpdate>> Preserve date/time on edit
To hide your ZiddlyWiki from web surfers and require visitors to log in to view it, go to the ''Security'' tab of your index_html script, scroll down to the ''View'' permission, uncheck ''Acquire'', and check ''Authenticated''. Then click ''Save Changes''.\n\nNote that you can also add the tags {{{private}}} and {{{protected}}} to your tiddlers to keep others from seeing or editing them, respectively. See PrivateTiddlers.
Based on TiddlyWiki 2.0.10\n\n[[Download here.|/versions/2.0.10.1.zexp]]
!Free?\n\nThere used to be several free Zope hosting services, but they seem to have all disappeared. If anyone knows of one, please email me (Bob McElrath) at my first name dot my last name dot org.\n\n!On Your Own Server or Paid Hosting\n\n# GetZope.\n# [[Download ZiddlyWiki|/download]].\n# ImportZiddlyWiki. (Or UpgradeZiddlyWiki)\n# Copy the {{{ZiddlyWiki/index_html}}} script to the location where you want your ZW (probably the root).\n# If you are upgrading, check UpgradeZiddlyWiki to see if there are any important extra steps.\n\nThat's it! Now point your web browser to your site and start creating tiddlers.\n----\nOptionally, you can also:\n* Make MultipleZWs (or rename your ZW)\n* HideYourZW
Select a TiddlyWiki file to import...\n\n<html><form action="http://www.ziddlywiki.com/" enctype="multipart/form-data" method="post" onsubmit="return confirm('Are you sure you want to import this file?')"><input type="hidden" name="action" value="import"/><input type="hidden" name="redirect_to" value="http://www.ziddlywiki.com/"/><input type="file" name="file"/><br/><input type="checkbox" id="keep_newest" name="keep_newest" value="yes" checked="checked"/><label for="keep_newest">Only import newer content</label><br/><input type="checkbox" id="delete_missing" name="delete_missing" value="yes"/><label for="delete_missing">Delete missing content</label><br/><input type="submit" value="Import"/></form></html>
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.12.zexp]]\n\nMajor Changes:\n* improved automatic addition of "created" date on existing tiddlers
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.11.zexp]]\n\nMajor Changes:\n* fixed another _inplacevar_ error experienced with at least one version of Zope (caused by using += in Python scripts)\n* made unlock action fail more gracefully when a tiddler doesn't exist
Based on TiddlyWiki 2.0.0\n\n[[Download here.|/versions/2.0.0.10.zexp]]\n\nMajor Changes:\n* fixed XML feed by html quoting characters in tiddler titles
Tags that have special meaning to TiddlyWiki/ZiddlyWiki:\n\n''private''\nOnly allows tiddler to be seen by logged-in users.\n\n''protected''\nOnly editable by its author or an administrator.\n\n''onlyAdmin''\nOnly allows tiddler to be seen by users with the "Manager" role. This is useful for testing out macros/plugins prior to release.\n\n''deleted''\nDeleted tiddlers are tagged with this tag rather than actually being deleted. "Deleted" tiddlers remain in the [[Zope]] object database, but don't get transfered to the client.\n\n''systemConfig''\nExecutes the tiddler body as JavaScript code. This is utilized to create macros and plugins.
Starting with [[Version 2.0.0.5]], tiddlers are &quot;locked&quot; for five minutes when the &quot;edit&quot; button is clicked. This prevents other users (or the same user in another browser) from editing the same tiddler at the same time. When the &quot;cancel&quot; or &quot;done&quot; button is clicked, the lock is released immediately. The lock expiration time can be changed by adding an integer property to your Zope instance called &quot;zw_lock_minutes&quot; with the number of your choice.\n\nStarting with [[Version 2.0.11.2]], tiddler locks respect WebDAV locks, so that you may edit tiddlers using [[Zope's External Editor|http://plope.com/software/ExternalEditor]] through the Zope Management Interface, or in any WebDAV-aware editor.
//adds a "copy" option to duplicate a tiddler//\n\n{{{\nconfig.shadowTiddlers.EditTemplate = "<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler copyTiddler deleteTiddler'></div>\sn<div class='title' macro='view title'></div>\sn<div class='editor' macro='edit title'></div>\sn<div class='editor' macro='edit text'></div>\sn<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>";\n\nconfig.commands.copyTiddler = {\n text: 'copy',\n tooltip: 'Make a copy of this tiddler',\n handler: function(event,src,title) {\n story.displayTiddler(null,title,DEFAULT_VIEW_TEMPLATE);\n var tiddler = store.fetchTiddler(title);\n var newTitle = 'Copy of ' + title;\n var newTiddler = store.createTiddler(newTitle);\n newTiddler.text = tiddler.text;\n newTiddler.tags = tiddler.tags;\n story.displayTiddler(null,newTitle,DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(newTitle,"title");\n return false;\n }\n};\n}}}
/***\n|Name|ImportTiddlersPlugin|\n|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|\n|Version|3.1.2|\n|Author|Eric Shulman - ELS Design Studios|\n|License|http://www.TiddlyTools.com/#LegalStatements <<br>>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|~CoreVersion|2.1|\n|Type|plugin|\n|Requires||\n|Overrides||\n|Description||\n\nWhen many people share and edit copies of the same TiddlyWiki document, the ability to quickly collect all these changes back into a single, updated document that can then be redistributed to the entire group is very important. It can also be very extremely helpful when moving your own tiddlers from document to document (e.g., when upgrading to the latest version of TiddlyWiki, or 'pre-loading' your favorite stylesheets into a new 'empty' TiddlyWiki document.)\n\nThis plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. Automatically add tags to imported tiddlers so they are easy to find later on. Generates a detailed report of import 'history' in ImportedTiddlers.\n!!!!!Interactive interface\n<<<\n{{{<<importTiddlers>>}}} or {{{<<importTiddlers core>>}}}\ninvokes the built-in importTiddlers macro (TW2.1.x+). If installed in documents using TW2.0.x or earlier, fallback is to use 'link' display (see below)\n\n{{{<<importTiddlers link>>}}}\ncreates "import tiddlers" link that when clicked to show/hide import control panel\n\n{{{<<importTiddlers inline>>}}}\ncreates import control panel directly in tiddler content\n\n<<importTiddlers inline>>\n\nPress ''[browse]'' to select a TiddlyWiki document file to import. You can also type in the path/filename or a remote document URL (starting with http://)and press ''[open]''. //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//\n\nSelect one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items). You can press ''[select all]'' to quickly highlight all tiddler titles in the list. Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time. When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.\n\n''select: all, new, changes, or differences''\n\nYou can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:\n>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document\n>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)\n\n''Import Tagging:''\n\nTiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document. New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.\n\n''Skip, Rename, Merge, or Replace:''\n\nWhen importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.\n\nTo bypass importing this tiddler, press ''[skip]''. To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''. Press ''[merge]'' to combine the content from both tiddlers into a single tiddler. Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.\n\n//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//\n\n''Import Report History''\n\nWhen tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.\n\nWhen the import process is completed, the ImportedTiddlers report is automatically displayed for your review. If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.\n\nIf a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.\n\nNote: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.\n\n<<<\n!!!!!non-interactive 'load tiddlers' macro\n<<<\nUseful for automated installation/update of plugins and other tiddler content.\n\n{{{<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>}}}\n<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>\n\nSyntax:\n{{{<<loadTiddlers label:text prompt:text filter source quiet confirm tag tag tag...>>}}}\n\n''label:text'' and ''prompt:text''\n>defines link text and tooltip (prompt) that can be clicked to trigger the load tiddler processing. If a label is NOT provided, then no link is created and the loadTiddlers function is performed whenever the containing tiddler is rendered.\n''filter'' (optional) determines which tiddlers will be automatically selected for importing. Use one of the following keywords:\n>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler\n>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)\n>''"