<!--{{{-->
<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 = 124205700791;\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": "893.59381.49679.46540",\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>''"tiddler:~TiddlerName"'' retrieves only the specific tiddler named in the parameter.\n>''"tag:text"'' retrieves only the tiddlers tagged with the indicated text.\n>> Note: ''if an existing tiddler is tagged with 'noReload', then it will not be overwritten'', even if the inbound tiddler has been selected by the filtering process. This allows you to make local changes to imported tiddlers while ensuring that those changes won't be lost due to automatic tiddler updates retrieved from the import source document.\n''source'' (required) is the location of the imported document. It can be either a local document path/filename in whatever format your system requires, or a remote web location (starting with "http://" or "https://")\n>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked\n''"quiet"'' (optional)\n>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc). Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified. This ensures that changes to your document cannot occur without any visible indication at all.\n''"confirm"'' (optional)\n>adds interactive confirmation. A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.\n''"tag tag tag..."'' (optional)\n>any remaining parameters are used as tag values to be added to each imported tiddler (i.e., "tag-on-import")\n<<<\n!!!!!Installation\n<<<\ncopy/paste the following tiddlers into your document:\n''ImportTiddlersPlugin'' (tagged with <<tag systemConfig>>)\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add "< < ImportTiddlers > >" macro^^\n\n''Quick Installation Tip #1:''\nIf you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.\n<<<\n!!!!!Revision History\n<<<\n''2007.02.09 [3.2.0]'' loadTiddlers: added support for "noReload" tag (prevents overwriting existing tiddler, even if inbound tiddler is newer)\n''2007.02.09 [3.1.3]'' loadTiddlers: added missing code and documentation for "newTags" handling (a feature change from long, long ago that somehow got lost!)\n''2006.11.14 [3.1.2]'' fix macro handler parameter declaration (double-pasted param list corrupts IE)\n''2006.11.13 [3.1.1]'' use apply() method to invoke hijacked core handler\n''2006.11.13 [3.1.0]'' hijack TW2.1 built-in importTiddlers.handler() so it can co-exist with the plugin interface 'panel'. Use macro without params (or use 'core' keyword) to display built-in core interface. Use new "link" param to embed "import tiddlers" link that shows floating panel when clicked. Renamed a few plugin utility functions so they don't collide with core internal functions. More code restructuring to come.\n''2006.10.12 [3.0.8]'' in readTiddlersFromHTML(), fallback to find end of store area by matching "/body" when POST-BODY-START is not present (backward compatibility for older documents)\n''2006.09.10 [3.0.7]'' in readTiddlersFromHTML(), find end of store area by matching "POST-BODY-START" instead of "/body" \n''2006.08.16 [3.0.6]'' Use higher-level store.saveTiddler() instead of store.addTiddler() to avoid conflicts with ZW and other adaptations that hijack low-level tiddler handling. Also, in CreateImportPanel(), no longer register notify to "refresh listbox after every tiddler change" (left over from old 'auto-filtered' list handling). Thanks to Bob McElrath for report/solution.\n''2006.07.29 [3.0.5]'' added noChangeMsg to loadTiddlers processing. if not 'quiet' mode, reports skipped tiddlers.\n''2006.04.18 [3.0.4]'' in loadTiddlers.handler, fixed parsing of "prompt:" param. Also, corrected parameters mismatch in loadTiddlers() callback function definition (order of params was wrong, resulting in filters NOT being applied)\n''2006.04.12 [3.0.3]'' moved many display messages to macro properties for easier L10N translations via 'lingo' definitions.\n''2006.04.12 [3.0.2]'' additional refactoring of 'core candidate' code. Proposed API now defines "loadRemoteFile()" for XMLHttpRequest processing with built in fallback for handling local filesystem access, and readTiddlersFromHTML() to process the resulting source HTML content.\n''2006.04.04 [3.0.1]'' in refreshImportList(), when using [by tags], tiddlers without tags are now included in a new "untagged" psuedo-tag list section\n''2006.04.04 [3.0.0]'' Separate non-interactive {{{<<importTiddlers...>>}}} macro functionality for incorporation into TW2.1 core and renamed as {{{<<loadTiddlers>>}}} macro. New parameters for loadTiddlers: ''label:text'' and ''prompt:text'' for link creation, ''ask'' for filename/URL, ''tag:text'' for filtering, "confirm" for accept/reject of individual inbound tiddlers. Also, ImportedTiddlers report generator output has been simplified and "importReplace/importPublic" tags and associated "force" param (which were rarely, if ever, used) has been dropped.\n''2006.03.30 [2.9.1]'' when extracting store area from remote URL, look for "</body>" instead of "</body>\sn</html>" so it will match even if the "\sn" is absent from the source.\n''2006.03.30 [2.9.0]'' added optional 'force' macro param. When present, autoImportTiddlers() bypasses the checks for importPublic and importReplace. Based on a request from Tom Otvos.\n''2006.03.28 [2.8.1]'' in loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (IE does *not* define these values, so we bypass this code)\nAlso, when extracting store area from remote URL, explicitly look for "</body>\sn</html>" to exclude any extra content that may have been added to the end of the file by hosting environments such as GeoCities. Thanks to Tom Otvos for finding these bugs and suggesting some fixes.\n''2006.02.21 [2.8.0]'' added support for "tiddler:TiddlerName" filtering parameter in auto-import processing\n''2006.02.21 [2.7.1]'' Clean up layout problems with IE. (Use tables for alignment instead of SPANs styled with float:left and float:right)\n''2006.02.21 [2.7.0]'' Added "local file" and "web server" radio buttons for selecting dynamic import source controls in ImportPanel. Default file control is replaced with URL text input field when "web server" is selected. Default remote document URL is defined in SiteURL tiddler. Also, added option for prepending SiteProxy URL as prefix to remote URL to mask cross-domain document access (requires compatible server-side script)\n''2006.02.17 [2.6.0]'' Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.\n''2006.02.16 [2.5.4]'' added checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.\n''2006.02.14 [2.5.3]'' FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()\n''2006.02.10 [2.5.2]'' corrected unintended global variable in importReport().\n''2006.02.05 [2.5.1]'' moved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2006.01.18 [2.5.0]'' added checkbox for "create a report". Default is to create/update the ImportedTiddlers report. Clear the checkbox to skip this step.\n''2006.01.15 [2.4.1]'' added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic\n''2006.01.15 [2.4.0]'' Added support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax. Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.\n''2006.01.15 [2.3.2]'' Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)\n''2006.01.15 [2.3.1]'' Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME. Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins). Seems to resolve the "Found 0 tiddlers" problem. Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.\n''2006.01.12 [2.3.0]'' Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest. Let's processing continue while waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source. Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.\n''2006.01.11 [2.2.0]'' Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck\n''2006.01.09 [2.1.1]'' When a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button. This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit. I removed the onChange handling for file input field. To open a file (local or URL), you must now explicitly press the "open" button in the control panel.\n''2006.01.08 [2.1.0]'' IMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.\n''2006.01.06 [2.0.2]'' When refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.\n''2006.01.04 [2.0.1]'' When "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.\n''2005.12.27 [2.0.0]'' Update for TW2.0\nDefer initial panel creation and only register a notification function when panel first is created\n''2005.12.22 [1.3.1]'' tweak formatting in importReport() and add 'discard report' link to output\n''2005.12.03 [1.3.0]'' Dynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)\n''2005.11.29 [1.2.1]'' fixed formatting of 'detail info' in importReport()\n''2005.11.11 [1.2.0]'' added 'inline' param to embed controls in a tiddler\n''2005.11.09 [1.1.0]'' only load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.\n''2005.10.25 [1.0.5]'' fixed typo in importReport() that prevented reports from being generated\n''2005.10.09 [1.0.4]'' combined documentation with plugin code instead of using separate tiddlers\n''2005.08.05 [1.0.3]'' moved CSS and HTML definitions into plugin code instead of using separate tiddlers\n''2005.07.27 [1.0.2]'' core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()\n''2005.07.23 [1.0.1]'' added parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]'' Initial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n// // ''MACRO DEFINITION''\n//{{{\n// Version\nversion.extensions.importTiddlers = {major: 3, minor: 2, revision: 0, date: new Date(2007,02,09)};\n\n// IE needs explicit global scoping for functions/vars called from browser events\nwindow.onClickImportButton=onClickImportButton;\nwindow.refreshImportList=refreshImportList;\n\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\n// fixups for TW2.0.x and earlier\nif (window.merge==undefined) window.merge=function(dst,src,preserveExisting)\n { for (p in src) if (!preserveExisting||dst[p]===undefined) dst[p]=src[p]; return dst; }\nif (config.macros.importTiddlers==undefined) config.macros.importTiddlers={ };\n\nmerge(config.macros.importTiddlers,{\n label: "import tiddlers",\n prompt: "Copy tiddlers from another document",\n foundMsg: "Found %0 tiddlers in %1",\n countMsg: "%0 tiddlers selected for import",\n importedMsg: "Imported %0 of %1 tiddlers from %2",\n src: "", // path/filename or URL of document to import (retrieved from SiteUrl tiddler)\n proxy: "", // URL for remote proxy script (retrieved from SiteProxy tiddler)\n useProxy: false, // use specific proxy script in front of remote URL\n inbound: null, // hash-indexed array of tiddlers from other document\n newTags: "", // text of tags added to imported tiddlers\n addTags: true, // add new tags to imported tiddlers\n listsize: 8, // # of lines to show in imported tiddler list\n importTags: true, // include tags from remote source document when importing a tiddler\n keepTags: true, // retain existing tags when replacing a tiddler\n index: 0, // current processing index in import list\n sort: "" // sort order for imported tiddler listbox\n});\n\nif (config.macros.importTiddlers.coreHandler==undefined)\n config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler\n\nconfig.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!params[0] || params[0].toLowerCase()=='core') { // default to built in\n if (config.macros.importTiddlers.coreHandler)\n config.macros.importTiddlers.coreHandler.apply(this,arguments);\n else \n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n }\n else if (params[0]=='link') // show link to floating panel\n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n else if (params[0]=='inline') {// show panel as INLINE tiddler content\n createImportPanel(place);\n document.getElementById("importPanel").style.position="static";\n document.getElementById("importPanel").style.display="block";\n }\n else config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers\n}\n//}}}\n\n// // ''INTERFACE DEFINITION''\n// // Handle link click to create/show/hide control panel\n//{{{\nfunction onClickImportMenu(e)\n{\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("importPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=createImportPanel(parent);\n var isOpen = panel.style.display=="block";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n panel.style.display = isOpen ? "none" : "block" ;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n\n// // Create control panel: HTML, CSS\n//{{{\nfunction createImportPanel(place) {\n var panel=document.getElementById("importPanel");\n if (panel) { panel.parentNode.removeChild(panel); }\n setStylesheet(config.macros.importTiddlers.css,"importTiddlers");\n panel=createTiddlyElement(place,"span","importPanel",null,null)\n panel.innerHTML=config.macros.importTiddlers.html;\n refreshImportList();\n var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";\n document.getElementById("importSourceURL").value=siteURL;\n config.macros.importTiddlers.src=siteURL;\n var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";\n document.getElementById("importSiteProxy").value=siteProxy;\n config.macros.importTiddlers.proxy=siteProxy;\n return panel;\n}\n//}}}\n\n// // CSS\n//{{{\nconfig.macros.importTiddlers.css = '\s\n#importPanel {\s\n display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\s\n background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\s\n padding: 0.5em; margin:0em; -moz-border-radius:1em;\s\n}\s\n#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\s\n#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\s\n#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\s\n#importPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\s\n#importPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\s\n#importPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\s\n#importPanel .rad { width:auto; }\s\n#importPanel .chk { width:auto; margin:1px;border:0; }\s\n#importPanel .btn { width:auto; }\s\n#importPanel .btn1 { width:98%; }\s\n#importPanel .btn2 { width:48%; }\s\n#importPanel .btn3 { width:32%; }\s\n#importPanel .btn4 { width:24%; }\s\n#importPanel .btn5 { width:19%; }\s\n#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\s\n#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\s\n#importCollisionPanel { display:none; margin:0.5em 0em 0em 0em; }\s\n';\n//}}}\n\n// // HTML \n//{{{\nconfig.macros.importTiddlers.html = '\s\n<!-- source and report -->\s\n<table><tr><td align=left>\s\n import from\s\n <input type="radio" class="rad" name="importFrom" value="file" CHECKED\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=!this.checked?\s'block\s':\s'none\s'"> local file\s\n <input type="radio" class="rad" name="importFrom" value="http"\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=!this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=this.checked?\s'block\s':\s'none\s'"> web server\s\n</td><td align=right>\s\n <input type=checkbox class="chk" id="chkImportReport" checked\s\n onClick="config.options[\s'chkImportReport\s']=this.checked;"> create a report\s\n</td></tr></table>\s\n<!-- import from local file -->\s\n<div id="importLocalPanel" style="display:block;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\nlocal document path/filename:<br>\s\n<input type="file" id="fileImportSource" size=57 style="width:100%"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<!-- import from http server -->\s\n<div id="importHTTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\n<table><tr><td align=left>\s\n remote document URL:<br>\s\n</td><td align=right>\s\n <input type="checkbox" class="chk" id="importUseProxy"\s\n onClick="config.macros.importTiddlers.useProxy=this.checked;\s\n document.getElementById(\s'importSiteProxy\s').style.display=this.checked?\s'block\s':\s'none\s'"> use a proxy script\s\n</td></tr></table>\s\n<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\s\n onKeyUp="config.macros.importTiddlers.proxy=this.value"\s\n onChange="config.macros.importTiddlers.proxy=this.value;">\s\n<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<table><tr><td align=left>\s\n select:\s\n <a href="JavaScript:;" id="importSelectAll"\s\n onclick="onClickImportButton(this)" title="select all tiddlers">\s\n &nbsp;all&nbsp;</a>\s\n <a href="JavaScript:;" id="importSelectNew"\s\n onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\s\n &nbsp;added&nbsp;</a> \s\n <a href="JavaScript:;" id="importSelectChanges"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\s\n &nbsp;changes&nbsp;</a> \s\n <a href="JavaScript:;" id="importSelectDifferences"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\s\n &nbsp;differences&nbsp;</a> \s\n <a href="JavaScript:;" id="importToggleFilter"\s\n onclick="onClickImportButton(this)" title="show/hide selection filter">\s\n &nbsp;filter&nbsp;</a> \s\n</td><td align=right>\s\n <a href="JavaScript:;" id="importListSmaller"\s\n onclick="onClickImportButton(this)" title="reduce list size">\s\n &nbsp;&#150;&nbsp;</a>\s\n <a href="JavaScript:;" id="importListLarger"\s\n onclick="onClickImportButton(this)" title="increase list size">\s\n &nbsp;+&nbsp;</a>\s\n <a href="JavaScript:;" id="importListMaximize"\s\n onclick="onClickImportButton(this)" title="maximize/restore list size">\s\n &nbsp;=&nbsp;</a>\s\n</td></tr></table>\s\n<select id="importList" size=8 multiple\s\n onchange="setTimeout(\s'refreshImportList(\s'+this.selectedIndex+\s')\s',1)">\s\n <!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\s\n</select>\s\n<input type=checkbox class="chk" id="chkAddTags" checked\s\n onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags &nbsp;\s\n<input type=checkbox class="chk" id="chkImportTags" checked\s\n onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags &nbsp;\s\n<input type=checkbox class="chk" id="chkKeepTags" checked\s\n onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags<br>\s\n<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\s\n<div align=center>\s\n <input type=button id="importOpen" class="importButton" style="width:32%" value="open"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importStart" class="importButton" style="width:32%" value="import"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importClose" class="importButton" style="width:32%" value="close"\s\n onclick="onClickImportButton(this)">\s\n</div>\s\n<div id="importCollisionPanel">\s\n tiddler already exists:\s\n <input type=text id="importNewTitle" size=15 autocomplete=off">\s\n <div align=center>\s\n <input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importRename" class="importButton" style="width:23%" value="rename"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\s\n onclick="onClickImportButton(this)">\s\n </div>\s\n</div>\s\n';\n//}}}\n\n// // Control interactions\n//{{{\nfunction onClickImportButton(which)\n{\n // DEBUG alert(which.id);\n var theList = document.getElementById('importList');\n if (!theList) return;\n var thePanel = document.getElementById('importPanel');\n var theCollisionPanel = document.getElementById('importCollisionPanel');\n var theNewTitle = document.getElementById('importNewTitle');\n var count=0;\n switch (which.id)\n {\n case 'fileImportSource':\n case 'importOpen': // load import source into hidden frame\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n if (config.macros.importTiddlers.src=="") break;\n // Load document into hidden iframe so we can read it's DOM and fill the list\n config.macros.importTiddlers.loadRemoteFile(config.macros.importTiddlers.src, function(src,txt) {\n var tiddlers = readTiddlersFromHTML(txt);\n var count=tiddlers?tiddlers.length:0;\n displayMessage(config.macros.importTiddlers.foundMsg.format([count,src]));\n config.macros.importTiddlers.inbound=tiddlers;\n window.refreshImportList(0);\n });\n break;\n case 'importSelectAll': // select all tiddler list items (i.e., not headings)\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=true;\n count++;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectNew': // select tiddlers not in current document\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importToggleFilter': // show/hide filter\n case 'importFilter': // apply filter\n alert("coming soon!");\n break;\n case 'importStart': // initiate the import processing\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.index=0;\n config.macros.importTiddlers.index=importTiddlers(0);\n importStopped();\n break;\n case 'importClose': // unload imported tiddlers or hide the import control panel\n // if imported tiddlers not loaded, close the import control panel\n if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n break;\n case 'importSkip': // don't import the tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status='skipped after asking'; // mark item as skipped\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item\n importStopped();\n break;\n case 'importRename': // change name of imported tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status = 'renamed from '+theImported.title; // mark item as renamed\n theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title\n theItem.value = theNewTitle.value; // change the listbox item text\n theItem.text = theNewTitle.value; // change the listbox item text\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importMerge': // join existing and imported tiddler content\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n var theText = theExisting.text+'\sn----\sn^^merged from: ';\n theText +='[['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\sn';\n theText +='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\sn'+theImported.text;\n var theDate = new Date();\n var theTags = theExisting.getTags()+' '+theImported.getTags();\n theImported.set(null,theText,null,theDate,theTags);\n theImported.status = 'merged with '+theExisting.title; // mark item as merged\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item\n importStopped();\n break;\n case 'importReplace': // substitute imported tiddler for existing tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n theImported.status = 'replaces '+theExisting.title; // mark item for replace\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importListSmaller': // decrease current listbox size, minimum=5\n if (theList.options.length==1) break;\n theList.size-=(theList.size>5)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListLarger': // increase current listbox size, maximum=number of items in list\n if (theList.options.length==1) break;\n theList.size+=(theList.size<theList.options.length)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListMaximize': // toggle listbox size between current and maximum\n if (theList.options.length==1) break;\n theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;\n break;\n }\n}\n//}}}\n\n// // refresh listbox\n//{{{\nfunction refreshImportList(selectedIndex)\n{\n var theList = document.getElementById("importList");\n if (!theList) return;\n // if nothing to show, reset list content and size\n if (!config.macros.importTiddlers.inbound) \n {\n while (theList.length > 0) { theList.options[0] = null; }\n theList.options[0]=new Option('please open a document...',"",false,false);\n theList.size=config.macros.importTiddlers.listsize;\n return;\n }\n // get the sort order\n if (!selectedIndex) selectedIndex=0;\n if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading\n if (selectedIndex==1) config.macros.importTiddlers.sort='title';\n if (selectedIndex==2) config.macros.importTiddlers.sort='modified';\n if (selectedIndex==3) config.macros.importTiddlers.sort='tags';\n if (selectedIndex>3) {\n // display selected tiddler count\n for (var t=0,count=0; t < theList.options.length; t++) count+=(theList.options[t].selected&&theList.options[t].value!="")?1:0;\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n return; // no refresh needed\n }\n\n // get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)\n var tiddlers=config.macros.importTiddlers.inbound;\n tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n // add heading and control items to list\n var i=0;\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n theList.options[i++]=new Option(tiddlers.length+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);\n // output the tiddler list\n switch(config.macros.importTiddlers.sort)\n {\n case "title":\n for(var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);\n break;\n case "modified":\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });\n var lastSection = "";\n for(var t = 0; t < tiddlers.length; t++) {\n var tiddler = tiddlers[t];\n var theSection = tiddler.modified.toLocaleDateString();\n if (theSection != lastSection) {\n theList.options[i++] = new Option(theSection,"",false,false);\n lastSection = theSection;\n }\n theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);\n }\n break;\n case "tags":\n var theTitles = {}; // all tiddler titles, hash indexed by tag value\n var theTags = new Array();\n for(var t=0; t<tiddlers.length; t++) {\n var title=tiddlers[t].title;\n var tags=tiddlers[t].tags;\n if (!tags || !tags.length) {\n if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }\n theTitles["untagged"].push(title);\n }\n else for(var s=0; s<tags.length; s++) {\n if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }\n theTitles[tags[s]].push(title);\n }\n }\n theTags.sort();\n for(var tagindex=0; tagindex<theTags.length; tagindex++) {\n var theTag=theTags[tagindex];\n theList.options[i++]=new Option(theTag,"",false,false);\n for(var t=0; t<theTitles[theTag].length; t++)\n theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);\n }\n break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;\n if (theList.size>theList.options.length) theList.size=theList.options.length;\n}\n//}}}\n\n// // re-entrant processing for handling import with interactive collision prompting\n//{{{\nfunction importTiddlers(startIndex)\n{\n if (!config.macros.importTiddlers.inbound) return -1;\n\n var theList = document.getElementById('importList');\n if (!theList) return;\n var t;\n // if starting new import, reset import status flags\n if (startIndex==0)\n for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)\n config.macros.importTiddlers.inbound[t].status="";\n for (var i=startIndex; i<theList.options.length; i++)\n {\n // if list item is not selected or is a heading (i.e., has no value), skip it\n if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))\n continue;\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==t) break;\n var inbound = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(inbound.title);\n // avoid redundant import for tiddlers that are listed multiple times (when 'by tags')\n if (inbound.status=="added")\n continue;\n // don't import the "ImportedTiddlers" history from the other document...\n if (inbound.title=='ImportedTiddlers')\n continue;\n // if tiddler exists and import not marked for replace or merge, stop importing\n if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))\n return i;\n // assemble tags (remote + existing + added)\n var newTags = "";\n if (config.macros.importTiddlers.importTags)\n newTags+=inbound.getTags() // import remote tags\n if (config.macros.importTiddlers.keepTags && theExisting)\n newTags+=" "+theExisting.getTags(); // keep existing tags\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newTags+=" "+config.macros.importTiddlers.newTags; // add new tags\n inbound.set(null,null,null,null,newTags.trim());\n // set the status to 'added' (if not already set by the 'ask the user' UI)\n inbound.status=(inbound.status=="")?'added':inbound.status;\n // do the import!\n // OLD: store.addTiddler(in); store.setDirty(true);\n store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags);\n store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value\n }\n return(-1); // signals that we really finished the entire list\n}\n//}}}\n\n//{{{\nfunction importStopped()\n{\n var theList = document.getElementById('importList');\n var theNewTitle = document.getElementById('importNewTitle');\n if (!theList) return;\n if (config.macros.importTiddlers.index==-1)\n importReport(); // import finished... generate the report\n else\n {\n // DEBUG alert('import stopped at: '+config.macros.importTiddlers.index);\n // import collision... show the collision panel and set the title edit field\n document.getElementById('importCollisionPanel').style.display='block';\n theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;\n }\n}\n//}}}\n\n// // ''REPORT GENERATOR''\n//{{{\nfunction importReport(quiet)\n{\n if (!config.macros.importTiddlers.inbound) return;\n // DEBUG alert('importReport: start');\n\n // if import was not completed, the collision panel will still be open... close it now.\n var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';\n\n // get the alphasorted list of tiddlers\n var tiddlers = config.macros.importTiddlers.inbound;\n // gather the statistics\n var count=0;\n for (var t=0; t<tiddlers.length; t++)\n if (tiddlers[t].status && tiddlers[t].status.trim().length && tiddlers[t].status.substr(0,7)!="skipped") count++;\n\n // generate a report\n if (count && config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName\n newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\sn[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\sn";\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newText += "imported tiddlers were tagged with: \s""+config.macros.importTiddlers.newTags+"\s"\sn";\n newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n// 20060918 ELS: DON'T ADD "discard" BUTTON TO REPORT\n// newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n// newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n// newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n // OLD: store.addTiddler(theReport);\n store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n\n // reset status flags\n for (var t=0; t<config.macros.importTiddlers.inbound.length; t++) config.macros.importTiddlers.inbound[t].status="";\n\n // refresh display if tiddlers have been loaded\n if (count) { store.setDirty(true); store.notifyAll(); }\n\n // always show final message when tiddlers were actually loaded\n if (count) displayMessage(config.macros.importTiddlers.importedMsg.format([count,tiddlers.length,config.macros.importTiddlers.src]));\n}\n//}}}\n\n/***\n!!!!! non-interactive 'load tiddlers' macro\n***/\n//{{{\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\nconfig.macros.loadTiddlers = {\n label: "",\n prompt: "add/update tiddlers from '%0'",\n lockedTag: "noReload", // if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer\n askMsg: "Please enter a local path/filename or a remote URL",\n openMsg: "Opening %0",\n openErrMsg: "Could not open %0 - error=%1",\n readMsg: "Read %0 bytes from %1",\n foundMsg: "Found %0 tiddlers in %1",\n nochangeMsg: "'%0' is up-to-date... skipped.",\n lockedMsg: "'%0' is tagged '%1'... skipped.",\n skippedMsg: "skipped (cancelled by user)",\n loadedMsg: "Loaded %0 of %1 tiddlers from %2",\n newTags: []\n};\n\nconfig.macros.loadTiddlers.handler = function(place,macroName,params) {\n var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;\n var prompt=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.prompt;\n var filter="updates";\n if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'\n || params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))\n filter=params.shift();\n var src=params.shift(); if (!src || !src.length) return; // filename is required\n var quiet=(params[0]=="quiet"); if (quiet) params.shift();\n var ask=(params[0]=="confirm"); if (ask) params.shift();\n var force=(params[0]=="force"); if (force) params.shift();\n if (params[0]) this.newTags=params; // any remaining params are used as "autotags"\n if (label.trim().length) {\n // link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store\n createTiddlyButton(place,label.format([src]),prompt.format([src]), function() {\n if (src=="ask") src=prompt(config.macros.loadTiddlers.askMsg);\n config.macros.importTiddlers.loadRemoteFile(src,loadTiddlers,quiet,ask,filter,force);\n })\n }\n else {\n // load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store\n if (src=="ask") src=prompt(this.askMsg);\n config.macros.importTiddlers.loadRemoteFile(src,loadTiddlers,quiet,ask,filter,force);\n }\n}\n\nfunction loadTiddlers(src,html,quiet,ask,filter,force)\n{\n var tiddlers = readTiddlersFromHTML(html);\n var count=tiddlers?tiddlers.length:0;\n if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src]));\n var count=0;\n if (tiddlers) for (var t=0;t<tiddlers.length;t++) {\n var inbound = tiddlers[t];\n var theExisting = store.getTiddler(inbound.title);\n if (inbound.title=='ImportedTiddlers')\n continue; // skip "ImportedTiddlers" history from the other document...\n if (theExisting && theExisting.tags.contains(config.macros.loadTiddlers.lockedTag)) {\n if (!quiet) displayMessage(config.macros.loadTiddlers.lockedMsg.format([theExisting.title,config.macros.loadTiddlers.lockedTag]));\n continue; // skip existing tiddler if tagged with 'noReload'\n }\n // apply the all/new/changes/updates filter (if any)\n if (filter && filter!="all") {\n if ((filter=="new") && theExisting) // skip existing tiddlers\n continue;\n if ((filter=="changes") && !theExisting) // skip new tiddlers\n continue;\n if ((filter.substr(0,4)=="tag:") && inbound.tags.find(filter.substr(4))==null) // must match specific tag value\n continue;\n if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name\n continue;\n if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0))\n { if (!quiet) displayMessage(config.macros.loadTiddlers.nochangeMsg.format([inbound.title])); continue; }\n }\n // get confirmation if required\n if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\snfrom "+src))\n { tiddlers[t].status=config.macros.loadTiddlers.skippedMsg; continue; }\n // DO IT!\n // OLD: store.addTiddler(in);\n var tags=Array.concat(inbound.tags,config.macros.loadTiddlers.newTags);\n store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, tags);\n store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value\n tiddlers[t].status=theExisting?"updated":"added"\n count++;\n }\n if (count) {\n // refresh display\n store.setDirty(true);\n store.notifyAll();\n // generate a report\n if (config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName+" loaded "+count+" tiddlers from\sn[["+src+"|"+src+"]]:\sn";\n newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n// 20060918 ELS: DON'T ADD "discard" BUTTON TO REPORT\n// newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n// newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n// newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n // OLD: store.addTiddler(theReport);\n store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n }\n // always show final message when tiddlers were actually loaded\n if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src]));\n}\n\n// replaces existing core function\n\nconfig.macros.importTiddlers.loadRemoteFile = function(src,callback,quiet,ask,filter,force) {\n if (src==undefined || !src.length) return null; // filename is required\n if (!quiet) clearMessage();\n if (!quiet) displayMessage(config.macros.loadTiddlers.openMsg.format([src]));\n if (src.substr(0,4)!="http" && src.substr(0,4)!="file") { // if not a URL, fallback to read from local filesystem\n var txt=loadFile(src);\n if ((txt==null)||(txt==false)) // file didn't load\n { if (!quiet) displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,"(unknown)"])); }\n else {\n if (!quiet) displayMessage(config.macros.loadTiddlers.readMsg.format([txt.length,src]));\n if (callback) callback(src,convertUTF8ToUnicode(txt),quiet,ask,filter,force);\n }\n }\n else {\n var x; // get an request object\n try {x = new XMLHttpRequest()} // moz\n catch(e) {\n try {x = new ActiveXObject("Msxml2.XMLHTTP")} // IE 6\n catch (e) {\n try {x = new ActiveXObject("Microsoft.XMLHTTP")} // IE 5\n catch (e) { return }\n }\n }\n // setup callback function to handle server response(s)\n x.onreadystatechange = function() {\n if (x.readyState == 4) {\n if (x.status==0 || x.status == 200) {\n if (!quiet) displayMessage(config.macros.loadTiddlers.readMsg.format([x.responseText.length,src]));\n if (callback) callback(src,x.responseText,quiet,ask,filter,force);\n }\n else {\n if (!quiet) displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,x.status]));\n }\n }\n }\n // get privileges to read another document's DOM via http:// or file:// (moz-only)\n if (typeof(netscape)!="undefined") {\n try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }\n catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }\n }\n // send the HTTP request\n try {\n var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();\n x.open("GET",src,true);\n if (x.overrideMimeType) x.overrideMimeType('text/html');\n x.send(null);\n }\n catch (e) {\n if (!quiet) {\n displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,"(unknown)"]));\n displayMessage(e.description?e.description:e.toString());\n }\n }\n }\n}\n\nfunction readTiddlersFromHTML(html)\n{\n // extract store area from html \n var start=html.indexOf('<div id="storeArea">');\n var end=html.indexOf("<!--POST-BODY-START--"+">",start);\n if (end==-1) var end=html.indexOf("</body"+">",start); // backward-compatibility for older documents\n var sa="<html><body>"+html.substring(start,end)+"</body></html>";\n\n // load html into iframe document\n var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);\n f=document.createElement("iframe"); f.id="loaderFrame";\n f.style.width="0px"; f.style.height="0px"; f.style.border="0px";\n document.body.appendChild(f);\n var d=f.document;\n if (f.contentDocument) d=f.contentDocument; // For NS6\n else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6\n d.open(); d.writeln(sa); d.close();\n\n // read tiddler DIVs from storeArea DOM element \n var sa = d.getElementById("storeArea");\n if (!sa) return null;\n sa.normalize();\n var nodes = sa.childNodes;\n if (!nodes || !nodes.length) return null;\n var tiddlers = [];\n for(var t = 0; t < nodes.length; t++) {\n var title = null;\n if(nodes[t].getAttribute)\n title = nodes[t].getAttribute("tiddler");\n if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))\n title = nodes[t].id.substr(5);\n if(title && title != "")\n tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));\n }\n return tiddlers;\n}\n//}}}
Formats: [[XML|?format=xml]] | [[YAML|?format=yaml]]\n
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Open options panel'>><<exportLink>><<importLink>><<login>> \n
http://objectis.org\n\nObjectis used to give away free 10MB [[Zope]] accounts, but have recently discontinued their free service with little or no explanation. Their server(s) have been unreliable in the last few days, so we recommend ZW users stay away until they show signs of improvement. ''If you're already using Objectis, export your data to be on the safe side.''
<!--{{{-->\n<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler deleteTiddler permalink references revisions jump'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date [[DD MMM YYYY]]'></span> (created <span macro='view created date [[DD MMM YYYY]]'></span>)</div>\n<div class='tagging' macro='tagging'></div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div>\n<!--}}}-->
Based on TiddlyWiki 2.0.6\n\n[[Download here.|/versions/2.0.6.1.zexp]]\n\nMajor Changes:\n* Fixed tiddler name collisions.\n** Existing tiddlers will be renamed for a seamless upgrade.\n* Fixed bug retrieving, deleting, and saving certain tiddlers (URL wasn't being encoded properly for some tiddler titles).\n* Added CustomJS and CustomCSS feature to ''ziddly'' script.\n* Curly quotes and such are replaced with their simpler counterparts to prevent Safari lockup.
WebDAV stands for "Web-based Distributed Authoring and Versioning" and can be used to edit ZiddlyWiki tiddlers. WebDAV provides methods to load and save web objects. It is a superset of the HTTP (Hyper Text Transfer Protocol) and is beginning to be recognized by many operating systems and editors. See below for your specific situation.\n\n[[WebDAV on Linux]]\n[[WebDAV on MacOSX]]\n[[WebDAV on Windows]]
Based on TiddlyWiki 2.0.6\n\n[[Download here.|/versions/2.0.6.2.zexp]]\n\nMajor Changes:\n* Fixed bug in curly quote replacement (only the first instance of each character was being replaced).\n* Fixed bug preventing the use of quotes in tiddler titles.
ZiddlyWiki <<ziddlyversion>>\n[[News]]\nGetYourOwn\nCreateALogin\n\n[[Sandbox|/sandbox]]\n\nHosted by [[Zettai|http://zettai.net]]
Powered by [[ZiddlyWiki|http://ziddlywiki.com]]\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//_createTiddlyButton = createTiddlyButton;\n//createTiddlyButton = 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{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\nconfig.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.imgLoc = img_edit;\n//config.commands.editTiddler.readOnlyText = img_edit;\nconfig.commands.closeTiddler.imgLoc = img_close;\nconfig.commands.closeOthers.imgLoc = img_close_others;\nconfig.commands.saveTiddler.text.imgLoc = img_save;\nconfig.commands.cancelTiddler.imgLoc = img_cancel;\nconfig.commands.deleteTiddler.imgLoc = img_del;\nconfig.commands.permalink.imgLoc = img_perm;\nconfig.commands.references.imgLoc = img_ref;\nconfig.commands.jump.imgLoc = img_jump;\nif(config.commands.revisions)\n config.commands.revisions.imgLoc = img_rev;\nif(config.commands.copyTiddler)\n config.commands.copyTiddler.imgLoc = img_copy;\n}}}\n
//This tiddler refers to the process of installing ZiddlyWiki; if you want to import a file into your ZW, check out ImportAndExport.//\n\n# Stick the downloaded file in your Zope server's ''import'' directory. On Windows, this might be something like {{{C:\sProgram Files\sZope\sdata\simport}}}.\n# Log into the ZopeManagementInterface, click the ''Import/Export'' button, and at the bottom find the ZiddlyWiki file you downloaded.\n# Click ''Import''.\n\n''Note:'' FreeZope doesn't allow import; you must use the InstallScript.
Tricks to utilize both planned and unplanned features of ZiddlyWiki:\n\n<<list tag tricks ZiddlyTricks>>
ZiddlyWiki sports "protected tiddlers", which are tiddlers only the author or an administrators can edit. By default, the following tiddlers are protected:\n\nJust add the "protected" tag to a tiddler you want to keep others from messing with.
<!--{{{--> \n<div class='header' macro='gradient vert #18f #04b'> \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
It's easy to copy/move tiddlers from one ZiddlyWiki instance to another:\n\n# Open up the ZopeManagementInterface.\n# Navigate to the ZiddlyWiki instance with the tiddler you want to copy/move. Open up the ''tiddlers'' folder there.\n# Find the tiddler, select the checkbox next to it, and click ''Copy'' or ''Cut''.\n# Navigate to the destination ''tiddlers'' folder.\n# Click ''Paste''.
Based on TiddlyWiki 2.0.2\n\n[[Download here.|/versions/2.0.2.1.zexp]]\n\nMajor Changes:\n* introduced AutoRefresh\n** needs some improvement for handling renamed and deleted tiddlers\n* fixed login macro to properly link to logged-in user\n* removed brackets from title bar\n** still won't properly wikify text though\n* fixed import on new tiddlers\n** has been broken for awhile now I think\n* changed labels on import and export to more clearly state their purpose\n** can be changed by modifying config.messages.exportLinkLabel and config.messages.importLinkLabel\n* fixed unlocking of renamed tiddlers\n* added status message to show delay when locking a tiddler for edit\n* removed auto-creation of system tiddlers - shadow tiddlers are now used instead
Based on TiddlyWiki 2.0.2\n\n[[Download here.|/versions/2.0.2.3.zexp]]\n\nMajor Changes:\n* made it possible to edit anyway if a tiddler is locked by you (by accident or in another browser)
Based on TiddlyWiki 2.0.2\n\n[[Download here.|/versions/2.0.2.2.zexp]]\n\nMajor Changes:\n* made AutoRefresh fail more gracefully on malformed requests (but where are they coming from?)\n* added new actions for administrators:\n** TiddlerCleanup\n** TiddlerBackup
Based on TiddlyWiki 2.0.2\n\n[[Download here.|/versions/2.0.2.4.zexp]]\n\nMajor Changes:\n* fixed order of tiddler properties when exported
Any plans for ZiddlyWiki to support the latest version of TiddlyWiki (2.1.3 at the time of writing)? Thanks.\n(Or alternatively could you give us a clue as to how to do this?). There are some features in the newer TiddlyWiki (such as RSS feeds) which would be quite nice to have in Ziddly form.
web & wiki Geek\nLocation: Hamburg (Germany)\n[[more info|http://www.sven-tissot.de/wiki/SvenTissot]]\nmail: //prename// at //surname// dot de
''If you just want to play around with ZiddlyWiki, visit the [[Sandbox|/sandbox]].''\n\nYou don't need to create a login to GetYourOwn.\n\nTo edit tiddlers on this site, first create a login by clicking the link below and filling out the form.\n\n''[[Sign Up.|/cookie_auth/signup]]''
TiddlyWiki is a complete ClientSide [[Wiki]] system contained in a single HTML file created by JeremyRuston. JavaScript is used to store, retrieve, edit, and delete wiki content, and no ServerSide is required. You can create a standalone copy of your ZiddlyWiki by clicking the {{{save to file}}} link at the right, and your ZiddlyWiki can be updated from standalone files as well.\n\nMany people putting the file on a USB stick or carry it to meetings/class/presentations for note-taking.\n\nhttp://tiddlywiki.com
<<importTiddlers>>
[[Zope]] stores old revisions of most types of objects, therefore all old tiddler versions are stored in ZiddlyWiki. ZW makes use of this to provide TiddlerRevisions.
ZiddlyWiki saves its changes in real-time, after each tiddler edit.\n\nIf you want to reuse this site, you can GetYourOwn.
The "index_html" script is magic. You can put it in any folder and call it whatever you want, and it will be its own ZiddlyWiki. Copy it to a folder called "resume", and you have a separate ZW for your resume!\n\nZW gets its tiddlers from the first "tiddlers" folder it finds. This is easiest to explain with an example... Pretend this is the folder structure of your [[Zope]] instance:\n\n{{{\nmyzw.com:\n/\n ZiddlyWiki/\n tiddlers/\n index_html\n resume/\n tiddlers/\n index_html\n another_zw/\n index_html\n}}}\n\nThis instance has three ZiddlyWiki instances because this user copied the "index_html" script to three different locations. But notice the "tiddlers" folders that are present. In this scenario, {{{myzw.com}}} is a ZW, and so is {{{myzw.com/resume}}}. Each have their own "tiddlers" folder. However, {{{myzw.com/another_zw}}} doesn't have its own "tiddlers" folder, so it uses the first one it sees, which is the one in the root. Both {{{myzw.com}}} and {{{myzw.com/another_zw}}} will have exactly the same tiddlers. Making changes on one ZW will make changes on the other.\n\nThis long-winded example is to illustrate the need to create "tiddlers" folders where you need them. Whew!
a TiddlyWiki server utilizing Zope
[[See a video of it in use.|http://ia300105.us.archive.org/3/items/TimMorganZWInstallScript/ZWInstall.wmv]]\n\nTo use the installer:\n# [[Get the code|/ZiddlyWiki/create_installer]] and ''copy'' it.\n# Log into the ZopeManagementInterface.\n# If you have an object called "index_html", rename it or delete it.\n# Create a new "Script (Python)" object (name it "install" or something similar).\n# Delete the default stuff and ''paste''.\n# ''Save.''\n# Click the ''Test'' tab.\n\nThat's it! View your new site's URL and get busy setting up your ZiddlyWiki.\n----\nIf you want to upgrade using the InstallScript, delete the "~ZiddlyWiki" folder and start with step 1 above.
Add a property to your Zope instance called {{{zw_anon_edit}}}. Make the property a boolean type and give it a value of "1".\n\nEdits made by not-logged-in people will be marked as edited by "Anonymous User".
/*{{{*/\n#ZiddlyFormats,#ZiddlyPowered,#ZiddlyFormats a,#ZiddlyPowered a {\n color:#999\n}\n#sidebarOptions .sliderPanel .txtOptionInput {\n width: 2em;\n font-family: mono;\n font-size: 1em;\n}\n#ZiddlyFormats, #ZiddlyPowered { margin:5px }\n/*}}}*/\n
http://imageshack.us\n\nA free image host. Great for creating portable TW styles without making people copy images.
ZiddlyWiki
It's probably not a bad idea to occasionally make a copy of your "tiddlers" folder in case something goes horribly wrong.\n\n<<tiddler TiddlerBackup>>
An administrator can make a quick backup of all a ZW's tiddlers by appending {{{?action=backup}}} to the ZW url.\n\nFor instance, browsing to {{{http://mysite.com/mywiki/?action=backup}}} while logged in as an administrator (manager) will make a copy of the "tiddlers" folder and name it "backup".
Now you can mark certain tiddlers as {{{private}}}, causing them to only appear if you're logged in. To do so, add the {{{private}}} tag to your tiddler. Zope permissions are also used to ensure that the tiddler can only be seen by logged in users.\n\nYou can also add the {{{protected}}} tag to tiddlers which will cause them to be visible, but read-only to everyone except their creator.
Based on TiddlyWiki 2.0.3\n\n[[Download here.|/versions/2.0.3.1.zexp]]\n\nMajor Changes:\n* moved much of the ZW-specific code into a "zw" object to prevent namespace collisions\n** still a bit more to do, but already much better separated than it was\n* fixed revisions on renamed tiddlers\n* improved appearance of AJAX status message in the corner\n* fixed error occuring while creating a new tiddler to overwrite an existing one\n* improved ProtectedTiddlers by adding "protected" [[SpecialTag|SpecialTags]]\n* made tiddler source available to anonymous users\n* made protected tiddler source available to non-admins\n
Based on TiddlyWiki 2.0.3\n\n[[Download here.|/versions/2.0.3.2.zexp]]\n\nMajor Changes:\n* Fixed bug with MinorChanges (shift-done).\n* Made protected tiddlers protect non-admins, too. Only the creator or an admin can now modify a [[ProtectedTiddler|ProtectedTiddlers]].
Based on TiddlyWiki 1.2.39 (final)\n\n[[Download here.|/versions/1.2.39.1.zexp]]\n\nMajor Changes:\n//none//
Based on TiddlyWiki 1.2.36; last version with skins.\n\n[[Download here.|http://ziddlywiki.com/old/ZiddlyWiki-1.2.36.zexp]]
asdf\n
//plugin to pretty up the timeline dates//\n\n{{{\nvar today = 'Today';\nvar yesterday = 'Yesterday';\n\nconfig.macros.timeline.dateFormat = '!DD MMM YYYY';\nDate.prototype._formatString = Date.prototype.formatString;\nDate.prototype.formatString = function(template) {\n if(template.match(/^!/)) {\n var repr = this._formatString('YYYYMMDD');\n var day = new Date();\n if(repr == day._formatString('YYYYMMDD'))\n return today;\n day.setDate(day.getDate()-1);\n if(repr == day._formatString('YYYYMMDD'))\n return yesterday;\n for(var i=0; i<3; i++) {\n day.setDate(day.getDate()-1);\n if(repr == day._formatString('YYYYMMDD'))\n return config.messages.dates.days[this.getDay()];\n }\n }\n template = template.replace(/^!/, '');\n return this._formatString(template);\n}\n}}}
To use fancy cookie-based authentication like this site does, download [[this file|/versions/cookie_auth.zexp]] and stick it in your root. You'll need to tweak it a bit to make it look like you want it.
An administrator can permanently get rid of "deleted" tiddlers in the "tiddlers" folder by appending {{{?action=cleanup}}} to the ZW url.\n\nFor instance, browsing to {{{http://mysite.com/mywiki/?action=cleanup}}} while logged in as an administrator (manager) will delete tiddlers tagged as "deleted".
/*{{{*/\n.shell {\n font-family: monospace;\n font-size: 85%;\n}\n#output { \n white-space: pre; \n white-space: -moz-pre-wrap; \n background: #000;\n} /* Preserve line breaks, but wrap too if browser supports it */\n#output .input {\n background: #000;\n}\n#input { \n width: 100%; \n/* height: 1.4em; */\n border: none; \n padding: 0; \n overflow: auto; \n}\n.shell .input { \n font-family: mono; \n color: blue; \n font: inherit; \n margin-top: .5em;\n background: #E6E6FF; \n}\n.shell .normalOutput { \n font-family: mono; \n color: black; \n background: white; \n}\n.shell .print { color: brown; background: black; }\n.shell .error { color: red; background: black; }\n.shell .propList { color: green; background: black; }\n.shell .message { color: green; background: black; }\n.shell .tabcomplete { color: purple; background: black; }\n/*}}}*/
* [[Zope]] provides the ServerSide architecture for storing tiddler content and constructing the TiddlyWiki frontend for the client. And with FreeZope, even cheapskates can have their own ZiddlyWiki!\n* ZopeAuthentication is used to track and restrict wiki content modifications.\n* ZopeRevisions store old tiddler versions, and ZW makes use of this feature to provide TiddlerRevisions.\n* [[AJAX]] is used for all after-page-load communication with the server.\n* TiddlerLocks prevent several people from editing the same tiddler at the same time.\n* AutoRefresh keeps the page up-to-date without requiring a reload.\n* ImportAndExport allows you to take your ZW offline wherever you go. Even better, you don't have to commit to ZW -- take your data with you when you're done!\n* MultipleZWs allow you to have many sites without the hassle of uploading ZW multiple times and maintaining each one.\n\nRead about the rest of ZW's <<tag features>>.
A [[Wiki]] is a type of website that allows users to easily add and edit content and is especially suited for collaborative authoring.\n\nhttp://en.wikipedia.org/wiki/Wiki
/***\n''InlineJavascriptPlugin for ~TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#InlineJavascriptPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nInsert Javascript executable code directly into your tiddler content. Lets you ''call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.\n!!!!!Usage\n<<<\nWhen installed, this plugin adds new wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be treated as embedded javascript and executed each time the tiddler is rendered.\n\n''Deferred execution from an 'onClick' link''\nBy including a label="..." parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered.\n\n''External script source files:''\nYou can also load javascript from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.\n\n''Display script source in tiddler output''\nBy including the keyword parameter "show", in the initial {{{<script>}}} marker, the plugin will include the script source code in the output that it displays in the tiddler.\n\n''Defining javascript functions and libraries:''\nAlthough the external javascript file is loaded while the tiddler content is being rendered, any functions it defines will not be available for use until //after// the rendering has been completed. Thus, you cannot load a library and //immediately// use it's functions within the same tiddler. However, once that tiddler has been loaded, the library functions can be freely used in any tiddler (even the one in which it was initially loaded).\n\nTo ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that will be rendered as soon as your TiddlyWiki document is opened. For example, you could put your {{{<script src="..."></script>}}} syntax into a tiddler called LoadScripts, and then add {{{<<tiddler LoadScripts>>}}} in your MainMenu tiddler.\n\nSince the MainMenu is always rendered immediately upon opening your document, the library will always be loaded before any other tiddlers that rely upon the functions it defines. Loading an external javascript library does not produce any direct output in the tiddler, so these definitions should have no impact on the appearance of your MainMenu.\n\n''Creating dynamic tiddler content''\nAn important difference between this implementation of embedded scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document:\n* In a typical web document, you use the document.write() function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.\n* However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and completely replaces the entire ~TiddlyWiki document in your browser window.\n* To allow these scripts to work unmodified, the plugin automatically converts all occurences of document.write() so that the output is inserted into the tiddler content instead of replacing the entire ~TiddlyWiki document.\n\nIf your script does not use document.write() to create dynamically embedded content within a tiddler, your javascript can, as an alternative, explicitly return a text value that the plugin can then pass through the wikify() rendering engine to insert into the tiddler display. For example, using {{{return "thistext"}}} will produce the same output as {{{document.write("thistext")}}}.\n\n//Note: your script code is automatically 'wrapped' inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.//\n\n''Accessing the ~TiddlyWiki DOM''\nThe plugin provides one pre-defined variable, 'place', that is passed in to your javascript code so that it can have direct access to the containing DOM element into which the tiddler output is currently being rendered.\n\nAccess to this DOM element allows you to create scripts that can:\n* vary their actions based upon the specific location in which they are embedded\n* access 'tiddler-relative' information (use findContainingTiddler(place))\n* perform direct DOM manipulations (when returning wikified text is not enough)\n<<<\n!!!!!Examples\n<<<\nan "alert" message box:\n><script show>\n alert('InlineJavascriptPlugin: this is a demonstration message');\n</script>\ndynamic output:\n><script show>\n return (new Date()).toString();\n</script>\nwikified dynamic output:\n><script show>\n return "link to current user: [["+config.options.txtUserName+"]]";\n</script>\ndynamic output using 'place' to get size information for current tiddler:\n><script show>\n if (!window.story) window.story=window;\n var title=story.findContainingTiddler(place).id.substr(7);\n return title+" is using "+store.getTiddlerText(title).length+" bytes";\n</script>\ncreating an 'onclick' button/link that runs a script:\n><script label="click here" show>\n if (!window.story) window.story=window;\n alert("Hello World!\snlinktext='"+place.firstChild.data+"'\sntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");\n</script>\nloading a script from a source url:\n>http://www.TiddlyTools.com/demo.js contains:\n>>{{{function demo() { alert('this output is from demo(), defined in demo.js') } }}}\n>>{{{alert('InlineJavascriptPlugin: demo.js has been loaded'); }}}\n><script src="demo.js" show>\n return "loading demo.js..."\n</script>\n><script label="click to execute demo() function" show>\n demo()\n</script>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''InlineJavascriptPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.06.01 [1.5.1]'' when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly\n''2006.04.19 [1.5.0]'' added 'show' parameter to force display of javascript source code in tiddler output\n''2006.01.05 [1.4.0]'' added support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.\n''2005.12.13 [1.3.1]'' when catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski\n''2005.11.09 [1.3.0]'' for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content. Based on a suggestion by BradleyMeck\n''2005.11.08 [1.2.0]'' handle loading of javascript from an external URL via src="..." syntax\n''2005.11.08 [1.1.0]'' pass 'place' param into scripts to provide direct DOM access \n''2005.11.08 [1.0.0]'' initial release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.inlineJavascript= {major: 1, minor: 5, revision: 1, date: new Date(2006,6,1)};\n\nconfig.formatters.push( {\n name: "inlineJavascript",\n match: "\s\s<script",\n lookahead: "\s\s<script(?: src=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?(?: label=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?( show)?\s\s>((?:.|\s\sn)*?)\s\s</script\s\s>",\n\n handler: function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {\n if (lookaheadMatch[1]) { // load a script library\n // make script tag, set src, add to body to execute, then remove for cleanup\n var script = document.createElement("script"); script.src = lookaheadMatch[1];\n document.body.appendChild(script); document.body.removeChild(script);\n }\n if (lookaheadMatch[4]) { // there is script code\n if (lookaheadMatch[3]) // show inline script code in tiddler output\n wikify("//{{{\sn"+lookaheadMatch[0]+"\sn//}}}\sn",w.output);\n if (lookaheadMatch[2]) { // create a link to an 'onclick' script\n // add a link, define click handler, save code in link (pass 'place'), set link attributes\n var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",lookaheadMatch[2]);\n link.onclick=function(){try{return(eval(this.code))}catch(e){alert(e.description?e.description:e.toString())}}\n link.code="function _out(place){"+lookaheadMatch[4]+"};_out(this);"\n link.setAttribute("href","javascript:;"); link.setAttribute("title",""); link.style.cursor="pointer";\n }\n else { // run inline script code\n var code="function _out(place){"+lookaheadMatch[4]+"};_out(w.output);"\n code=code.replace(/document.write\s(/gi,'place.innerHTML+=(');\n try { var out = eval(code); } catch(e) { out = e.description?e.description:e.toString(); }\n if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);\n }\n }\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n} )\n//}}}\n
TiddlyWiki + RubyOnRails + Hosting Service\n\nhttp://serversidewiki.com
AJAX (Asynchronous JavaScript and XML) is a term describing a web development technique for creating interactive web applications and is made possible by modern browsers supporting the XMLHTTPRequest API.
/*{{{*/\nbody {\n font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; \n background-image: url(/images/bg21hi.gif); \n background-color: #229;\n} \n.header { \n background-image:url(/images/bg0fu.gif); \n height: 22px; \n padding:5px; \n font-size:1.1em; \n font-weight:bold; \n color:#9f6; \n overflow:hidden;\n} \n.header .tiddlyLink { \n color:#9f6; \n text-decoration:none; \n font-size:1.1em; \n}\n#SiteSubtitle { \n font-weight:normal;\n font-size:0.9em;\n color:#9f6; \n}\n#SiteSubtitle .tiddlyLink { \n font-size:0.9em;\n color:#9f6; \n}\n#sitetitlebg { \n background:transparent url(/images/bgs5hf.gif) repeat-x; \n height:15px;\n} \n.viewer pre { \n background:transparent url(/images/bgs5hf.gif) repeat-x; \ncolor:#666; }\n.button { border:none;color:#ff3; }\na:hover { color:#252d93; }\n.tagged { background-color:transparent; }\n.listTitle,.tagged .listTitle { color:#fff; } \n.button:hover { \n background-color:#ff3;\n border:none; \n}\n.popup .tiddlyLink, #popup .tiddlyLink, #popup * { \n color:#ff3; \n} \n.popup .revisionCurrent, #popup .revisionCurrent { \n color:#ff3; \n}\n.tiddler .title { \n border-bottom:1px solid #390; \n} \n#displayArea { margin-top:0px; }\n.tiddler { margin-top:0px; } \n#mainMenu { margin-top:20px; } \n#sidebar { margin-top:20px; } \n.tiddler .title {\n font-size:2em; \n margin-bottom:1px;\n}\n.tiddler .toolbar {\n float:right; \n margin-top:5px;\n} \nh1,h2,h3,h4,h5,h6{\n background-color:transparent; \n margin-bottom:0px; \n margin-top:0px;\n}\n.viewer pre { \n color: #fff;\n background-color: #229;\n border: 1px solid #00c;\n}\n/*}}}*/\n
* handle config.protectedTiddlers better -- explicitly add the 'protected' tag when these shadow tiddlers are displayed.\n* Adjust editing logic\n* Don't unlock when not editing (e.g. viewing a read only tiddler)\n* Make cancelling the edit of a non-existing (i.e. shadow) tiddler work