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

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

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

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

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

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

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

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

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

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

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

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

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

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

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left: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:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding: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 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin: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;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
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;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<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 excludeLists'></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>>
|''Type:''|file|
|''URL:''|http://tiddlywiki.abego-software.de|
|''Workspace:''|(default)|

This tiddler was automatically created to record the details of this server
|''Type:''|file|
|''URL:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Workspace:''|(default)|

This tiddler was automatically created to record the details of this server
|''Type:''|file|
|''URL:''|http://www.cs.umb.edu/~rouilj/courses/SEC_intermediate/SEC_tw.html|
|''Workspace:''|(default)|

This tiddler was automatically created to record the details of this server
|''Type:''|file|
|''URL:''|http://www.math.ist.utl.pt/~psoares/addons.html|
|''Workspace:''|(default)|

This tiddler was automatically created to record the details of this server
|''Type:''|file|
|''URL:''|http://www.tiddlytools.com|
|''Workspace:''|(default)|

This tiddler was automatically created to record the details of this server
<script label="bookmark" title="Add this tiddler to the Bookmarks list">
// Copied in part from Eric Schulman's MessageLogPlugin

var log = "BookmarkList";

var tid=store.getTiddler(log);
if (tid) { // update BookmarkList
      var out=store.getTiddlerText(log,"")+'\n[['+story.findContainingTiddler(place).getAttribute("tiddler")+']]';
      var who=config.options.chkForceMinorUpdate?tid.modifier:config.options.txtUserName;
      var when=config.options.chkForceMinorUpdate?tid.modified:new Date();

      store.saveTiddler(log,log,out,who,when,tid.tags,tid.fields);
}
if (!story.isDirty(log)) story.refreshTiddler(log,null,true); // only if log is not being edited
</script>
/***
|Name|AliasPlugin|
|Source|http://www.TiddlyTools.com/#AliasPlugin|
|Documentation|http://www.TiddlyTools.com/#AliasPluginInfo|
|Version|1.1.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Create text-substitution macros|
Define macros for abbreviations and other "aliases", and then embed them in the rest of your tiddler content to quickly insert common terms, phrases and links without a lot of repetitive typing.
!!!!!Documentation
> see [[AliasPluginInfo]]
!!!!!Revisions
<<<
2009.09.09 [1.1.1] 'tiddler' arg passed to wikify() so aliases containing macros render with correct context
| Please see [[AliasPluginInfo]] for previous revision details |
2005.08.12 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.AliasPlugin= {major: 1, minor: 1, revision: 1, date: new Date(2009,9,9)};
config.macros.alias= { };
config.macros.alias.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	var alias=params.shift(); if (!alias) return; alias=alias.replace(/ /g,"_"); // don't allow spaces in alias
	if (config.macros[alias]==undefined) { // create new macro (as needed)
		config.macros[alias] = { };
		config.macros[alias].handler =
			function (place,macroName,params,wikifier,paramString,tiddler)
				{ wikify(config.macros[macroName].text.format(params),place,null,tiddler); }
	}
	config.macros[alias].text = params[0]?params.join(' '):alias;	// set alias text
}
//}}}
http://url1
----
http://url2
----
https://url3
----
http://url4
----
<<tiddler "GettingStarted::courseHomeContent">>
/***
|''Name:''|AnnotationsPlugin|
|''Description:''|Inline annotations for tiddler text.|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#AnnotationsPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.0|
|''Date:''||
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|

!!Usage:
*{{{((text to annotate(annotation goes here)))}}}
* To include the text being annotated, in the popup as a title, put {{{^}}} as the first letter of the annotation text.
** {{{((text to annotate(^annotation goes here)))}}}

!!Examples:
Mouse over, the text below:
* ((banana(the best fruit in the world)))
* ((banana(^ the best fruit in the world)))

***/
// /%
config.formatters.unshift({name:"annotations",match:"\\(\\(",lookaheadRegExp:/\(\((.*?)\((\^?)((?:.|\n)*?)\)\)\)/g,handler:function(w){
this.lookaheadRegExp.lastIndex=w.matchStart;
var _2=this.lookaheadRegExp.exec(w.source);
if(_2&&_2.index==w.matchStart){
var _3=createTiddlyElement(w.output,"span",null,"annosub",_2[1]);
_3.anno=_2[3];
if(_2[2]){
_3.subject=_2[1];
}
_3.onmouseover=this.onmouseover;
_3.onmouseout=this.onmouseout;
_3.ondblclick=this.onmouseout;
w.nextMatch=_2.index+_2[0].length;
}
},onmouseover:function(e){
popup=createTiddlyElement(document.body,"div",null,"anno");
this.popup=popup;
if(this.subject){
wikify("!"+this.subject+"\n",popup);
}
wikify(this.anno,popup);
addClass(this,"annosubover");
Popup.place(this,popup,{x:25,y:7});
},onmouseout:function(e){
removeNode(this.popup);
this.popup=null;
removeClass(this,"annosubover");
}});
setStylesheet(".anno{position:absolute;border:2px solid #000;background-color:#DFDFFF; color:#000;padding:0.5em;max-width:15em;width:expression(document.body.clientWidth > (255/12) *parseInt(document.body.currentStyle.fontSize)?'15em':'auto' );}\n"+".anno h1, .anno h2{margin-top:0;color:#000;}\n"+".annosub{background:#ccc;}\n"+".annosubover{z-index:25; background-color:#DFDFFF;cursor:help;}\n","AnnotationStyles");


// %/
<<tiddler SlideSubstyle##levelTwo>>
!Any 
*quips
*comments
*evasions
*questions
*answers
<<tiddler SlideSubstyle##levelOne with: 'url("textbooks.gif")'>>
! There are a number of areas that can use some improvement:
* {{overlay1{tags underused}}}
* {{overlay2{more flexibility with themes}}}
* {{overlay3{discovering relations between tiddlers}}}
* {{overlay4{edit cycle with multiple users}}}
text/plain
.txt .text .js .vbs .asp .cgi .pl
----
text/html
.htm .html .hta .htx .mht
----
text/comma-separated-values
.csv
----
text/javascript
.js
----
text/css
.css
----
text/xml
.xml .xsl .xslt
----
image/gif
.gif
----
image/jpeg
.jpg .jpe .jpeg
----
image/png
.png
----
image/bmp
.bmp
----
image/tiff
.tif .tiff
----
audio/basic
.au .snd
----
audio/wav
.wav
----
audio/x-pn-realaudio
.ra .rm .ram
----
audio/x-midi
.mid .midi
----
audio/mp3
.mp3
----
audio/m3u
.m3u
----
video/x-ms-asf
.asf
----
video/avi
.avi
----
video/mpeg
.mpg .mpeg
----
video/quicktime
.qt .mov .qtvr
----
application/pdf
.pdf
----
application/rtf
.rtf
----
application/postscript
.ai .eps .ps
----
application/wordperfect
.wpd
----
application/mswrite
.wri
----
application/msexcel
.xls .xls3 .xls4 .xls5 .xlw
----
application/msword
.doc
----
application/mspowerpoint
.ppt .pps
----
application/x-director
.swa
----
application/x-shockwave-flash
.swf
----
application/x-zip-compressed
.zip
----
application/x-gzip
.gz
----
application/x-rar-compressed
.rar
----
application/octet-stream
.com .exe .dll .ocx
----
application/java-archive
.jar
/***
|Name|AttachFilePlugin|
|Source|http://www.TiddlyTools.com/#AttachFilePlugin|
|Documentation|http://www.TiddlyTools.com/#AttachFilePluginInfo|
|Version|4.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|AttachFilePluginFormatters, AttachFileMIMETypes|
|Overrides||
|Description|Store binary files as base64-encoded tiddlers with fallback links for separate local and/or remote file storage|
Store or link binary files (such as jpg, gif, pdf or even mp3) within your TiddlyWiki document and then use them as images or links from within your tiddler content.
> Important note: As of version 3.6.0, in order to //render// images and other binary attachments created with this plugin, you must also install [[AttachFilePluginFormatters]], which extends the behavior of the TiddlyWiki core formatters for embedded images ({{{[img[tooltip|image]]}}}), linked embedded images ({{{[img[tooltip|image][link]]}}}), and external/"pretty" links ({{{[[label|link]]}}}), so that these formatter will process references to attachment tiddlers as if a normal file reference had been provided. |
!!!!!Documentation
>see [[AttachFilePluginInfo]]
!!!!!Inline interface (live)
>see [[AttachFile]] (shadow tiddler)
><<tiddler AttachFile>>
!!!!!Revisions
<<<
2009.06.04 [4.0.0] changed attachment storage format to use //sections// instead of embedded substring markers.
|please see [[AttachFilePluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
// // version
//{{{
version.extensions.AttachFilePlugin= {major: 4, minor: 0, revision: 0, date: new Date(2009,6,4)};

// shadow tiddler
config.shadowTiddlers.AttachFile="<<attach inline>>";

// add 'attach' backstage task (insert before built-in 'importTask')
if (config.tasks) { // for TW2.2b or above
	config.tasks.attachTask = {
		text: "attach",
		tooltip: "Attach a binary file as a tiddler",
		content: "<<attach inline>>"
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf("importTask"),0,"attachTask");
}

config.macros.attach = {
// // lingo
//{{{
	label: "attach file",
	tooltip: "Attach a file to this document",
	linkTooltip: "Attachment: ",

	typeList: "AttachFileMIMETypes",

	titlePrompt: " enter tiddler title...",
	MIMEPrompt: "<option value=''>select MIME type...</option><option value='editlist'>[edit list...]</option>",
	localPrompt: " enter local path/filename...",
	URLPrompt: " enter remote URL...",

	tiddlerErr: "Please enter a tiddler title",
	sourceErr: "Please enter a source path/filename",
	storageErr: "Please select a storage method: embedded, local or remote",
	MIMEErr: "Unrecognized file format.  Please select a MIME type",
	localErr: "Please enter a local path/filename",
	URLErr: "Please enter a remote URL",
	fileErr: "Invalid path/file or file not found",

	tiddlerFormat: '!usage\n{{{%0}}}\n%0\n!notes\n%1\n!type\n%2\n!file\n%3\n!url\n%4\n!data\n%5\n',

//}}}
// // macro definition
//{{{
	handler:
	function(place,macroName,params) {
		if (params && !params[0])
			{ createTiddlyButton(place,this.label,this.tooltip,this.toggleAttachPanel); return; }
		var id=params.shift();
		this.createAttachPanel(place,id+"_attachPanel",params);
		document.getElementById(id+"_attachPanel").style.position="static";
		document.getElementById(id+"_attachPanel").style.display="block";
	},
//}}}
//{{{
	createAttachPanel:
	function(place,panel_id,params) {
		if (!panel_id || !panel_id.length) var panel_id="_attachPanel";
		// remove existing panel (if any)
		var panel=document.getElementById(panel_id); if (panel) panel.parentNode.removeChild(panel);
		// set styles for this panel
		setStylesheet(this.css,"attachPanel");
		// create new panel
		var title=""; if (params && params[0]) title=params.shift();
		var types=this.MIMEPrompt+this.formatListOptions(store.getTiddlerText(this.typeList)); // get MIME types
		panel=createTiddlyElement(place,"span",panel_id,"attachPanel",null);
		var html=this.html.replace(/%id%/g,panel_id);
		html=html.replace(/%title%/g,title);
		html=html.replace(/%disabled%/g,title.length?"disabled":"");
		html=html.replace(/%IEdisabled%/g,config.browser.isIE?"disabled":"");
		html=html.replace(/%types%/g,types);
		panel.innerHTML=html;
		if (config.browser.isGecko) { // FF3 FIXUP
			document.getElementById("attachSource").style.display="none";
			document.getElementById("attachFixPanel").style.display="block";
		}
		return panel;
	},
//}}}
//{{{
	toggleAttachPanel:
	function (e) {
		if (!e) var e = window.event;
		var parent=resolveTarget(e).parentNode;
		var panel = document.getElementById("_attachPanel");
		if (panel==undefined || panel.parentNode!=parent)
			panel=config.macros.attach.createAttachPanel(parent,"_attachPanel");
		var isOpen = panel.style.display=="block";
		if(config.options.chkAnimate)
			anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
		else
			panel.style.display = isOpen ? "none" : "block" ;
		e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();
		return(false);
	},
//}}}
//{{{
	formatListOptions:
	function(text) {
		if (!text || !text.trim().length) return "";
		// get MIME list content from text
		var parts=text.split("\n----\n");
		var out="";
		for (var p=0; p<parts.length; p++) {
			var lines=parts[p].split("\n");
			var label=lines.shift(); // 1st line=display text
			var value=lines.shift(); // 2nd line=item value
			out +='<option value="%1">%0</option>'.format([label,value]);
		}
		return out;
	},
//}}}
// // interface definition
//{{{
	css:
	".attachPanel { display: none; position:absolute; z-index:10; width:35em; right:105%; top:0em;\
		background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
		border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
		padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em; text-align:left }\
	.attachPanel form { display:inline;border:0;padding:0;margin:0; }\
	.attachPanel select { width:99%;margin:0px;font-size:8pt;line-height:110%;}\
	.attachPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\
	.attachPanel textarea { width:98%;margin:0px;height:2em;font-size:8pt;line-height:110%}\
	.attachPanel table { width:100%;border:0;margin:0;padding:0;color:inherit; }\
	.attachPanel tbody, .attachPanel tr, .attachPanel td { border:0;margin:0;padding:0;color:#000; }\
	.attachPanel .box { border:1px solid black; padding:.3em; margin:.3em 0px; background:#f8f8f8; \
		-moz-border-radius:5px;-webkit-border-radius:5px; }\
	.attachPanel .chk { width:auto;border:0; }\
	.attachPanel .btn { width:auto; }\
	.attachPanel .btn2 { width:49%; }\
	",
//}}}
//{{{
	html:
	'<form>\
		attach from source file\
		<input type="file" id="attachSource" name="source" size="56"\
			onChange="config.macros.attach.onChangeSource(this)">\
		<div id="attachFixPanel" style="display:none"><!-- FF3 FIXUP -->\
			<input type="text" id="attachFixSource" style="width:90%"\
				title="Enter a path/file to attach"\
				onChange="config.macros.attach.onChangeSource(this);">\
			<input type="button" style="width:7%" value="..."\
				title="Enter a path/file to attach"\
				onClick="config.macros.attach.askForFilename(document.getElementById(\'attachFixSource\'));">\
		</div><!--end FF3 FIXUP-->\
		<div class="box">\
		<table style="border:0"><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			embed data <input type=checkbox class=chk name="useData" %IEdisabled% \
				onclick="if (!this.form.MIMEType.value.length)\
					this.form.MIMEType.selectedIndex=this.checked?1:0; ">&nbsp;\
		</td><td style="border:0">\
			<select size=1 name="MIMEType" \
				onchange="this.title=this.value; if (this.value==\'editlist\')\
					{ this.selectedIndex=this.form.useData.checked?1:0; story.displayTiddler(null,config.macros.attach.typeList,2); return; }">\
				<option value=""></option>\
				%types%\
			</select>\
		</td></tr><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			local link <input type=checkbox class=chk name="useLocal"\
				onclick="this.form.local.value=this.form.local.defaultValue=this.checked?config.macros.attach.localPrompt:\'\';">&nbsp;\
		</td><td style="border:0">\
			<input type=text name="local" size=15 autocomplete=off value=""\
				onchange="this.form.useLocal.checked=this.value.length" \
				onkeyup="this.form.useLocal.checked=this.value.length" \
				onfocus="if (!this.value.length) this.value=config.macros.attach.localPrompt; this.select()">\
		</td></tr><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			remote link <input type=checkbox class=chk name="useURL"\
				onclick="this.form.URL.value=this.form.URL.defaultValue=this.checked?config.macros.attach.URLPrompt:\'\';\">&nbsp;\
		</td><td style="border:0">\
			<input type=text name="URL" size=15 autocomplete=off value=""\
				onfocus="if (!this.value.length) this.value=config.macros.attach.URLPrompt; this.select()"\
				onchange="this.form.useURL.checked=this.value.length;"\
				onkeyup="this.form.useURL.checked=this.value.length;">\
		</td></tr></table>\
		</div>\
		<table style="border:0"><tr style="border:0"><td style="border:0;text-align:right;vertical-align:top;width:1%;white-space:nowrap">\
			notes&nbsp;\
		</td><td style="border:0" colspan=2>\
			<textarea name="notes" style="width:98%;height:3.5em;margin-bottom:2px"></textarea>\
		</td><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			attach as&nbsp;\
		</td><td style="border:0" colspan=2>\
			<input type=text name="tiddlertitle" size=15 autocomplete=off value="%title%"\
				onkeyup="if (!this.value.length) { this.value=config.macros.attach.titlePrompt; this.select(); }"\
				onfocus="if (!this.value.length) this.value=config.macros.attach.titlePrompt; this.select()" %disabled%>\
		</td></tr></tr><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			add tags&nbsp;\
		</td><td style="border:0">\
			<input type=text name="tags" size=15 autocomplete=off value="" onfocus="this.select()">\
		</td><td style="width:40%;text-align:right;border:0">\
			<input type=button class=btn2 value="attach"\
				onclick="config.macros.attach.onClickAttach(this)"><!--\
			--><input type=button class=btn2 value="close"\
				onclick="var panel=document.getElementById(\'%id%\'); if (panel) panel.parentNode.removeChild(panel);">\
		</td></tr></table>\
	</form>',
//}}}
// // control processing
//{{{
	onChangeSource:
	function(here) {
		var form=here.form;
		var list=form.MIMEType;
		var theFilename  = here.value;
		var theExtension = theFilename.substr(theFilename.lastIndexOf('.')).toLowerCase();
		// if theFilename is in current document folder, remove path prefix and use relative reference
		var h=document.location.href; folder=getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf("/")+1)));
		if (theFilename.substr(0,folder.length)==folder) theFilename='./'+theFilename.substr(folder.length);
		else theFilename='file:///'+theFilename; // otherwise, use absolute reference
		theFilename=theFilename.replace(/\\/g,"/"); // fixup: change \ to /
		form.useLocal.checked = true;
		form.local.value = theFilename;
		form.useData.checked = !form.useData.disabled;
		list.selectedIndex=1;
		for (var i=0; i<list.options.length; i++) // find matching MIME type
			if (list.options[i].value.indexOf(theExtension)!=-1) { list.selectedIndex = i; break; }
		if (!form.tiddlertitle.disabled)
			form.tiddlertitle.value=theFilename.substr(theFilename.lastIndexOf('/')+1); // get tiddlername from filename
	},
//}}}
//{{{
	onClickAttach:
	function (here) {
		clearMessage();
		// get input values
		var form=here.form;
		var src=form.source; if (config.browser.isGecko) src=document.getElementById("attachFixSource");
		src=src.value!=src.defaultValue?src.value:"";
		var when=(new Date()).formatString(config.macros.timeline.dateFormat);
		var title=form.tiddlertitle.value;
		var local = form.local.value!=form.local.defaultValue?form.local.value:"";
		var url = form.URL.value!=form.URL.defaultValue?form.URL.value:"";
		var notes = form.notes.value;
		var tags = "attachment excludeMissing "+form.tags.value;
		var useData=form.useData.checked;
		var useLocal=form.useLocal.checked;
		var useURL=form.useURL.checked;
		var mimetype = form.MIMEType.value.length?form.MIMEType.options[form.MIMEType.selectedIndex].text:"";
		// validate checkboxes and get filename
		if (useData) {
			if (src.length) { if (!theLocation) var theLocation=src; }
			else { alert(this.sourceErr); src.focus(); return false; }
		}
		if (useLocal) {
			if (local.length) { if (!theLocation) var theLocation = local; }
			else { alert(this.localErr); form.local.focus(); return false; }
		}
		if (useURL) {
			if (url.length) { if (!theLocation) var theLocation = url; }
			else { alert(this.URLErr); form.URL.focus(); return false; }
		}
		if (!(useData||useLocal||useURL))
			{ form.useData.focus(); alert(this.storageErr); return false; }
		if (!theLocation)
			{ src.focus(); alert(this.sourceErr); return false; }
		if (!title || !title.trim().length || title==this.titlePrompt)
			{ form.tiddlertitle.focus(); alert(this.tiddlerErr); return false; }
		// if not already selected, determine MIME type based on filename extension (if any)
		if (useData && !mimetype.length && theLocation.lastIndexOf('.')!=-1) {
			var theExt = theLocation.substr(theLocation.lastIndexOf('.')).toLowerCase();
			var theList=form.MIMEType;
			for (var i=0; i<theList.options.length; i++)
				if (theList.options[i].value.indexOf(theExt)!=-1)
					{ var mimetype=theList.options[i].text; theList.selectedIndex=i; break; }
		}
		// attach the file
		return this.createAttachmentTiddler(src, when, notes, tags, title,
			useData, useLocal, useURL, local, url, mimetype);
	},
	getMIMEType:
	function(src,def) {
		var ext = src.substr(src.lastIndexOf('.')).toLowerCase();
		var list=store.getTiddlerText(this.typeList);
		if (!list || !list.trim().length) return def;
		// get MIME list content from tiddler
		var parts=list.split("\n----\n");
		for (var p=0; p<parts.length; p++) {
			var lines=parts[p].split("\n");
			var mime=lines.shift(); // 1st line=MIME type
			var match=lines.shift(); // 2nd line=matching extensions
			if (match.indexOf(ext)!=-1) return mime;
		}
		return def;
	},
	createAttachmentTiddler:
	function (src, when, notes, tags, title, useData, useLocal, useURL, local, url, mimetype, noshow) {
		if (useData) { // encode the data
			if (!mimetype.length) {
				alert(this.MIMEErr);
				form.MIMEType.selectedIndex=1; form.MIMEType.focus();
				return false;
			}
			var d = this.readFile(src); if (!d) { return false; }
			displayMessage('encoding '+src);
			var encoded = this.encodeBase64(d);
			displayMessage('file size='+d.length+' bytes, encoded size='+encoded.length+' bytes');
		}
		var usage=(mimetype.substr(0,5)=="image"?'[img[%0]]':'[[%0|%0]]').format([title]);
		var theText=this.tiddlerFormat.format([
			usage, notes.length?notes:'//none//', mimetype,
			useLocal?local.replace(/\\/g,'/'):'', useURL?url:'',
			useData?('data:'+mimetype+';base64,'+encoded):'' ]);
		store.saveTiddler(title,title,theText,config.options.txtUserName,new Date(),tags);
		var panel=document.getElementById("attachPanel"); if (panel) panel.style.display="none";
		if (!noshow) { story.displayTiddler(null,title); story.refreshTiddler(title,null,true); }
		displayMessage('attached "'+title+'"');
		return true;
	},
//}}}
// // base64 conversion
//{{{
	encodeBase64:
	function (d) {
		if (!d) return null;
		// encode as base64
		var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		var out="";
		var chr1,chr2,chr3="";
		var enc1,enc2,enc3,enc4="";
		for (var count=0,i=0; i<d.length; ) {
			chr1=d.charCodeAt(i++);
			chr2=d.charCodeAt(i++);
			chr3=d.charCodeAt(i++);
			enc1=chr1 >> 2;
			enc2=((chr1 & 3) << 4) | (chr2 >> 4);
			enc3=((chr2 & 15) << 2) | (chr3 >> 6);
			enc4=chr3 & 63;
			if (isNaN(chr2)) enc3=enc4=64;
			else if (isNaN(chr3)) enc4=64;
			out+=keyStr.charAt(enc1)+keyStr.charAt(enc2)+keyStr.charAt(enc3)+keyStr.charAt(enc4);
			chr1=chr2=chr3=enc1=enc2=enc3=enc4="";
		}
		return out;
	},
	decodeBase64: function(input) {
		var out="";
		var chr1,chr2,chr3;
		var enc1,enc2,enc3,enc4;
		var i = 0;
		// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
		input=input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
		do {
			enc1=keyStr.indexOf(input.charAt(i++));
			enc2=keyStr.indexOf(input.charAt(i++));
			enc3=keyStr.indexOf(input.charAt(i++));
			enc4=keyStr.indexOf(input.charAt(i++));
			chr1=(enc1 << 2) | (enc2 >> 4);
			chr2=((enc2 & 15) << 4) | (enc3 >> 2);
			chr3=((enc3 & 3) << 6) | enc4;
			out=out+String.fromCharCode(chr1);
			if (enc3!=64) out=out+String.fromCharCode(chr2);
			if (enc4!=64) out=out+String.fromCharCode(chr3);
		} while (i<input.length);
		return out;
	},
//}}}
// // I/O functions
//{{{
	readFile: // read local BINARY file data
	function(filePath) {
		if(!window.Components) { return null; }
		try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
		catch(e) { alert("access denied: "+filePath); return null; }
		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		try { file.initWithPath(filePath); } catch(e) { alert("cannot read file - invalid path: "+filePath); return null; }
		if (!file.exists()) { alert("cannot read file - not found: "+filePath); return null; }
		var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
		inputStream.init(file, 0x01, 00004, null);
		var bInputStream = Components.classes["@mozilla.org/binaryinputstream;1"].createInstance(Components.interfaces.nsIBinaryInputStream);
		bInputStream.setInputStream(inputStream);
		return(bInputStream.readBytes(inputStream.available()));
	},
//}}}
//{{{
	writeFile:
	function(filepath,data) {
		// TBD: decode base64 and write BINARY data to specified local path/filename
		return(false);
	},
//}}}
//{{{
	askForFilename: // for FF3 fixup
	function(target) {
		var msg=config.messages.selectFile;
		if (target && target.title) msg=target.title; // use target field tooltip (if any) as dialog prompt text
		// get local path for current document
		var path=getLocalPath(document.location.href);
		var p=path.lastIndexOf("/"); if (p==-1) p=path.lastIndexOf("\\"); // Unix or Windows
		if (p!=-1) path=path.substr(0,p+1); // remove filename, leave trailing slash
		var file=""
		var result=window.mozAskForFilename(msg,path,file,true); // FF3 FIXUP ONLY
		if (target && result.length) // set target field and trigger handling
			{ target.value=result; target.onchange(); }
		return result; 
	}
};
//}}}
//{{{
if (window.mozAskForFilename===undefined) { // also defined by CoreTweaks (for ticket #604)
	window.mozAskForFilename=function(msg,path,file,mustExist) {
		if(!window.Components) return false;
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, mustExist?nsIFilePicker.modeOpen:nsIFilePicker.modeSave);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel)
				var result=picker.file.persistentDescriptor;
		}
		catch(ex) { displayMessage(ex.toString()); }
		return result;
	}
}
//}}}
/***
|Name|AttachFilePluginFormatters|
|Source|http://www.TiddlyTools.com/#AttachFilePluginFormatters|
|Version|4.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1.3|
|Type|plugin|
|Description|run-time library for displaying attachment tiddlers|
Runtime processing for //rendering// attachment tiddlers created by [[AttachFilePlugin]].   Attachment tiddlers are tagged with<<tag attachment>>and contain binary file content (e.g., jpg, gif, pdf, mp3, etc.) that has been stored directly as base64 text-encoded data or can be loaded from external files stored on a local filesystem or remote web server.  Note: after creating new attachment tiddlers, you can remove [[AttachFilePlugin]], as long as you retain //this// tiddler (so that images can be rendered later on).
!!!!!Formatters
<<<
This plugin extends the behavior of the following TiddlyWiki core "wikify()" formatters:
* embedded images: {{{[img[tooltip|image]]}}}
* linked embedded images: {{{[img[tooltip|image][link]]}}}
* external/"pretty" links: {{{[[label|link]]}}}
''Please refer to AttachFilePlugin (source: http://www.TiddlyTools.com/#AttachFilePlugin) for additional information.''
<<<
!!!!!Revisions
<<<
2009.10.10 [4.0.1] in fileExists(), check for IE to avoid hanging Chrome during startup
2009.06.04 [4.0.0] changed attachment storage format to use //sections// instead of embedded substring markers.
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.10.29 [3.7.0] more code reduction: removed upload handling from AttachFilePlugin (saves ~7K!)
2007.10.28 [3.6.0] removed duplicate formatter code from AttachFilePlugin (saves ~10K!) and updated documentation accordingly.  This plugin ([[AttachFilePluginFormatters]]) is now //''required''// in order to display attached images/binary files within tiddler content.
2006.05.20 [3.4.0] through 2007.03.01 [3.5.3] sync with AttachFilePlugin
2006.05.13 [3.2.0] created from AttachFilePlugin v3.2.0
<<<
!!!!!Code
***/
// // version
//{{{
version.extensions.AttachFilePluginFormatters= {major: 4, minor: 0, revision: 1, date: new Date(2009,10,10)};
//}}}

//{{{
if (config.macros.attach==undefined) config.macros.attach= { };
//}}}
//{{{
if (config.macros.attach.isAttachment==undefined) config.macros.attach.isAttachment=function (title) {
	var tiddler = store.getTiddler(title);
	if (tiddler==undefined || tiddler.tags==undefined) return false;
	return (tiddler.tags.indexOf("attachment")!=-1);
}
//}}}

//{{{
// test for local file existence - returns true/false without visible error display
if (config.macros.attach.fileExists==undefined) config.macros.attach.fileExists=function(f) {
	if(window.Components) { // MOZ
		try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
		catch(e) { return false; } // security access denied
		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		try { file.initWithPath(f); }
		catch(e) { return false; } // invalid directory
		return file.exists();
	}
	else if (config.browser.isIE) { // IE
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		return fso.FileExists(f);
	}
	else return true; // other browsers: assume file exists
}
//}}}

//{{{
if (config.macros.attach.getAttachment==undefined) config.macros.attach.getAttachment=function(title) {

	// extract embedded data, local and remote links (if any)
	var text=store.getTiddlerText(title,'');
	var embedded=store.getTiddlerText(title+'##data','').trim();
	var locallink=store.getTiddlerText(title+'##file','').trim();
	var remotelink=store.getTiddlerText(title+'##url','').trim();

	// backward-compatibility for older attachments (pre 4.0.0)
	var startmarker="---BEGIN_DATA---\n";
	var endmarker="\n---END_DATA---";
	var pos=0; var endpos=0;
	if ((pos=text.indexOf(startmarker))!=-1 && (endpos=text.indexOf(endmarker))!=-1)
		embedded="data:"+(text.substring(pos+startmarker.length,endpos)).replace(/\n/g,'');
	if ((pos=text.indexOf("/%LOCAL_LINK%/"))!=-1)
		locallink=text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));
	if ((pos=text.indexOf("/%REMOTE_LINK%/"))!=-1)
		remotelink=text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));

	// if there is a data: URI defined (not supported by IE)
	if (embedded.length && !config.browser.isIE) return embedded;

	// document is being served remotely... use remote URL (if any)  (avoids security alert)
	if (remotelink.length && document.location.protocol!="file:")
		return remotelink;  

	// local link only... return link without checking file existence (avoids security alert)
	if (locallink.length && !remotelink.length) 
		return locallink; 

	// local link, check for file exist... use local link if found
	if (locallink.length) { 
		locallink=locallink.replace(/^\.[\/\\]/,''); // strip leading './' or '.\' (if any)
		if (this.fileExists(getLocalPath(locallink))) return locallink;
		// maybe local link is relative... add path from current document and try again
		var pathPrefix=document.location.href;  // get current document path and trim off filename
		var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
		if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
		if (this.fileExists(getLocalPath(pathPrefix+locallink))) return locallink;
	}

	// no embedded data, no local (or not found), fallback to remote URL (if any)
	if (remotelink.length) return remotelink;

	// attachment URL doesn't resolve, just return input as is
	return title;
}
//}}}
//{{{
if (config.macros.attach.init_formatters==undefined) config.macros.attach.init_formatters=function() {
	if (this.initialized) return;

	// find the formatter for "image" and replace the handler
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="image"; i++);
	if (i<config.formatters.length)	config.formatters[i].handler=function(w) {
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link
			{
			var e = w.output;
			if(lookaheadMatch[5])
				{
				var link = lookaheadMatch[5];
				// ELS -------------
				var external=config.formatterHelpers.isExternalLink(link);
				if (external)
					{
					if (config.macros.attach.isAttachment(link))
						{
						e = createExternalLink(w.output,link);
						e.href=config.macros.attach.getAttachment(link);
						e.title = config.macros.attach.linkTooltip + link;
						}
					else
						e = createExternalLink(w.output,link);
					}
				else 
					e = createTiddlyLink(w.output,link,false,null,w.isStatic);
				// ELS -------------
				addClass(e,"imageLink");
				}
			var img = createTiddlyElement(e,"img");
			if(lookaheadMatch[1])
				img.align = "left";
			else if(lookaheadMatch[2])
				img.align = "right";
			if(lookaheadMatch[3])
				img.title = lookaheadMatch[3];
			img.src = lookaheadMatch[4];
			// ELS -------------
			if (config.macros.attach.isAttachment(lookaheadMatch[4]))
				img.src=config.macros.attach.getAttachment(lookaheadMatch[4]);
			// ELS -------------
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
//}}}
//{{{
	// find the formatter for "prettyLink" and replace the handler
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="prettyLink"; i++);
	if (i<config.formatters.length)	{
		config.formatters[i].handler=function(w) {
			this.lookaheadRegExp.lastIndex = w.matchStart;
			var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
			if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
				var e;
				var text = lookaheadMatch[1];
				if(lookaheadMatch[3]) {
					// Pretty bracketted link
					var link = lookaheadMatch[3];
					if (config.macros.attach.isAttachment(link)) {
						e = createExternalLink(w.output,link);
						e.href=config.macros.attach.getAttachment(link);
						e.title=config.macros.attach.linkTooltip+link;
					}
					else e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link))
						? createExternalLink(w.output,link)
						: createTiddlyLink(w.output,link,false,null,w.isStatic);
				} else {
					e = createTiddlyLink(w.output,text,false,null,w.isStatic);
				}
				createTiddlyText(e,text);
				w.nextMatch = this.lookaheadRegExp.lastIndex;
			}
		}
	} // if "prettyLink" formatter found
	this.initialized=true;
}
//}}}
//{{{
config.macros.attach.init_formatters(); // load time init
//}}}
//{{{
if (TiddlyWiki.prototype.coreGetRecursiveTiddlerText==undefined) {
	TiddlyWiki.prototype.coreGetRecursiveTiddlerText = TiddlyWiki.prototype.getRecursiveTiddlerText;
	TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,depth) {
		return config.macros.attach.isAttachment(title)?
			config.macros.attach.getAttachment(title):this.coreGetRecursiveTiddlerText.apply(this,arguments);
	}
}
//}}}
/***
|Name|AttachFilePluginInfo|
|Source|http://www.TiddlyTools.com/#AttachFilePlugin|
|Documentation|http://www.TiddlyTools.com/#AttachFilePluginInfo|
|Version|4.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Documentation for AttachFilePlugin|
Store or link binary files (such as jpg, gif, pdf or even mp3) within your TiddlyWiki document and then use them as images or links from within your tiddler content.
!!!!!Inline interface (live)
>see [[AttachFile]] (shadow tiddler)
><<tiddler AttachFile>>
!!!!!Syntax
<<<
''To display the attach file control panel, simply view the [[AttachFile]] shadow tiddler that is automatically created by the plugin, and contains an instance of the inline control panel.''.  Or, you can write:
{{{
<<attach inline>>
}}}
in any tiddler to display the control panel embedded within that tiddler.  Note: you can actually use any unique identifier in place of the "inline" keyword.  Each unique id creates a separate instance of the controls.  If the same ID is used in more than one tiddler, then the control panel is automatically moved to the most recently rendered location.  Or, you can write:
{{{
<<attach>>
}}}
(with no ID parameter) in SidebarOptions.  This adds a command link that opens the controls as a floating panel, positioned directly to the left of the sidebar.
<<<
!!!!!Usage
<<<
Binary file content can be stored in three different locations:
#embedded in the attachment tiddler (encoded as base64)
#on your filesystem (a 'local link' path/filename)
#on a web server (a 'remote link' URL)
The plugin creates an "attachment tiddler" for each file you attach.  Regardless of where you store the binary content, your document can refer to the attachment tiddler rather than using a direct file or URL reference in your embedded image or external links, so that changing document locations will not require updating numerous tiddlers or copying files from one system to another.
> Important note: As of version 3.6.0, in order to //render// images and other binary attachments created with this plugin, you must also install [[AttachFilePluginFormatters]], which extends the behavior of the TiddlyWiki core formatters for embedded images ({{{[img[tooltip|image]]}}}), linked embedded images ({{{[img[tooltip|image][link]]}}}), and external/"pretty" links ({{{[[label|link]]}}}), so that these formatter will process references to attachment tiddlers as if a normal file reference had been provided. |
When you attach a file, a tiddler (tagged with<<tag attachment>>) is generated (using the source filename as the tiddler's title).  The tiddler contains //''base64 text-encoded binary data''//, surrounded by {{{/%...%/}}} comment markers (so they are not visible when viewing the tiddler).  The tiddler also includes summary details about the file: when it was attached, by whom, etc. and, if the attachment is an image file (jpg, gif, or png), the image is automatically displayed below the summary information.
>Note: although you can edit an attachment tiddler, ''don't change any of the encoded content below the attachment header'', as it has been prepared for use in the rest of your document, and even changing a single character can make the attachment unusable.  //If needed, you ''can'' edit the header information or even the MIME type declaration in the attachment data, but be very careful not to change any of the base64-encoded binary data.//
With embedded data, your TW document can be completely self-contained...unfortunately, embedding just a few moderately-sized binary files using base64 text-encoding can dramatically increase the size of your document.   To avoid this problem, you can create attachment tiddlers that define external local filesystem (file://) and/or remote web server (http://) 'reference' links, without embedding the binary data directly in the tiddler (i.e., uncheck "embed data" in the 'control panel').

These links provide an alternative source for the binary data: if embedded data is not found (or you are running on Internet Explorer, which does not currently support using embedded data), then the plugin tries the local filesystem reference.  If a local file is not found, then the remote reference (if any) is used.  This "fallback" approach also lets you 'virtualize' the external links in your document, so that you can access very large binary content such as PDFs, MP3's, and even *video* files, by using just a 'remote reference link' without embedding any data or downloading huge files to your hard disk.

Of course, when you //do// download an attached file, the local copy will be used instead of accessing a remote server each time, thereby saving bandwidth and allowing you to 'go mobile' without having to edit any tiddlers to alter the link locations...
<<<
!!!!!Syntax / Examples
<<<
To embed attached files as images or link to them from other tiddlers, use the standard ~TiddlyWiki image syntax ({{{[img[tooltip|filename]]}}}), linked image syntax ({{{[img[tooltip|filename][tiddlername]]}}}) , or "external link" syntax ({{{[[text|URL]]}}}), replacing the filename or URL that is normally entered with the title of an attachment tiddler.

embedded image data:
>{{{[img[Meow|AttachFileSample]]}}}
>[img[Meow|AttachFileSample]]
embedded image data with link to larger remote image:
>{{{[img[click for larger view|AttachFileSample][AttachFileSample2]]}}}
>[img[click for larger view|AttachFileSample][AttachFileSample2]]
'external' link to embedded image data:
>{{{[[click to view attachment|AttachFileSample]]}}}
>[[click to view attachment|AttachFileSample]]
'external' link to remote image:
>{{{[[click to view attachment|AttachFileSample2]]}}}
>[[click to view attachment|AttachFileSample2]]
regular ~TiddlyWiki links to attachment tiddlers:
>{{{[[AttachFileSample]]}}} [[AttachFileSample]]
>{{{[[AttachFileSample2]]}}} [[AttachFileSample2]]
<<<
!!!!!Defining MIME types
<<<
When you select a source file, a ''[[MIME|http://en.wikipedia.org/wiki/MIME]]'' file type is automatically suggested, based on filename extension.  The AttachFileMIMETypes tiddler defines the list of MIME types that will be recognized by the plugin.  Each MIME type definition consists of exactly two lines of text: the official MIME type designator (e.g., "text/plain", "image/gif", etc.), and a space-separated list of file extensions associated with that type.  List entries are separated by "----" (horizontal rules).
<<<
!!!!!Known Limitations
<<<
Internet Explorer does not support the data: URI scheme, and cannot use the //embedded// data to render images or links.  However, you can still use the local/remote link definitions to create file attachments that are stored externally.  In addition, while it is relatively easy to read local //text// files, reading binary files is not directly supported by IE's FileSystemObject (FSO) methods, and other file I/O techniques are subject to security barriers or require additional MS proprietary technologies (like ASP or VB) that make implementation more difficult.  As a result, you cannot //create// new attachment tiddlers using IE.
<<<
!!!!!Installation
<<<
Import (or copy/paste) the following tiddlers into your document:
* [[AttachFilePlugin]] (tagged with <<tag systemConfig>>)
* [[AttachFilePluginFormatters]] ("runtime distribution library") (tagged with <<tag systemConfig>>)
* [[AttachFileSample]] and [[AttachFileSample2]] //(tagged with <<tag attachment>>)//
* [[AttachFileMIMETypes]] //(defines binary file types)//
> Important note: As of version 3.6.0, in order to //render// images and other binary attachments created with this plugin, you must also install [[AttachFilePluginFormatters]], which extends the behavior of the TiddlyWiki core formatters for embedded images ({{{[img[tooltip|image]]}}}), linked embedded images ({{{[img[tooltip|image][link]]}}}), and external/"pretty" links ({{{[[label|link]]}}}), so that these formatter will process references to attachment tiddlers as if a normal file reference had been provided. |
<<<
!!!!!Revisions
<<<
2009.06.04 [4.0.0] changed attachment storage format to use //sections// instead of embedded substring markers.
2008.07.21 [3.9.0] Fixup for FireFox 3: use HTML with separate text+button control instead of type='file' control
2008.05.12 [3.8.1] automatically add 'attach' task to backstage (moved from BackstageTweaks)
2008.04.09 [3.8.0] in onChangeSource(), if source matches current document folder, use relative reference for local link.  Also, disable 'embed' when using IE (which //still// doesn't support data: URI)
2008.04.07 [3.7.3] fixed typo in HTML for 'local file link' so that clicking in input field doesn't erase current path/file (if any)
2008.04.07 [3.7.2] auto-create AttachFile shadow tiddler for inline interface
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.12.03 [3.7.1] in createAttachmentTiddler(), added optional "noshow" flag to suppress display of newly created tiddlers.
2007.10.29 [3.7.0] code reduction: removed support for built-in upload to server... on-line hosting of binary attachments is left to the document author, who can upload/host files using 3rd-party web-based services (e.g. www.flickr.com, ) or stand-alone applications (e.g., FTP).
2007.10.28 [3.6.0] code reduction: removed duplicate definition of image and prettyLink formatters.  Rendering of attachment tiddlers now //requires// installation of AttachFilePluginFormatters
2007.03.01 [3.5.3] use apply() to invoke hijacked function
2007.02.25 [3.5.2] in hijack of "prettyLink", fix version check for TW2.2 compatibility (prevent incorrect use of fallback handler)
2007.01.09 [3.5.1] onClickAttach() refactored to create separate createAttachmentTiddler() API for use with FileDropPluginHandlers
2006.11.30 [3.5.0] in getAttachment(), for local references, add check for file existence and fallback to remote URL if local file not found.  Added fileExists() to encapsulate FF vs. IE local file test function (IE FSO object code is TBD).
2006.11.29 [3.4.8] in hijack for PrettyLink, 'simple bracketed link' opens tiddler instead of external link to attachment
2006.11.29 [3.4.7] in readFile(), added try..catch around initWithPath() to handle invalid/non-existent paths better.
2006.11.09 [3.4.6] REAL FIX for TWv2.1.3: incorporate new TW2.1.3 core "prettyLink" formatter regexp handling logic and check for version < 2.1.3 with fallback to old plugin code.  Also, cleanup table layout in HTML (added "border:0" directly to table elements to override stylesheet)
2006.11.08 [3.4.5] TEMPORARY FIX for TWv2.1.3: disable hijack of wikiLink formatter due to changes in core wikiLink regexp definition.  //Links to attachments are broken, but you can still use {{{[img[TiddlerName]]}}} to render attachments as images, as well as {{{background:url('[[TiddlerName]]')}}} in CSS declarations for background images.//
2006.09.10 [3.4.4] update formatters for 2.1 compatibility (use this.lookaheadRegExp instead of temp variable)
2006.07.24 [3.4.3] in prettyLink formatter, added check for isShadowTiddler() to fix problem where shadow links became external links.
2006.07.13 [3.4.2] in getAttachment(), fixed stripping of newlines so data: used in CSS will work
2006.05.21 [3.4.1] in getAttachment(), fixed substring() to extract data: URI (was losing last character, which broken rendering of SOME images)
2006.05.20 [3.4.0] hijack core getRecursiveTiddlerText() to support rendering attachments in stylesheets (e.g. {{{url([[AttachFileSample]])}}})
2006.05.20 [3.3.6] add "description" feature to easily include notes in attachment tiddler (you can always edit to add them later... but...)
2006.05.19 [3.3.5] add "attach as" feature to change default name for attachment tiddlers.  Also, new optional param to specify tiddler name (disables editing)
2006.05.16 [3.3.0] completed XMLHttpRequest handling for GET or POST to configurable server scripts
2006.05.13 [3.2.0] added interface for upload feature.  Major rewrite of code for clean object definitions.  Major improvements in UI interaction and validation.
2006.05.09 [3.1.1] add wikifer support for using attachments in links from "linked image" syntax: {{{[img[tip|attachment1][attachment2]]}}}
2006.05.09 [3.1.0] lots of code changes: new options for attachments that use embedded data and/or links to external files (local or remote)
2006.05.03 [3.0.2] added {{{/%...%/}}} comments around attachment data to hide it when viewing attachment tiddler.
2006.02.05 [3.0.1] wrapped wikifier hijacks in initAttachmentFormatters() function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
2005.12.27 [3.0.0] Update for TW2.0.  Automatically add 'excludeMissing' tag to attachments
2005.12.16 [2.2.0] Dynamically create/remove attachPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding.
2005.11.20 [2.1.0] added wikifier handler extensions for "image" and "prettyLink" to render tiddler attachments
2005.11.09 [2.0.0] begin port from old ELS Design adaptation based on ~TW1.2.33
2005.07.20 [1.0.0] Initial release (as adaptation)
<<<
/***
|''Name''|BetaUpgradePlugin|
|''Description''|change the upgrade source to the beta location|
|''~CoreVersion''|2.4.0|
|''Source''|http://svn.tiddlywiki.org/Trunk/associations/plugins/|
|''CodeRepository''|http://svn.tiddlywiki.org|
***/
//{{{
config.macros.upgrade.source = "http://www.tiddlywiki.com/beta/upgrade.html";
//}}}
Replace this text with links to tiddlers.
This page describes some issues with particular browsers/configurations. In addition to these notes you can also goto
* http://tiddlywiki.com/#Installation%20ServicePack2Problems%20Browsers
* http://tiddlywiki.org/wiki/How_To/Configure_your_browser_to_allow_saves_to_disk

{{sectionTOC{}}}

! Firefox

This problem was observed on:

* Kubuntu/Ubuntu version 3.0.13 of Firefox
* Windows XP version 3.5.3 of Firefox

!! When the cookie's keep option is set to "Ask me always"

You will be prompted for every cookie change associated with options changes or changing/displaying the tab interface.

The only workaround at this point it to change the "ask me always" setting to some other level. You can also create a new profile for Firefox that you use specifically for the coursebook and other """file://""" web applications with a compatible setting for the keep option.

Aspects of this bug are described in:

* https://bugzilla.mozilla.org/show_bug.cgi?id=440973
* https://bugzilla.mozilla.org/show_bug.cgi?id=430045
* https://bugzilla.mozilla.org/show_bug.cgi?id=452575

! Internet Explorer

These problems were observed on MS Windows XP version 8, 7, 6 of Internet Explorer.

!! Goto box requires scrolling to display full tiddler titles (IE)

Unlike Firefox, the list of tiddlers that match the text typed into the Goto box at the upper right of the page is totally off the screen in the compatibility mode of IE 8, IE 7 and IE 6. What you type in is being matched, and you can use the horizontal scroll bar to see the full tiddler titles.

In IE 8 standards display mode the tiddler list is [[partly off the screen as with Safari|here##Goto box requires scrolling to display full tiddler titles (safari)]].

!! Presentation and Chapters selection listbox truncates the titles

In Firefox the dropdown list that is displayed by the select box for presentations or chapters grows to display the entire name of the tiddlers. In IE however this doesn't happen, the size of the dropdown is the same as the size of the selector box.

Because of this, the links in the main menu for each presentation and chapter are provided as an index of what is covered in each presentation/chapter.

! Safari

These problems were observed on Windows XP version 4.0.3 of Safari.

!! Goto box requires scrolling to display full tiddler titles (safari)

Unlike Firefox, the list of tiddlers that match the text typed into the Goto box at the upper right of the page is partly off the screen. You need to use the horizontal scroll bar to see the full tiddler titles.

! Opera

These problems were observed on MS Windows XP version 10.0 of Opera.

!! Goto box requires scrolling to display full tiddler titles (Opera)

In opera tiddler list is [[partly off the screen as with Safari|here##Goto box requires scrolling to display full tiddler titles (safari)]]. Also it covers the input box so you can't see what you are typing.

!! Can't synchronize/load content from the internet
Similar to Chrome there is something preventing http requests from completing. The dragonfly debugger in Opera doesn't show any network activity when using the link on the [[sync]] page or when updating the rss feed in [[ContentChanges]]. Similar to Chrome, it appears the ~XmlHttpRequest is disabled for local files as desribed by http://operawiki.info./XMLHttpRequest and http://www.opera.com/docs/specs/presto211/security/ (look for {{{Local HTML accessing sites..}}}).

! Google Chrome

These problems were observed on MS Windows XP version 3.0.195.10 of Google Chrome.

!! Can't synchronize/load content from the internet (chrome)

Apparently something in chrome's support for ~XmlHttpRequest doesn't work correctly with tiddlywiki. This prevents the sync and rss feed reading mechanisms from working. However an already loaded coursebook does function under chrome.

It appears ~XMLHttpRequest is disabled for """file://""" url's as a security measure. Some details can be found at: http://www.informationweek.com/news/internet/browsers/showArticle.jhtml?articleID=212202252, http://code.google.com/p/chromium/issues/detail?id=4951. 

!! Unable to store cookies for local files

Cookies for """file://""" are disabled for security reasons.  Starting chrome with the {{{--enable-file-cookies}}} option will permit cookies to be used. Details are at: http://code.google.com/p/chromium/issues/detail?id=535.
This means that options can't be saved for the tiddlywiki including username.
Here are some Bugs or feature requests for the plugins.
{{sectionTOC{@@font-style: bold;List of Bugs/Features@@}}}

! Notebook plugin use with part tiddlers
When a part tiddler (e.g. [[Glossary/sync]]) is displayed there is a notebook also displayed. Which is expected, but the entries done there aren't included in the Glossary tiddler so when the student looks at the Glossary it looks like his notes have dissapeared. They haven't they are just not named properly to be dislayed in the Glossary tiddler context.

!! Possible solutions
Use jQuery to add links to the additional notes tiddlers by scanning for {{{<part name>>}}} entries in the tiddler and creating a link to each existing subtiddler note. Could also include the content from these subtiddler notes, but then editing the note does not have the included content.

! SiteUrl and slices for external urls.

need to make sure they are all the same page. have some for bblisa and some for LISA itself.
need to reconcile.

! ToggleFullScreen

The entry in the main menu for this toggle displays "Toggle Fullscreen" until used. Then it is stuck on "restore" untill the tw is reloaded. When looking at MainMenu in the story column it does properly
toggle.  Maybe a missing refresh of the main menu column when going to multi column mode?

! FootnotePlugin

Breaks with tiddler is null error when using ExportTiddlers to save rss feed. Partial fix:

Place
{{{
 if (!story.findContainingTiddler(place)) return;
}}}

at top of handler so it returns. However another issue. If using the TiddlerNotes plugin, the footnotes are rendered below the notes. And the structure is wrong:

{{{
 div id=tiddler...
   ...
   div class=viewer
   div class=notes viewer
         div id=notesContainer.... class=TiddlerNotes
         div class=footnoteholder
              ol ...
}}}

The footnoteholder div should either be inside the viewer div or between the viewer div and the notes/viewer div.
Where it is now means that hiding the notes class (for printing) also hides the footnotes. Also the footnote
current location places it well away from the viewer tiddler that it is really a part of.

! SlideShowPlugin

!! alternate text

It can't handle:
{{{
[[Welcome to the Class|Slide Welcome]]
[[Slide 2]]
}}}
will skip first slide"Slide Welcome" and start withe "Slide 2". Needs to resolve slide properly.

!! excluding wiki words from slide show

Following a wikiword with a : stops the slide show plugin from treating that page as a slide.
Is this intentional? If so needs to be documented. Allows slideshow template to be annotated
for reading through rather than just presenting.

!! slideshow macro doesn't take name of the tiddler to show

Makes it impossible to have a single page where clicking on a macro starts
that slide show. E.G. I want:

{{{
<<slideShow options tiddler:[[use me for list of tiddlers]]>>
<<slideShow options tiddler:SlideShow1>>
}}}

!! Way to change clock and other options setting according to style sheet

Can the stylesheet set default options for clock ...

!! slideshow macro can't be included via tiddler

I would like to include a single control tiddler with the slideshow macro's predefined. So I can have tiddlers with:

{{{
Instructor show with theme InstructorSlideShowTheme:
  <<slideShow  theme:InstructorSlideShowTheme toc:titles footer:"copyright(c) John Rouillard 2009" clock:+>>
}}}

and
{{{
Student show using  {{comment{SlideShowStyleSheet}}}:
  <<slideShow noClicks noKeyboard toc:titles >>

Print show with theme PrintingSlideShowTheme:
  <<slideShow showAll theme:PrintingSlideShowTheme >>
}}}

and then include these tiddlers at the end of a slide show presentation tiddler with:
{{{
<<tiddler InstructorShow>>
<<tiddler StudentShow>>
}}}

allowing a common look/set of instructions to all the slideshows to be changed without having to visit each show.

!! tiddlers being edited are not hidden when slideshow is started.

any tiddlers being edited are displayed below the slides in the slideshow.

While my claim is you shouldn't be editing any tiddlers during a preso...

Hiding tiddlers being edited should not prevent editing of the tiddler when in slideshow mode.
(e.g. if a TiddlerNotesPlugin note is displayed, it should be able to be edited).

!! Doc bug label and tooltip not documented

changes hover text and text of label in button.

!! slide show pulldown TOC menu needs numbered list

The slideshow pulldown menu needs to autogenerate a number for each slide listed so it can be used in the goto slide entry box.

!! Background of slideshow TOC pulldown isn't opaque

At least in one of my examples, not opaque. Maybe a missing stylesheet setting?? I can see rules on the slide behind it.

!! per slide delay in autoplay mode

Allow setting of a default and a per slide (e.g. for slides that have more/less material on them) advance value.
Can be an absolute setting or maybe multipler/percentage (2%-2000%) of the default value set on the slide show macro line.

Have an autoplay show for students when they enter. title and welcome message need little time on screen, directions
should take upmost of the time.

! GotoPlugin
On some browsers, notably IE, the suggestion list is displayed to the right of the entry box which places it off screen if the goto box is placed in SideBarOptions.
Firefox works better in this regard as the suggestion box is displayed below the entry box.

! StorySaverPlugin

!! Allow links in story tiddler that are not part of the story.

I have a couple of use cases for a story where it would be useful to be able to include a tiddler reference but not have it opened as part of a story. Is it possible to enclose test in a class like noStory to exclude the text in that section from being parsed for story tiddlers?

Use cases:

Using a tiddler as an annotated table of contents for a chapter. Sometimes the comments/annotations refer to other tiddlers/chapters.

Alternate way of showing a Slide Show using the SlideShow Plugin. The slideshow plugin doesn't load tiddlers that have a : at the end of the name, so I can reference style sheets etc quickly when I pull up the tiddler. Hmm, maybe I can use transclusion to hide this as well??

! AnnotationsPlugin

!! clicking on link in popup
How can you click on a link in the popup annotation? Maybe I need a different plugin? As soon as I move into the popup, it dissapears.
Firefox 3.

!! Forced links not displayed right

Also putting a forced link inside the annotation tiddler prevent the link from being properly displayed.
{{{
(( [[nice link]] (^<<tiddler glossary/nicelink>>)))
}}}
displays as {{{ [[nice link]] }}} on a grey background. Mousing over does display the popup nicely.

! PartTiddlerPlugin <<tiddler "PartTiddlerPlugin::Version">>

nested parts seem to be displaying incorrectly.

{{{
You should have done the steps in [[Download and Setup SEC]] before starting this example.

! A simple Hello World example

<part content>

Open your editor and type:

<part example1>
{{  // really three braces
type = single
desc = my first rule
ptype = regexp
pattern = Hello
action = write - I saw %0
}}  // really three braces
</part>

Save it to a file called {{{rules1.sr}}}.
[... omitted content]
Congratulations you just matched your first event with SEC.
</part>
}}}

displays as:

{{{
 A simple Hello World example

<part contents>

Open your editor and type:
[...]
Congratulations you just matched your first event with SEC.
</part>
}}}

If I remove the {{{<part example1>}}} then the outer parts dissapear, but I really want to use both as the content is imported into a larger chapter while the example is imported into a diferent chapter and discussion.

! Import Plugin

# How do I make a default of record source of imported tiddler so I can sync.
# How can I get it to add a new systemServer tiddler with the url's of the servers I import from.
# I can't get the list of default defined servers to work. Is that a known issue?

~FireBug reports:

{{{
 if(attribs){
78 for(var n in attribs){
79 e.setAttribute(n,attribs[n]);
80 }
}}}

that {{{e}}} is undefined.

! AttachFilePlugin

Unable to save the embedded link in IE. Is this a known issue? Other alternatives for storing a file in a tiddlywiki and
exporting it to a local file with formatting preserved (for scripts and data files needed for a class).

! Other Issues

!! How to delete old tiddlers w/ sync.
I am currently tagging deleted tiddlers with "content deleted" and removing the tiddler contents while keeping the title
to overwrite prior tiddlers however it is then up to the student to delete the tiddler. Can I:

# add a new systemConfig tiddler that deletes tiddlers marked with deleted?
# if I can what about the notes tiddlers, should they be moved/renamed to a new tiddler?
# maybe leave a link in the old tiddler pointing to tne new tiddler and use that to trigger deletion and rename of the notes tiddler?
# maybe just have the user delete as needed and renaming as the link shows?

!! Allow links to act as a jump to tiddler if the tiddler is already open in the story

Use case: Have a table of contents tiddler. Tag it as  story to open it an all it's component tiddlers. Use it as a toc
to jump right to a component tiddler. If the tiddler is not open in the story column, open the tidder and jump to it's location.

!! (solved) excludeOrphans tag to prevent chapters and other top level items from being presented as orphans
{{{
These are available as the result of embedded searches on tags, and I want them to show up in timeline etc, just not in
orphans list. They are all tagged with "chapters", can I add an excludeOrphans to the tag tidder to prevent them from displaying
on the orphans list?
}}}
submitted July 19 http://groups.google.com/group/TiddlyWiki/t/39f7be322883586e

!! Support mailto links with anti-spam capability.

Be nice to allow students to submit issues by just clicking on a mailto link. But I don't want it to end up being harvestable by spambots.

! TiddlerNotes

Can't use more than 1 note in a tiddler. Should be able to have multiple notes.
While they can display multiples, can only edit one of them.

If a note exists, it should have an additional class. This way a media print style can print actual notes with contents while not printing empty notes blocks.

Also there is a bug: [[PatchedPlugin##TiddlerNotesPlugin]]

!Notes

{{{
(5:27:16 PM) ericshulman: rouilj: I know you won't be using this until the next revision (after your deadlines), but here's something I just cooked up and published on TiddlyTools: http://www.TiddlyTools.com/#ShowImage
(5:27:32 PM) ericshulman: it doesn't use any plugins or non-core syntax
(5:28:31 PM) ericshulman: it's a 'self-documenting tiddler transclusion'
(5:29:33 PM) ericshulman: (i.e., view the tiddler to read the docs, transclude the tiddler with params to render it's output)
(5:39:15 PM) rouilj: cool. Will it support functionality like: [img(75%,)[Fallen trees.|Tunguska_event_fallen_trees.jpg]]
(5:39:19 PM) rouilj: afk
(5:51:51 PM) ericshulman: the output format is determined by the content of the ShowImage##show section
(5:52:15 PM) ericshulman: you could add the "(75%)" literal there (to scale all images)
(5:52:50 PM) ericshulman: or, you could write "($3,)"
(5:53:56 PM) ericshulman: and then change the last line of the ShowImage tiddler to:
(5:54:19 PM) ericshulman: 	with: [[$1]] {{'$2'=='$'+'2'?'$1':'$2'}} {{'$2'=='$'+'2'?'auto':'$3'}}>>
(5:54:53 PM) ericshulman: Usage would then be: <<tiddler ShowImage with: AttachmentTitle "tooltip" "width">>
(5:55:18 PM) ericshulman: errata: 	with: [[$1]] {{'$2'=='$'+'2'?'$1':'$2'}} {{'$3'=='$'+'3'?'auto':'$3'}}>>
}}}

!! ChapterStart

Sets an inline style to force a page break before the enclosing tiddler. This seems a little hacky. Would it be better to create a chapterStart style and add that to the enclosing tiddler. Then the StyleSheet in the @media section can have 
{{{
.chapterStart {page-break-before:always}
}}}
for the user to edit rather than editing a javascript tiddler.

<<sectionTOC>>
! ChangeLog for SEC coursebook

Each dated subsection has a description has a description of the changes done to the coursebook.

!! 2010-07-05

Core updated to 2.6.0. Multiple plugin updates including new SlideShowPlugin with ability to exclude tidders and reference another tiddler as the slide show source list.

!! 2009-09-02

Updated with HideWhenPlugin to allow conditional text. Used primarily for GettingStarted to:
# Display download link if user views tiddlywiki from somewhere other than local file
# guide user though 4 step preparation sequence
# provide positive feedback when load tiddlers is successfully completed (by checking for Welcome tiddler)

!! 2009-07-11

Finished presentation 1 first cut at coursebook orientation and use.

Changed slide show starting labels and popups for the buttons.

Changed StorySaverPlugin settings to reference section rather than story in popup menu.

!! 2009-07-09

Added auto cycle and auto advance slide show for display before start of class.

!! 2009-05-30

Added ChangeLog.
This tiddler implements javascript code that opens a popup to change the displayed page title. Enter a title of """default""" to reset it to the tiddlywiki's embeded page title. Use cancel to leave title unchanged.

Use when printing a story column to [[ PDFCreator|http://www.pdfcreator.org]] to change the title of the document.

!Script
<script label="change page title">
 document.title=prompt('enter new document title, or default',document.title) || document.title; 
 if (document.title == "default" ) document.title = window.getPageTitle();
</script>
!end
There are some simple changes that can be made to the style sheets whose CSS setting control the display and printing format for the coursebook.

{{sectionTOC{}}}

!! Changing Chapter Printing
If the first tiddler in every chapter starts with {{{<<tiddler ChapterStart>>}}}, then each chapter will start on a new page. Howeverr you may want chapters to start on an odd or even page, or disable a new page start entirely. To change this edit the ChapterStart tiddler and change:
{{{
if (here.previousSibling) here.style.pageBreakBefore='always';
}}}
Replacing {{{always}}} with [[some other suitable value|http://www.w3schools.com/css/pr_print_pageba.asp]] like auto or left will modify the page break policy for all chapters.

!! Changing Slide Printing
The style sheet controlling slide printing in SlideShowPlugin print mode is the PrintingSlideShowStyleSheet. There is an {{{@media}}} section that contains the changes specifically for printing to paper or other media.

By default every slide prints on a new page. If you want to change this, you need to edit the PrintingSlideShowStyleSheet and change the setting:
{{{
.tiddler{
 page-break-after: always;
  ...
}}}
from always to auto or [[other suitable setting|http://www.w3schools.com/css/pr_print_pageba.asp]].

If you want to hide the slide comments (notes to students) in the SlideShowPlugin print mode, you can add the line:
{{{
display: none;
}}}
inside the .comment block:
{{{
.comment{
 border: 1pt dashed;
 padding: 0.5em;
}
}}}
of the PrintingSlideShowStyleSheet tiddler.

If you want to change the base font size used when printing slide presentations (e.g. you want to increase the size to print 4-up or 8-up), change
{{{
#contentWrapper.slideShowMode #displayArea{
 font-size: 150%;
 margin: 1em 15.5em 0em 1em !important;
}
}}}
replacing {{{150%}}} with {{{200%}}} or [[some other suitable value|http://www.w3schools.com/CSS/pr_font_font-size.asp]].

!!! Slides printed in normal story column
However slide tiddlers printed as part of a story column (accessed by the drop down menu for the presentation) are also printed one per page. To change
this you edit the StyleSheet and modify the line:
{{{
*[template="slideViewTemplate"] {page-break-after: always}
}}}
replacing always with [[some other option|http://www.w3schools.com/css/pr_print_pageba.asp]].

<<tiddler ChapterStart>>You can create two types of presentations:
# Single tiddler presentations
# Multi-tiddler presentations

!! Single Tiddler Presentations
As the name "Single tiddler" implies, the presentation tiddler is divided into multiple segments and each segment is displayed as a slide in the presentation. This method has a few advantages:
* editing is easier as only one tiddler need to be modified,
* useful for "administrative presentations". For example:
** a looping slide show at the beginning of a class welcoming the students and displaying info they need to know about the class. 
** a looping slide show during a class break with a countdown timer till class resumes.
However it comes with some drawbacks:
* Slide titles are generic ~TempSlide1, ~TempSlide2 etc. So you have to use a style/theme that doesn't display the tiddler title.
* Students can't annotate a slide as there is no actual tiddler associated with each slide.
* You have to hide certain control elements when using a single tiddler, but these elements aren't hidden if exported to the student copy.

!! Multi-tiddler Presentations
As the name "Multi-tiddler" implies, a single tiddler links to multiple slide tiddlers and each slide tiddler is displayed as a slide in the presentation. This method has a few advantages:
* Student's can't annotate single tiddler shows as there is no actual tiddler associated with each slide.
* The tiddler title is used as a slide title to provide a useful description of the slide content.
* A single tiddler can be used in multiple presentations
However it comes with some drawbacks:
* Revising multiple slides requires editing multiple tiddlers. (If you are doing text substitution consider using the TiddlerTweakerPlugin to do batch editing of content.)
* More tiddlers makes tiddlywiki somewhat slower
* The addition of slide tiddlers can make it more difficult to find the specific tiddler you are interested in.
[[Chapter  1 - Types of Presentations]]
[[Creating a Presentation]]
[[Creating a Slide]]
[[Opening a Presentation]]
[[Display a Presentation]]
[[Presentation Tips]]
[[Slide Tips]]
[[Printing Slide Set]]
[[Tagging a Presentation]]
[[Creating Your Own Presentation Theme]]
<<tiddler ChapterStart>>Chapter operate a lot like a presentation. It provides a linear set of tiddlers for the student. Unlike the presentation, the tidders in a chapter are displayed all at once in the story column of the tiddlywiki. This facilitates printing, searching  (using the browsers search function) and reading the material.

As with presentations, [[tags define a chapter control tiddler|Tagging a Chapter]].
[[Chapter  2 - Chapters Defined]]
[[How to Create a Chapter]]
[[Creating Chapter Content]]
[[Creating Chapter Content as Separate Tiddlers]]
[[Creating Chapter Content as Single Tiddler and Split Into Multiple Tiddlers]]
[[Creating Chapter Content as Single Large Tiddler]]
[[Creating a New Chapter from an Existing Tiddler]]
[[How to Create Additional Content]]
[[Opening a Chapter]]
[[Printing Chapters]]
[[Creating Quizzes]]
[[Creating Reference Tiddlers]]
[[Chapter  3 - Other Publication Options]]

[[Creating PDF's]]
[[Creating visual html]]
[[Changing the Style Sheet]]
Although the Coursebook is meant to be used on a computer, sometimes you need to print out the material:
* students don't have a computer at the course
* students are not familiar with technology and using the Coursebook would be a distraction
* provide a fallback mechanism in case things go wrong (print slides as transparencies)
* annotate slides for use by presenter, and work from those notes during presentation

The tiddlers on:
* [[Printing]]
* [[Printing Chapters]]
* [[Printing Slide Set]]
describe how to set up to print directly to paper. Using [[CSS - Cascading Stle Sheets|http://www.w3.org/Style/CSS/learning]] you can modfiy the font, layout and other settings (e.g. page breaks).

Besides printing directly to paper, other options are to [[print to PDF in windows|Creating PDF's]] or produce html that visually replicates the information. While both of these options can be used on the computer, they do not easily support links or other interaction with the document, so they should be considers the equivalent of a paper document except viewable on the computer.
! A chapter is:
* A linear sequence of tiddlers listed in the "chapter control tiddler"
* Indexed in the main menu
* Displayed as a single entitiy
* Is made up of parts (tiddlers) that stand alone which has some unique challenges

{{comment{
Because tiddlers are stand alone entities (and are the unit of notetaking for the students) flow of prose is somewhat tricky. References to other tiddler content is tricky because a tiddler can stand alone outside of a chapter context.
}}}
<<matchTags inline {{"* <<openStory [[%0]] '%0' 'Open %0'>" + "> @@font-size: smaller;([[open|%0]])@@"}} "\n" sort:title chapter>>
!Reference
/% replace this entire line if you are manually listing reference tiddlers%/<<matchTags inline "* [[%0]]" "\n" sort:title reference>>
/%
If you replace the reference tiddler list with a manual list like:

* [[Glossary of terms|Glossary]]
* [[Other Resources|Resources]]

consider adding:
<<tiddler ShowPopup with: [[ChapterList##reference]] "All References" "List of all tiddlers tagged with reference in alphabetic order." >> 

below the list. This was less used references are strill available, but you don't have them taking up space unless the user want's to see them.

Don't touch this needed for the popup to work.
!reference
<<matchTags inline "[[%0]]" "\n" sort:title reference>>
!end
%/
<script>
// set up page break when printing first tiddler of every chapter if it is not the first tiddler on page
// Start the first tiddler of every chapter with: <<tiddler ChapterStart>> Text of tiddler
var here=story.findContainingTiddler(place);
if (here.previousSibling) here.style.pageBreakBefore='always';
</script>
<<compareTiddlers "not excludeLists or Revisions">>
/***
|Name|CompareTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#CompareTiddlersPlugin|
|Version|1.1.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|show color-coded differences between two selected tiddlers|
!!!!!Usage
<<<
Display a form that lets you select and compare any two tiddlers:
{{{
<<compareTiddlers>>
}}}
To filter the lists of tiddlers by tags, include an optional tagvalue (or tag expression) parameter:
{{{
<<compareTiddlers "tagValue">>
   OR
<<compareTiddlers "boolean tag expression">> (requires MatchTagsPlugin)
}}}
<<<
!!!!!Example
<<<
{{{<<compareTiddlers>>}}}
{{smallform small{<<compareTiddlers>>}}}
<<<
!!!!!Revisions
<<<
2009.07.25 [1.1.0] added optional tag filter param
2007.10.15 [1.0.0] converted from inline script to true plugin
2006.12.27 [0.0.0] inline script.  {{{diff()}}} and {{{diffString()}}} functions written by Bradley Meck.
<<<
!!!!!Code
***/
//{{{
version.extensions.CompareTiddlersPlugin= {major: 1, minor: 1, revision: 0, date: new Date(2009,7,25)};
//}}}
//{{{
config.shadowTiddlers.CompareTiddlers='<<compareTiddlers>>';
//}}}
/***
//{{{
!html
<form><!--
--><input type=hidden name=filter value=''><!--
--><select name=list1 size=1 style='width:30%'
	onchange='config.macros.compareTiddlers.pick(this,this.form.view1,this.form.edit1,this.form.text1)'></select><!--
--><input type=button name=view1 style='width:10%' value='view' disabled
	onclick='if (this.form.list1.value.length)
		story.displayTiddler(story.findContainingTiddler(this),this.form.list1.value)'><!--
--><input type=button name=edit1 style='width:10%' value='edit' disabled
	onclick='if (this.form.list1.value.length)
		story.displayTiddler(story.findContainingTiddler(this),this.form.list1.value,DEFAULT_EDIT_TEMPLATE)'><!--
--><select name=list2 size=1 style='width:30%'
	onchange='config.macros.compareTiddlers.pick(this,this.form.view2,this.form.edit2,this.form.text2)'></select><!--
--><input type=button name=view2 style='width:10%' value='view' disabled
	onclick='if (this.form.list2.value.length)
		story.displayTiddler(story.findContainingTiddler(this),this.form.list2.value)'><!--
--><input type=button name=edit2 style='width:10%' value='edit' disabled
	onclick='if (this.form.list2.value.length)
		story.displayTiddler(story.findContainingTiddler(this),this.form.list2.value,DEFAULT_EDIT_TEMPLATE)'><br><!--
--><nobr><!--
--><textarea name=text1 style='width:49.5%;display:none' rows='10' readonly></textarea><!--
--><textarea name=text2 style='width:49.5%;display:none' rows='10' readonly></textarea><!--
--></nobr><!--
--><div style='float:left'><!--
-->Additions are shown in <span style='color:green'>GREEN</span>, <!--
-->deletions are shown in <span style='color:red'>RED</span><!--
--></div><!--
--><div style='text-align:right'><!--
--><input type=button name=compare style='width:10%' value='compare' disabled
	onclick='config.macros.compareTiddlers.compare(this.form,this.form.nextSibling)'><!--
--><input type=button name=done style='width:10%' value='done' disabled
	onclick='config.macros.compareTiddlers.reset(this.form,this.form.nextSibling)'><!--
--></div><!--
--></form><div class='compareTiddlersResults'>contents to be replaced by results of comparison</div>
!end
//}}}
***/
//{{{
config.macros.compareTiddlers= {
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		setStylesheet(this.css,'CompareTiddlersStyles');
		var out=createTiddlyElement(place,'span');
		out.innerHTML=store.getTiddlerText('CompareTiddlersPlugin##html');
		var form=out.getElementsByTagName('form')[0];
		var target=form.nextSibling;
		this.reset(form,target,params[0]);
	},
	css: '.compareTiddlersResults \
		{ display:none;clear:both;margin-top:1em;border:1px solid;-moz-border-radius:1em;-webkit-border-radius:1em;padding:1em;white-space:normal; }',
	reset: function(f,target,filter) {
		if (f.filter.value.length) var filter=f.filter.value;
		if (filter) var tids=store.filterTiddlers('[tag['+filter+']]')
		else var tids=store.getTiddlers('title','excludeLists');
		f.text1.style.display='none'; f.text1.value='';
		while (f.list1.options[0]) f.list1.options[0]=null; 
		f.list1.options[0]=new Option('select a tiddler...','',false,false);
		for (i=0; i<tids.length; i++)
			f.list1.options[f.list1.length]=new Option(tids[i].title,tids[i].title,false,false);
		f.text2.style.display='none'; f.text2.value='';
		while (f.list2.options[0]) f.list2.options[0]=null; 
		f.list2.options[0]=new Option('select a tiddler...','',false,false);
		for (i=0; i<tids.length; i++)
			f.list2.options[f.list2.length]=new Option(tids[i].title,tids[i].title,false,false);
		f.view1.disabled=f.view2.disabled=f.edit1.disabled=f.edit2.disabled=f.compare.disabled=f.done.disabled=true;
		f.filter.value=filter;
		target.style.display='none';
		removeChildren(target);
	},
	pick: function(list,view,edit,text) {
		var f=list.form;
		view.disabled=edit.disabled=f.done.disabled=!list.value.length;
		f.compare.disabled=!f.list1.value.length||!f.list2.value.length;
		if (!list.value.length) return;
		f.text1.style.display=f.text2.style.display='inline';
		text.value=store.getTiddlerText(list.value);
	},
	compare: function(f,target) {
		if (!f.list1.value.length) { f.list1.focus(); return alert('select a tiddler'); }
		var t1=store.getTiddlerText(f.list1.value); if (!t1) { displayMessage(f.list1.value+' not found');return false; }
		if (!f.list2.value.length) { f.list2.focus(); return alert('select a tiddler'); }
		var t2=store.getTiddlerText(f.list2.value); if (!t2) { displayMessage(f.list2.value+' not found');return false; }
		var out=this.diffString(t1,t2); if (!out || !out.length) out='no differences';
		removeChildren(target);
		target.innerHTML=out;
		target.style.display='block';
		f.done.disabled=false;
	},
//}}}
//{{{
	diffString: function( o, n ) {
		// This function was written by Bradley Meck
		// returns difference between old and new text, color-formatted additions and deletions
		if (o==n) return ""; // simple check, saves time if true
		var error = 5;
		var reg = new RegExp( "\\n|(?:.{0,"+error+"})", "g" );
		var oarr = o.match( reg ); // dices text into chunks
		var narr = n.match( reg );
		var out = this.diff(oarr,narr); // compare the word arrays
		var str = ""; // construct output
		for (i=0; i<out.length; i++) {
			switch (out[i].change) {
				case "ADDED":
					str+="<span style='color:green'>";
					str+=narr.slice(out[i].index,out[i].index+out[i].length).join("");
					str+="</span> ";
					break;
				case "DELETED":
					str+="<span style='color:red'>";
					str+=oarr.slice(out[i].index,out[i].index+out[i].length).join("");
					str+="</span> ";
					break;
				default:
					str+="<span>";
					str+=oarr.slice(out[i].index,out[i].index+out[i].length).join("");
					str+="</span> ";
					break;
			}	
		}
		return str;
	},
	diff: function( oldArray, newArray ) {
		// This function was written by Bradley Meck
		// finds the differences between one set of objects and another.
		// The objects do not need to be Strings.  It outputs an array of objects with the properties value and change.
		// This function is pretty hefty but appears to be rather light for a diff and tops out at O(N^2) for absolute worst cast scenario.
		var newElementHash = { };
		for( var i = 0; i < newArray.length; i++ ) {
			if( ! newElementHash [ newArray [ i ] ] ) {
				newElementHash [ newArray [ i ] ] = [ ];
			}
			newElementHash [ newArray [ i ] ].push( i );
		}
		var substringTable = [ ];
		for( var i = 0; i < oldArray.length; i++ ) {
			if(newElementHash [ oldArray [ i ] ] ) {
				var locations = newElementHash [ oldArray [ i ] ] ;
				for( var j = 0; j < locations.length; j++){
					var length = 1;
					while( i + length < oldArray.length && locations [ j ] + length < newArray.length
						&& oldArray [ i + length ] == newArray [ locations [ j ] + length ] ){
						length++;
					}
					substringTable.push( {
						oldArrayIndex : i,
						newArrayIndex : locations [ j ],
						matchLength : length
					} );
				}
			}
		}
		substringTable.sort( function( a, b ) {
			if ( a.matchLength > b.matchLength /* a is less than b by some ordering criterion */ ) {
				return -1;
			}
			if ( a.matchLength < b.matchLength /* a is greater than b by the ordering criterion */ ) {
				return 1;
			}
			// a must be equal to b
			return 0
		} );
		//displayMessage( substringTable.toSource( ) );
		for( var i = 0; i < substringTable.length; i++) {
			for( var j = 0; j < i; j++) {
				var oldDelta = substringTable [ i ].oldArrayIndex + substringTable [ i ].matchLength - 1 - substringTable [ j ].oldArrayIndex;
				var newDelta = substringTable [ i ].newArrayIndex + substringTable [ i ].matchLength - 1 - substringTable [ j ].newArrayIndex;
				//displayMessage( "oldDelta ::: " + oldDelta );
				//displayMessage( "newDelta ::: " + newDelta );
				//displayMessage( "matchLength ::: " + substringTable [ j ].matchLength );
				if( ( oldDelta >= 0 && oldDelta <= substringTable [ j ].matchLength )
				|| ( newDelta >= 0 && newDelta <= substringTable [ j ].matchLength )
				|| ( oldDelta < 0 && newDelta > 0 )
				|| ( oldDelta > 0 && newDelta < 0 ) ) {
					substringTable.splice( i, 1 );
					i--;
					break;
				}
			}
		}
		//displayMessage( substringTable.toSource(  ) );
		substringTable.sort( function( a, b ) {
			if ( a.oldArrayIndex < b.oldArrayIndex /* a is less than b by some ordering criterion */ ) {
				return -1;
			}
			if ( a.oldArrayIndex > b.oldArrayIndex /* a is greater than b by the ordering criterion */ ) {
				return 1;
			}
			// a must be equal to b
			return 0
		} );
		//displayMessage( substringTable.toSource( ) );
		var oldArrayIndex = 0;
		var newArrayIndex = 0;
		var results = [ ];
		for( var i = 0; i < substringTable.length; i++ ) {
			if( oldArrayIndex != substringTable [ i ].oldArrayIndex ) {
				results.push( {
					change : "DELETED",
					length : substringTable [ i ].oldArrayIndex - oldArrayIndex,
					index : oldArrayIndex
				} );
			}
			if( newArrayIndex != substringTable [ i ].newArrayIndex ) {
				results.push( {
					change : "ADDED",
					length : substringTable [ i ].newArrayIndex - newArrayIndex,
					index : newArrayIndex
				} );
			}
			results.push( {
				change : "STAYED",
				length : substringTable [ i ].matchLength,
				index : substringTable [ i ].oldArrayIndex
			} );
			oldArrayIndex = substringTable [ i ].oldArrayIndex + substringTable [ i ].matchLength;
			newArrayIndex = substringTable [ i ].newArrayIndex + substringTable [ i ].matchLength;
		}
		if( oldArrayIndex != oldArray.length ) {
			results.push( {
				change : "DELETED",
				length : oldArray.length - oldArrayIndex,
				index : oldArrayIndex
			} );
		}
		if( newArrayIndex != newArray.length ) {
			results.push( {
				change : "ADDED",
				length : newArray.length - newArrayIndex,
				index : newArrayIndex
			} );
		}
		return results;
	}
}
//}}}
{{sectionTOC{}}}
! Chapter tiddler structure

Chapter the chapter tiddler is a tiddler that self reference so it opens at the top of the story group.
Thus it acts as a toc. Now if there was some way to have the links in the TOC tiddler jump to the open tiddler
in the story rather than reopen that would work well. Idea from chapter 4 of:
http://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-719.html

! Possible tag taxonomy for content

Again from http://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-719.html

;Summary
:Brief, and assumes that the reader has some familiarity with the  topic.
;Introduction
: Longer, and assumes that the reader has not encountered the topic before.
;Example
:A page describing a worked example.
;Exercise
:A live exercise within the Book that the student can try.
;Exercise advice 
:A piece of advice about an issue that might come up in an exercise.
;Search
:Executes a search using a Web search engine.
;Chapter
:Takes the reader through the topic in an ordered manner. Chapters are made up of subtopics and are described in Section 4.3.

<<tiddler [[Dynamic Content]]>>

<<sectionTOC>>
This is the rss feed for new content changes from <<tiddler "GettingStarted::courseHomeRss">>.

<<rssReader noDesc {{store.getTiddlerSlice('GettingStarted', 'courseHomeRss');}} >>
/***
|Name|CopyTiddlerPlugin|
|Source|http://www.TiddlyTools.com/#CopyTiddlerPlugin|
|Version|3.2.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.3|
|Type|plugin|
|Requires||
|Overrides||
|Description|Quickly create a copy of any existing tiddler|
!!!Usage
<<<
The plugin automatically updates the default (shadow) ToolbarCommands definitions to insert the ''copyTiddler'' command, which will appear as ''copy'' when a tiddler is rendered.  If you are already using customized toolbar definitions, you will need to manually add the ''copyTiddler'' toolbar command to your existing ToolbarCommands tiddler, e.g.:
{{{
|EditToolbar|... copyTiddler ... |
}}}
When the ''copy'' command is selected, a new tiddler is created containing an exact copy of the current text/tags/fields, using a title of "{{{TiddlerName (n)}}}", where ''(n)'' is the next available number (starting with 1, of course).  If you copy while //editing// a tiddler, the current values displayed in the editor are used (including any changes you may have already made to those values), and the new tiddler is immediately opened for editing.

The plugin also provides a macro that allows you to embed a ''copy'' command directly in specific tiddler content:
{{{
<<copyTiddler TidderName label:"..." prompt:"...">>
}}}
where
* ''TiddlerName'' (optional)<br>specifies the //source// tiddler to be copied.  If omitted, the current containing tiddler (if any) will be copied.
* ''label:"..."'' (optional)<br>specifies text to use for the embedded link (default="copy TiddlerName")
* ''prompt:"..."'' (optional)<br>specifies mouseover 'tooltip' help text for link
//Note: to use non-default label/prompt values with the current containing tiddler, use "" for the TiddlerName//
<<<
!!!Configuration
<<<
<<option chkCopyTiddlerDate>> use date/time from existing tiddler (otherwise, use current date/time)
{{{<<option chkCopyTiddlerDate>>}}}
<<<
!!!Revisions
<<<
2009.06.08 [3.2.5] added option to use timestamp from source tiddler
2009.03.09 [3.2.4] fixed IE-specific syntax error
2009.03.02 [3.2.3] refactored code (again) to restore use of config.commands.copyTiddler.* custom settings
2009.02.13 [3.2.2] in click(), fix calls to displayTiddler() to use current tiddlerElem and use getTiddlerText() to permit copying of shadow tiddler content
2009.01.30 [3.2.1] fixed handling for copying field values when in edit mode
2009.01.23 [3.2.0] refactored code and added {{{<<copyTiddler TiddlerName>>}}} macro
2008.12.18 [3.1.4] corrected code for finding next (n) value when 'sparse' handling is in effect (thanks to RussThomas for identifying and diagnosing the problem)
2008.11.14 [3.1.3] added optional 'sparse' setting (avoids 'filling in' missing numbers that may have been previously deleted)
2008.11.14 [3.1.2] added optional 'zeroPad' setting
2008.11.14 [3.1.1] moved hard-coded '(n)' regex into 'suffixPattern' object property so it can be customized
2008.09.26 [3.1.0] changed new title generation to use '(n)' suffix instead of 'Copy of' prefix
2008.05.20 [3.0.3] in handler, when copying from VIEW mode, create duplicate array from existing tags array before saving new tiddler.
2007.12.19 [3.0.2] in handler, when copying from VIEW mode, duplicate custom fields before saving new tiddler. Thanks to bug report from Ken Girard.
2007.09.26 [3.0.1] in handler, use findContainingTiddler(src) to get tiddlerElem (and title).  Allows 'copy' command to find correct tiddler when transcluded using {{{<<tiddler>>}}} macro or enhanced toolbar inclusion (see [[CoreTweaks]])
2007.06.28 [3.0.0] complete re-write to handle custom fields and alternative view/edit templates
2007.05.17 [2.1.2] use store.getTiddlerText() to retrieve tiddler content, so that SHADOW tiddlers can be copied correctly when in VIEW mode
2007.04.01 [2.1.1] in copyTiddler.handler(), fix check for editor fields by ensuring that found field actually has edit=='text' attribute
2007.02.05 [2.1.0] in copyTiddler.handler(), if editor fields (textfield and/or tagsfield) can't be found (i.e., tiddler is in VIEW mode, not EDIT mode), then get text/tags values from stored tiddler instead of active editor fields.  Allows use of COPY toolbar directly from VIEW mode (based on a request from LaurentCharles)
2006.12.12 [2.0.0] completely rewritten so plugin just creates a new tiddler EDITOR with a copy of the current tiddler EDITOR contents, instead of creating the new tiddler in the STORE by copying the current tiddler values from the STORE.
2005.xx.xx [1.0.0] original version by Tim Morgan
<<<
!!!Code
***/
//{{{
version.extensions.CopyTiddlerPlugin= {major: 3, minor: 2, revision: 5, date: new Date(2009,6,8)};

// automatically tweak shadow EditTemplate to add 'copyTiddler' toolbar command (following 'cancelTiddler')
config.shadowTiddlers.ToolbarCommands=config.shadowTiddlers.ToolbarCommands.replace(/cancelTiddler/,'cancelTiddler copyTiddler');

if (config.options.chkCopyTiddlerDate===undefined) config.options.chkCopyTiddlerDate=false;

config.commands.copyTiddler = {
	text: 'copy',
	hideReadOnly: true,
	tooltip: 'Make a copy of this tiddler',
	notitle: 'this tiddler',
	prefix: '',
	suffixText: ' (%0)',
	suffixPattern: / \(([0-9]+)\)$/,
	zeroPad: 0,
	sparse: false,
	handler: function(event,src,title)
		{ return config.commands.copyTiddler.click(src,event); },
	click: function(here,ev) {
		var tiddlerElem=story.findContainingTiddler(here);
		var template=tiddlerElem?tiddlerElem.getAttribute('template'):null;
		var title=here.getAttribute('from');
		if (!title || !title.length) {
			if (!tiddlerElem) return false;
			else title=tiddlerElem.getAttribute('tiddler');
		}
		var root=title.replace(this.suffixPattern,''); // title without suffix
		// find last matching title
		var last=title;
		if (this.sparse) { // don't fill-in holes... really find LAST matching title
			var tids=store.getTiddlers('title','excludeLists');
			for (var t=0; t<tids.length; t++) if (tids[t].title.startsWith(root)) last=tids[t].title;
		}
		// get next number (increment from last matching title)
		var n=1; var match=this.suffixPattern.exec(last); if (match) n=parseInt(match[1])+1;
		var newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]);
		// if not sparse mode, find the next hole to fill in...
		while (store.tiddlerExists(newTitle)||document.getElementById(story.idPrefix+newTitle))
			{ n++; newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]); }
		if (!story.isDirty(title)) { // if tiddler is not being EDITED
			// duplicate stored tiddler (if any)
			var text=store.getTiddlerText(title,'');
			var who=config.options.txtUserName;
			var when=new Date();
			var newtags=[]; var newfields={};
			var tid=store.getTiddler(title); if (tid) {
				if (config.options.chkCopyTiddlerDate) var when=tid.modified;
				for (var t=0; t<tid.tags.length; t++) newtags.push(tid.tags[t]);
				store.forEachField(tid,function(t,f,v){newfields[f]=v;},true);
			}
	                store.saveTiddler(newTitle,newTitle,text,who,when,newtags,newfields,true);
			story.displayTiddler(tiddlerElem,newTitle,template);
		} else {
			story.displayTiddler(tiddlerElem,newTitle,template);
			var fields=config.commands.copyTiddler.gatherFields(tiddlerElem); // get current editor fields
			var newTiddlerElem=document.getElementById(story.idPrefix+newTitle);
			for (var f=0; f<fields.length; f++) {  // set fields in new editor
				if (fields[f].name=='title') fields[f].value=newTitle; // rename title in new tiddler
				var fieldElem=config.commands.copyTiddler.findField(newTiddlerElem,fields[f].name);
				if (fieldElem) {
					if (fieldElem.getAttribute('type')=='checkbox')
						fieldElem.checked=fields[f].value;
					else 
						fieldElem.value=fields[f].value;
				}
			}
		}
		story.focusTiddler(newTitle,'title');
		return false;
	},
	findField: function(tiddlerElem,field) {
		var inputs=tiddlerElem.getElementsByTagName('input');
		for (var i=0; i<inputs.length; i++) {
			if (inputs[i].getAttribute('type')=='checkbox' && inputs[i].field == field) return inputs[i];
			if (inputs[i].getAttribute('type')=='text' && inputs[i].getAttribute('edit') == field) return inputs[i];
		}
		var tas=tiddlerElem.getElementsByTagName('textarea');
		for (var i=0; i<tas.length; i++) if (tas[i].getAttribute('edit') == field) return tas[i];
		var sels=tiddlerElem.getElementsByTagName('select');
		for (var i=0; i<sels.length; i++) if (sels[i].getAttribute('edit') == field) return sels[i];
		return null;
	},
	gatherFields: function(tiddlerElem) { // get field names and values from current tiddler editor
		var fields=[];
		// get checkboxes and edit fields
		var inputs=tiddlerElem.getElementsByTagName('input');
		for (var i=0; i<inputs.length; i++) {
			if (inputs[i].getAttribute('type')=='checkbox')
				if (inputs[i].field) fields.push({name:inputs[i].field,value:inputs[i].checked});
			if (inputs[i].getAttribute('type')=='text')
				if (inputs[i].getAttribute('edit')) fields.push({name:inputs[i].getAttribute('edit'),value:inputs[i].value});
		}
		// get textareas (multi-line edit fields)
		var tas=tiddlerElem.getElementsByTagName('textarea');
		for (var i=0; i<tas.length; i++)
			if (tas[i].getAttribute('edit')) fields.push({name:tas[i].getAttribute('edit'),value:tas[i].value});
		// get selection lists (droplist or listbox)
		var sels=tiddlerElem.getElementsByTagName('select');
		for (var i=0; i<sels.length; i++)
			if (sels[i].getAttribute('edit')) fields.push({name:sels[i].getAttribute('edit'),value:sels[i].value});
		return fields;
	}
};
//}}}
// // MACRO DEFINITION
//{{{
config.macros.copyTiddler = {
	label: 'copy',
	prompt: 'Make a copy of %0',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var title=params.shift();
		params=paramString.parseParams('anon',null,true,false,false);
		var label	=getParam(params,'label',this.label+(title?' '+title:''));
		var prompt	=getParam(params,'prompt',this.prompt).format([title||this.notitle]);
		var b=createTiddlyButton(place,label,prompt,
			function(ev){return config.commands.copyTiddler.click(this,ev)});
		b.setAttribute('from',title||'');
	}
};
//}}}
! Copyright

All tiddlers marked with the structure or content tags are copyright&copy; 2010 by John P. Rouillard.

! Additional licenses
Parts of this coursebook use components that are licensed separately from the content. This section contains the license information under which they are made available, or permission from the author to use the component.

!! ~TiddlyWiki license
From: http://tiddlywiki.org/wiki/TiddlyWiki_License

{{{
TiddlyWiki created by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)

Copyright (c) UnaMesa Association 2004-2008

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of the UnaMesa Association nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

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

!! ~TiddlySaver.jar License

From http://www.mail-archive.com/tiddlywiki@googlegroups.com/msg07643.html:

{{{
[tw] Re: Can TiddlyWiki and TiddlySaver.jar be redistributed? Licensing and copyright questions.

Jeremy Ruston
Sat, 01 Aug 2009 11:55:02 -0700

For licensing purposes TiddlySaver is intended to be considered to be
a component of TiddlyWiki, and available under the same terms.

Cheers

Jerm
}}}

!! Plugins from tiddlytools.com

All the plugins/scripts  from tiddlytools.com are covered by http://www.tiddlytools.com/#LegalStatements.

<<<
This work is based upon TiddlyWiki <<version>>, written by Jeremy Ruston, &copy; [[UnaMesa Association|http://www.unamesa.org/]] 2004-2008.

Modifications and additions to this work, including (but not limited to) original programmatic components ("plugins", "macros", "scripts", "stylesheets") have been created by Eric L. Shulman and/or ELS Design Studios.  These components are currently distributed using an ''open source'' model; however, they are ''not in the public domain'', and the author ''retains all applicable rights''.  Nonetheless, you //are// permitted to ''use, copy, and/or modify'' individual components of this work, subject to the licensing ''terms and conditions'' specifically included within or referenced by those individual components, as well as other terms, conditions, instructions, and guidelines included herein or by reference to the [[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]].

This work may contain portions of copyrighted materials from other sources.  In accordance with "fair use" principles (see [[United States Copyright Law, Title 17, Section 107|http://www.copyright.gov/title17/92chap1.html#107]]), such materials have been reproduced without profit for purposes of criticism, comment, news reporting, instruction, scholarship, and/or research.  ''All other original content, including (but not limited to) writings, illustrations, photographic images, sound recordings, and videos, are the property of Eric L. Shulman and/or ELS Design Studios, or are used under license or agreement with third parties'' and, except as required for normative operation and viewing of this work, may not be stored, displayed or re-transmitted in any form, nor used for any commercial purposes, without the specific prior permission of the respective rights holders.

This work includes or makes reference to icons that are part of the [["Silk" icon set|http://www.famfamfam.com/lab/icons/silk/ ]] containing 1000 16-by-16 pixel icons in PNG format, created by Mark James, and is licensed under a Creative Commons Attribution 2.5 License. Please visit http://www.famfamfam.com/ for further information and licensing details regarding this icon set.

''Terms of use:''

This work contains ''individual components that are intended to be selectively copied and installed'' into your own TiddlyWiki files in order to enhance and customize those documents.  You may not re-distribute this document in it's entirety, nor re-use it's overall design without specific prior permission.  You may, however, ''download and save this work for use only as a //local// resource'' to assist you in developing your //own// TiddlyWiki document designs.

Because people can import plugins from anyone's TiddlyWiki document, as soon as you share your document with just ONE other person, you become a "re-distributor" of the components you have installed in that document.  As such, ''you should avoid modifying any ~TiddlyTools components you have installed in your own documents'' unless there is a compelling, //functional// reason to do so and, even then, ''the best approach is often to simply submit a feature request'' to the original author/publisher and leave it up to them to determine the best way to modify and re-publish their components.

Nonetheless, if you //do// modify and/or share components of this work, you should ''always retain the original published content within those those components'', including all documentation, credits, licensing information, and URL references to the official distribution source for the unaltered versions of those components.  In addition, ''all modified components must be clearly identifiable as derivative works'' that have been differentiated from the original versions by renaming those components, as well as adding inline comments and a "revision history" to document specific changes.

If you share a modified ~TiddlyTools component, you must be prepared to support it.  All ''problems that occur within a modified component should be reported first directly to the provider of that modified component'', and then only reported to ~TiddlyTools if it can be shown that the problem also occurs in ~TiddlyTools' officially-published version of the component.  Any ''problems that are reported for //undifferentiated// modifications won't receive help from ~TiddlyTools'' (once they are determined to be modified, of course!), other than to direct the inquiry to wherever they got the modified components from in the first place.

Except for officially-published links to specific components of this work, ''you must not create or share deep links'' to online components of this work (e.g., images, audio, video, etc.).  Instead, you should copy the desired components (subject to applicable licenses and copyrights) to your own system or online hosting service, and ensure that your document contains references to //those// copies.

''Trademarks/servicemarks:''

"ELS Design Studios", "~TiddlyTools", "~TiddlyStudios", "~TiddlyTech", "~TiddlyLabs", "Small Tools for Big Ideas!", "Intuitive Interfaces for Intelligent Interactions" and the "i4" logo (in graphical //and// text forms) are trademarks or servicemarks of ELS Design Studios and may not be used without permission.  Limited use of "ELS Design Studios" and "~TiddlyTools" marks in other works is granted for attribution purposes only.  Such use does not create or imply any endorsement, agency or partner relationship with Eric L. Shulman and/or ELS Design Studios, nor with any designated representatives, agents, or heirs thereof.

''Limits on Liability:''

All materials are presented on an "as-is" basis and are subject to change without notice.  The author of this document makes no claims regarding the suitability or reliability of the information presented, and assumes no liability for any damages that may occur as a result of its use.

''Privacy Notice: ''

This site limits the collection and use of non-public, personal customer information to that which is needed to offer products and services, and to file reports or financial statements as required by law. This site has physical, electronic and procedural safeguards to maintain the protections of private information, and does not provide, sell or otherwise disclose such information to non-affiliated third parties.
<<<

!! Plugins from tiddlywiki.bidx.info

Licensed under BSD open source license. http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D

!! Plugins from tw.lewcid.org

Plugins created by Saq Imtiaz are covered under the creative commons license: http://creativecommons.org/licenses/by-sa/3.0/ license.

!! Plugins from tiddlywiki.abego-software.de

Are licensed under the Bsd License that is referenced from the plugin and is located at:
http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D

!! Paulo Soares plugins

http://www.math.ist.utl.pt/~psoares/addons.html  licensed under http://creativecommons.org/licenses/by-sa/3.0/

!! ~Clint Checketts and Paul Petterson

RedirectMacro - Multiple attempts to contact the author have failed. From this thread:
<<<
http://groups.google.com/group/tiddlywiki/browse_thread/thread/2e65045b53d231cf/efc9861ded20605e?q=redirect#efc9861ded20605e
<<<
it appears to be abandoned. As a result it falls into the public domain.

!! TiddlyLockPlugin

http://creativecommons.org/licenses/by-sa/3.0/

!! RefreshCommand

Email addresses were changed to prevent harvesting.

{{{
From:    Simon Baird <simon.baird at gmail dot .com>
Subject: Re: Rights to redistribute the RefreshCommand

--0016e64bd5bc00cdad0471eff216
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Please go ahead.

License details for my TW related plugins:
http://mptw.tiddlyspot.com/#License%20TheBSDLicense

On Tue, Aug 25, 2009 at 2:23 PM, John P. Rouillard <[[redacted]]>wrote:

>
> Hello Mr. Baird:
>
> I am developing a TiddlyWiki for use in a class I am teaching.  I
> would like to include your RefreshCommand plugin, however I am unable
> to find any license/copyright for it.
>
> Since the TiddlyWiki will be distributed by the sponsor as part of the
> materials for the course, I need to be able to satisfy them that I
> have the right to redistribute the plugin as part of the course book.
>
> Also I plan on releasing the TiddlyWiki Coursebook for others to use
> and as a result it would include a copy of your plugin.
>
> Do I have your permission to redistribute the plugin?
>
> Thank you for your time.
>
}}}

!! DisplayOpenTiddlersPlugin

{{{
Date:    Wed, 26 Aug 2009 14:15:19 -0000
To:      rouilj@[[redacted]]

From:    shadowman131 at comcast dot net
Subject: Re: Right to redistribute the DisplayOpenTiddlersPlugin

------=_Part_192496_151585835.1251296119472
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit

Hi John, 

You have absolute permission to distribute/modify DisplayOpenTiddlersPlugin as
much as you like. It was very kind of you to ask. Let me know if you happen to
need anything else.

Thanks, 
-Walt 

----- Original Message ----- 
From: "John P. Rouillard" <rouilj at cs.umb.edu> 
To: shadowman131 at comcast dot .net 
Sent: Monday, August 24, 2009 8:48:37 PM GMT -08:00 US/Canada Pacific 
Subject: Right to redistribute the DisplayOpenTiddlersPlugin 

Hello Mr. Woods: 

I am developing a TiddlyWiki for use in a class I am teaching. I 
would like to include your DisplayOpenTiddlersPlugin plugin, however I 
am unable to find any license/copyright for it. 

Since the tiddlywiki will be distributed by the sponsor as part of the 
materials for the course, I need to be able to satisfy them that I 
have the right to redistribute the plugin as part of the course book. 

Also I plan on releasing the TiddlyWiki Coursebook for other to use 
and as a result it would include a copy of your plugin. 

Do I have your permission to redistribute the plugin? 

Thank you for your time. 

Sincerely yours, 

-- 
-- rouilj 
John Rouillard 
}}}
/***
''Selective copy of www.tiddlytools.com CoreTweaks renamed so that updates don't pull in the full CoreTweaks.''
***/
/***
http://trac.tiddlywiki.org/ticket/683 - OPEN
The web standard 'type=file' input control that has been used as a local path/file picker for TiddlyWiki no longer works as expected in FireFox3, which has, for security reasons, limited javascript access to this control so that *no* local filesystem path information can be revealed, even when it is intentional and necessary, as it is with TiddlyWiki.  This tweak provides alternative HTML source that patches the backstage import panel.  It replaces the 'type=file' input control with a text+button combination of controls that invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.
>Note: ''This tweak also requires http://trac.tiddlywiki.org/ticket/604 - cross-platform askForFilename()''

DISABLED: rolled into tw 2.5.2
***/
/***
//{{{
if (window.Components {
	var fixhtml='<input name="txtBrowse" style="width:30em"><input type="button" value="..."'
		+' onClick="window.browseForFilename(this.previousSibling,true)">';
	var cmi=config.macros.importTiddlers;
	cmi.step1Html=cmi.step1Html.replace(/<input type='file' size=50 name='txtBrowse'>/,fixhtml);
}

merge(config.messages,{selectFile:'Please enter or select a file'}); // ready for I18N translation

window.browseForFilename=function(target,mustExist) { // note: both params are optional
	var msg=config.messages.selectFile;
	if (target && target.title) msg=target.title; // use target field tooltip (if any) as dialog prompt text
	// get local path for current document
	var path=getLocalPath(document.location.href);
	var p=path.lastIndexOf('/'); if (p==-1) p=path.lastIndexOf('\\'); // Unix or Windows
	if (p!=-1) path=path.substr(0,p+1); // remove filename, leave trailing slash
	var file=''
	var result=window.askForFilename(msg,path,file,mustExist); // requires #604
	if (target && result.length) // set target field and trigger handling
		{ target.value=result; target.onchange(); }
	return result; 
}
//}}}
***/
/***
!!!604 cross-platform askForFilename()
***/
/***
http://trac.tiddlywiki.org/ticket/604 - OPEN
invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.

DISABLED: rolled into tw 2.5.2
***/
/***
//{{{
window.askForFilename=function(msg,path,file,mustExist) {
	var r = window.mozAskForFilename(msg,path,file,mustExist);
	if(r===null || r===false)
		r = window.ieAskForFilename(msg,path,file,mustExist);
	if(r===null || r===false)
		r = window.javaAskForFilename(msg,path,file,mustExist);
	if(r===null || r===false)
		r = prompt(msg,path+file);
	return r||'';
}

window.mozAskForFilename=function(msg,path,file,mustExist) {
	if(!window.Components) return false;
	try {
		netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
		var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
		picker.init(window, msg, mustExist?nsIFilePicker.modeOpen:nsIFilePicker.modeSave);
		var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
		thispath.initWithPath(path);
		picker.displayDirectory=thispath;
		picker.defaultExtension='html';
		picker.defaultString=file;
		picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
		if (picker.show()!=nsIFilePicker.returnCancel)
			var result=picker.file.persistentDescriptor;
	}
	catch(ex) { displayMessage(ex.toString()); }
	return result;
}

window.ieAskForFilename=function(msg,path,file,mustExist) {
	if(!config.browser.isIE) return false;
	try {
		var s = new ActiveXObject('UserAccounts.CommonDialog');
		s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
		s.FilterIndex=3; // default to HTML files;
		s.InitialDir=path;
		s.FileName=file;
		return s.showOpen()?s.FileName:'';
	}
	catch(ex) { displayMessage(ex.toString()); }
	return result;
}

window.javaAskForFilename=function(msg,path,file,mustExist) {
	if(!document.applets['TiddlySaver']) return false;
	// TBD: implement java-based askFile(...) function
	try { return document.applets['TiddlySaver'].askFile(msg,path,file,mustExist); } 
	catch(ex) { displayMessage(ex.toString()); }
}
//}}}
***/

/***
!!!529 IE fixup - case-sensitive element lookup of tiddler elements
***/
/***
http://trac.tiddlywiki.org/ticket/529 - OPEN
This tweak hijacks the standard browser function, document.getElementById(), to work-around the case-INsensitivity error in Internet Explorer (all versions up to and including IE7) //''Note: This tweak is only applied when using IE, and only for lookups of rendered tiddler elements within the containing 'tiddlerDisplay' element.''//
***/
//{{{
if (config.browser.isIE) {
document.coreTweaks_coreGetElementById=document.getElementById;
document.getElementById=function(id) {
	var e=document.coreTweaks_coreGetElementById(id);
	if (!e || !e.parentNode || e.parentNode.id!='tiddlerDisplay') return e;
	for (var i=0; i<e.parentNode.childNodes.length; i++)
		if (id==e.parentNode.childNodes[i].id) return e.parentNode.childNodes[i];
	return null;
};
}
//}}}

/***
!!! 1134 handle references to tiddler sections in shadows
***/
/***
http://trac.tiddlywiki.org/ticket/1134
This tweak REPLACES and extends {{{store.getTiddlerText()}}} so it can return sections defined in shadow tiddlers.  It also permits use of leading whitespace in section headings.
***/
//{{{
TiddlyWiki.prototype.getTiddlerText = function(title,defaultText)
{
	if(!title) return defaultText;
	var parts = title.split(config.textPrimitives.sectionSeparator);
	var title = parts[0];
	var section = parts[1];
	var parts = title.split(config.textPrimitives.sliceSeparator);
	var title = parts[0];
	var slice = parts[1]?this.getTiddlerSlice(title,parts[1]):null;
	if(slice) return slice;
	var tiddler = this.fetchTiddler(title);
	var text = defaultText;
	if(this.isShadowTiddler(title))
		text = this.getShadowTiddlerText(title);
	if(tiddler)
		text = tiddler.text;
	if(!section) return text;
	var re = new RegExp("(^!{1,6}[ \t]*" + section.escapeRegExp() + "[ \t]*\n)","mg");
	re.lastIndex = 0;
	var match = re.exec(text);
	if(match) {
		var t = text.substr(match.index+match[1].length);
		var re2 = /^!/mg;
		re2.lastIndex = 0;
		match = re2.exec(t); //# search for the next heading
		if(match)
			t = t.substr(0,match.index-1);//# don't include final \n
		return t;
	}
	return defaultText;
};
//}}}

/***
!!!608/609/610 toolbars - toggles, separators and transclusion
***/
/***
http://trac.tiddlywiki.org/ticket/608 - OPEN (more/less toggle)
http://trac.tiddlywiki.org/ticket/609 - OPEN (separators)
http://trac.tiddlywiki.org/ticket/610 - OPEN (wikify tiddler/slice/section content)

This combination tweak extends the """<<toolbar>>""" macro to add use of '<' to insert a 'less' menu command (the opposite of '>' == 'more'), as well as use of '*' to insert linebreaks and "!" to insert a vertical line separator between toolbar items.  In addition, this tweak add the ability to use references to tiddlernames, slices, or sections and render their content inline within the toolbar, allowing easy creation of new toolbar commands using TW content (such as macros, links, inline scripts, etc.)

To produce a one-line style, with "less" at the end, use
| ViewToolbar| foo bar baz > yabba dabba doo < |
or to use a two-line style with more/less toggle:
| ViewToolbar| foo bar baz > < * yabba dabba doo |
***/
//{{{
merge(config.macros.toolbar,{
	moreLabel: 'more\u25BC',
	morePrompt: 'Show additional commands',
	lessLabel: '\u25C4less',
	lessPrompt: 'Hide additional commands',
	separator: '|'
});
config.macros.toolbar.onClickMore = function(ev) {
	var e = this.nextSibling;
	e.style.display = 'inline'; // show menu
	this.style.display = 'none'; // hide button
	return false;
};
config.macros.toolbar.onClickLess = function(ev) {
	var e = this.parentNode;
	var m = e.previousSibling;
	e.style.display = 'none'; // hide menu
	m.style.display = 'inline'; // show button
	return false;
};
config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	for(var t=0; t<params.length; t++) {
		var c = params[t];
		switch(c) {
			case '!':  // ELS - SEPARATOR (added)
				createTiddlyText(place,this.separator);
				break;
			case '*':  // ELS - LINEBREAK (added)
				createTiddlyElement(place,'BR');
				break;
			case '<': // ELS - LESS COMMAND (added)
				var btn = createTiddlyButton(place,
					this.lessLabel,this.lessPrompt,config.macros.toolbar.onClickLess,'moreCommand');
				break;
			case '>':
				var btn = createTiddlyButton(place,
					this.moreLabel,this.morePrompt,config.macros.toolbar.onClickMore,'moreCommand');
				var e = createTiddlyElement(place,'span',null,'moreCommand');
				e.style.display = 'none';
				place = e;
				break;
			default:
				var theClass = '';
				switch(c.substr(0,1)) {
					case '+':
						theClass = 'defaultCommand';
						c = c.substr(1);
						break;
					case '-':
						theClass = 'cancelCommand';
						c = c.substr(1);
						break;
				}
				if(c in config.commands)

					this.createCommand(place,c,tiddler,theClass);
				else { // ELS - WIKIFY TIDDLER/SLICE/SECTION (added)
					if (c.substr(0,1)=='~') c=c.substr(1); // ignore leading ~
					var txt=store.getTiddlerText(c);
					if (txt) {
						// trim any leading/trailing newlines
						txt=txt.replace(/^\n*/,'').replace(/\n*$/,'');
						// trim PRE format wrapper if any
						txt=txt.replace(/^\{\{\{\n/,'').replace(/\n\}\}\}$/,'');
						// render content into toolbar
						wikify(txt,createTiddlyElement(place,'span'),null,tiddler);
					}
				} // ELS - end WIKIFY CONTENT
				break;
		}
	}
};
//}}}
This course has:
<html>
<ul>
<li class="overlay1">Presentations - instructor led slide shows</li>
<li class="overlay2">Chapters - additional contents that extends the presentations and reference material</li>
<li class="overlay3">Quizzes - usually included in the chapters, these test your knowledge of the material</li>
</ul>
</html>
{{overlay4 {
All three are accessible from the left hand menu
}}}
In normal mode coursebook has a three column layout:
* left - the MainMenu has links to the major components of the coursebook
* center - called the story column (or just story) contains the tiddlers for reading
* right - controls to search, jump to tiddlers, save configure and get additional info

@@display: block;text-align: center;[img(75%,)[Frontscreen.png]]@@

In presentation (slide show) mode the three columns are reduced to one and a slide is shown full screen.
There are three ways to create chapter content:
# writing as separate small tiddlers
# writing as single tiddler and split into multiple tiddlers
# writing as a single large tiddler

!! Writing as Separate Small Tiddlers

* advantages
** it's the tiddlywiki way: small units of microcontent that can be searched, annotated and combined
** works well from an outline as each subhead is a tiddler
** can be expanded easily to include subsub heads as individual tiddlers
**  allows search to isolate just the small tiddler unit that matches the search
** since notes are at tiddler level, the notes are closely associated with the microcontent tiddler making them more useful and placing them in context
* disadvantages
** creates a lot of tiddlers and it's easy to get lost in multitudes of tiddlers
** writing is fragmented and flow through the chapter is sacrificed or harder to get
**  editing subitems needs to be done in tiddlywiki interface. Can't use other tools (e.g. a full featured editor with search/replace) easily.

!! Write as Single Tiddler and Split into Multiple Tiddlers

In this case you write a single large tiddler and when it is nearly complete, you use section heads and the SplitTiddler function to split it into separate bite size tiddlers.

* advantages
** provides microcontent tiddlers
** can be made to use subtiddlers (e.g. for second or third level items in an outline), but doing so selectively without manual cut and paste is a bit trickier
** large chapter format is easier to edit in a word processor or other tool
** better flow of text from section to section
** allows search to isolate just the small tiddler unit that matches the search
** since notes are at tiddler level, the notes are closely associated with the microcontent tiddler making them more useful and placing them in context. But usually the context is larger in this method compared to writing content as multiple tiddlers to begin with.
* disadvantages
** better text flow may not make sense when tiddlers are split apart (since tiddlers are stand alone, units, reference to other content is the chapter is in a different tiddler that may not be displayed)
** links to other content within the chapter usually have to be redone
** spitting the chapter content using SplitTiddler is a little tricky and may require additional effort

!! writing as a single large tiddler
You can also write a chapter as one large multi-page/screen tiddler.

* advantages
** better flow of text in chapter since the content isn't able to be displayed as individual tiddlers which breaks the flow
** ability to use external authoring tools
* disadvantages
** not the tiddlywiki way
** searching pulls up entire chapter and not the focused micro content, so browser search function may be needed to find desired content rather than being able to visually scan
** bookmarking tiddler is less useful because of larger scope of content
** notes/annotations by student are at the tiddler level, so a large chapter tiddler moves the notes far from where they are meant to be used and context for the notes is lost

Note that the content of the chapter needs to be in a separate tiddler linked from the control tiddler to make the standard links/section mechanisms work.
Create a new chapter control tiddler by selecting the @@new chapter tiddler@@ link from the sidebar.

In the tiddler create links to the subtiddlers. If you have an outline or mindmap of the content, the first and second level headers can be pasted into the tiddler and surrounded with double brackets {{[[...]]}} to create link from the entry. Once you are done editing, you have a list of tiddlers in the chapter. If the tiddler doesn't exist the link is in italics (links to existing tiddlers are in bold face type e.g. [[Creating Chapter Content as Separate Tiddlers]]).

For each link pointing to a non-existent tiddler click on the link to open the placeholder. The edit the place holder to add the content. Also you must add the tag {{{content}}} tag to the tiddler if the students should see the content. Continue until all the content has been created.

In the first tiddler of the chapter prepend {{{<<tiddler ChapterStart>>}}} to the first line of the tiddler. This will make the tiddler start on a new page when printed.
Create a new chapter control tiddler by selecting the @@new chapter tiddler@@ link from the sidebar and create a link to the large tiddler you will be editing. E.G. IF you have created the {{{Chapter  2 - chapter title here}}} control tiddler add the link to your content tiddler. For example: {{{[[chapter title here]]}}} and save the control tiddler.

Click on the link in italics, tag it with the {{{content}}} tag and start writing. Start the tiddler with {{{<<tiddler ChapterStart>>}}} prepended to the first line of the tiddler. This will make the tiddler start on a new page when printed.
Create a new chapter control tiddler by selecting the @@new chapter tiddler@@ link from the sidebar and create a link to the large tiddler
you will be editing. E.G. IF you have created the Chapter 2 control tiddler add the link: {{{[[SOURCE Chapter  2 -- chapter title here]]}}}
and save the control tiddler. FIXME is this needed? Inde tiddler after split canbe made into control tiddler.

Click on the SOURCE link in the control tiddler and write your large tiddler using TiddlyWiki markup for the section heads. Tag the SOURCE tiddler with {{{InstructorOnly}}} as the SOURCE tiddler won't get published to the students. As you write assume each level 1 header (prefixed with a {{{!}}}) will be a tiddler. The level 2 headers (prefixed with  {{{!!}}}) may also become tiddlers depending on the length of the sections and your preference.

When the SOURCE tiddler is sufficiently polished break it apart by following the directions in [[Splitting Chapters]].

After you have split the tiddlers, make sure the first tiddler in the chapter has {{{<<tiddler ChapterStart>>}}} prepended to the first line of the tiddler. This will make the tiddler start on a new page when printed.
When teaching the delivery of content is often required to be in a particular form. PDF is often used as the deliverable format because it is portable to many platforms (MS Windows, Apple, Linux, Unix) and is not able to be modified by default preserving the author's original intent. Note that creating pdf's is somewhat tedious and time consuming, so you may want to do it for only your final release.

To create a pdf that visually replicates the information in the Coursebook under MS Windows, you can use the free [[PDFCreator|http://sourceforge.net/projects/pdfcreator/]]. PDFCreator creates a new printer under windows and printing to that printer creates a pdf file. Details on setup/tuning can be found at http://www.linux.com/archive/feed/59229.

Once PDFCreator is installed, printing to the new printer produces a pdf file with the following restrictions:
* links are displayed as links but don't actually work
* no bookmarks are created (but see below)
* no active content (e.g. popups are supported)

You can add bookmarks to the pdf document using the free [[JPdfBookmarks|http://sourceforge.net/projects/jpdfbookmarks/]] software. It is written in java, so it should be usable on all the platforms java supports. An example using it is available at: http://www.freewaregenius.com/2010/05/24/how-to-add-bookmarks-to-a-pdf-document-using-free-software/.

Below I discuss printing details for slides/presentations and chapters.

!! Printing Presentations/Slides in 2up Format

Display your presentation for printing as described in [[Printing Slide Set]] using the steps for SlideShowPlugin print mode.

Choose Page Setup from the browsers menu. In the Page Setup/Margins dialog, set:
* left header to document title
* middle header to nothing
* right header to Page N of M (sometimes displayed as page # of #)
* left footer to the course instance, e.g. a short name/date string using the custom setting
* middle footer to the title of your course using the custom setting
* right footer to print date and time (used to identify which slide set you are looking at if multiple printouts were done at different times).
Each slide will be printed with these 5 pieces of info.

Since slides are displayed at a larger font than a chapter you can usually print them 2-up on a page. This also provides some room for students to write notes under each slide.

Set an appropriate title for the printed slide set using @@change title@@ from the instructor menu in the right sidebar as described in [[instructor menu|TiddlyWiki Page Layout (Instructor)##instructorMenu]]. Then use your browser's print menu item to start the printer setup process.
Set the print mode to 2up by:
* Choose the PDFCreator printer from the drop down selector.
* Choose Properties/Layout (or Properties/Advanced/Printing defaults)
* Set the Pages per sheet to 2
* Select ok to get back to the Print dialog.
Start printing by clicking on "OK" in the print dialog. This will pop up the PDFCreator configuration tool. Select autosave from the left hand tree and set the output directory. Set the filename to {{{<Title>-<DateTime>}}}. Note that the first 10 characters of the title of the web page must are used for the {{{<Title>}}} token.
As a result the title must be unique in the first 10 or so characters as that is used to determine the output file name. Adding the {{{<DateTime>}}} is optional, but it will prevent overwriting the file if you don't have a unique 10 characters at the beginning of the page title. You can also set other options as described in http://www.linux.com/archive/feed/59229 if you haven't already done so, but it will take effect only for this printing session.

When PDFCreator is set to autosave, it will generate a file in the autosave directory and optionally pull up the default pdf viewer on the file.

When all the slide show proofs look ok, use [[pdftk|http://www.accesspdf.com/pdftk/]] to combine them into a single pdf file:
{{{
pdftk Presentation\ ?\ *.pdf Presentation\ ??\ *.pdf cat output ../pdf/S2_SEC_Presentations.pdf
}}}
Go through the pdf file with a couple of pdf readers (acrobat and foxit for example) to verify headers on top left match the presentation, lines aren't too long which results in them being cut off etc.

!!  Chapters (1 up)
Chapters are usually printed with a page on a single sheet of paper. To start display one or more chapters for printing as described in [[Printing Chapters]].

Choose Page Setup from the browsers menu. In the Page Setup/Margins dialog, set:
* left header to document title
* middle header to nothing
* right header to Page N of M (sometimes displayed as page # of #)
* left footer to the course instance, e.g. a short name/date string using the custom setting
* middle footer to the title of your course using the custom setting
* right footer to print date and time (used to identify which slide set you are looking at if multiple printouts were done at different times).
Each slide will be printed with these 5 pieces of info.

Set an appropriate title for the printed slide set using @@change title@@ from the instructor menu in the right sidebar as described in [[instructor menu|TiddlyWiki Page Layout (Instructor)##instructorMenu]].  For example set it to "Chapter 1-5"  or "Chapters 6-10". All the rest of the header/footer info stays the same. Then in the browser

* Use control-p or the print menu item to pull up the print dialog
* Choose the PDFCreator printer from the drop down selector.
* Choose Properties/Layout (or Properties/Advanced/Printing defaults)
* Set the Pages per sheet to 1
* Select ok to get back to the Print dialog.
Clicking on the "OK" button will start the printing process.
To create new quiz tiddler:
# create a new content tiddler using @@new content tiddler@@ and add a link to it to an existing chapter or other tiddler.
# tag the tiddler with {{{quiz}}}. This allows it to show up in the  list of all quizzes in the QuizList tiddler.

The using the syntax of the  [[QuizzerPlugin|QuizzerPluginDoc]] create your quiz entries:
* select the correct item
* true/false question
* select all correct items
* respond as an essay answer

!! Select One Item Question

Example:

(FIXME the plugin is broken with 2.6 of tw core)
; 1: What is the unit of content in a TiddlyWiki called
<<quiz type:S= id:contenttw >> page
<<quiz type:S= id:contenttw value:true >> tiddler
<<quiz type:S= id:contenttw >> splonk
<<quiz type:S= id:contenttw >> content

The code to produce this quiz is:
{{{
; 1: What is the unit of content in a TiddlyWiki called
<<quiz type:S= id:contenttw >> page
<<quiz type:S= id:contenttw value:true >> tiddler
<<quiz type:S= id:contenttw >> splonk
<<quiz type:S= id:contenttw >> content
}}}

!! True/False Question

; 2: Classify the following sentences as ''true'' or ''false'':
| T/F ||h
|<<quiz type:T= value:true id:Q2.1>>|A. The Earth is bigger than the Sun. |
|<<quiz type:T= id:Q2.2>>|B. If all men are mortal, and John is a man, then John is mortal.|
|<<quiz type:T value:true id:Q2.3>>|C. The Earth is bigger then Saturn.|
|<<quiz type:T id:Q2.4>>|D. 2+2 = 4.|

The code to produce this quiz is:
{{{
; 2: Classify the following sentences as ''true'' or ''false'':
| T/F ||h
|<<quiz type:T= value:true id:Q2.1>>|A. The Earth is bigger than the Sun. |
|<<quiz type:T= id:Q2.2>>|B. If all men are mortal, and John is a man, then John is mortal.|
|<<quiz type:T value:true id:Q2.3>>|C. The Earth is bigger then Saturn.|
|<<quiz type:T id:Q2.4>>|D. 2+2 = 4.|
}}}

!! Select All Correct Items                
; 3:  Select all the valid SEC rule types
|<<quiz value:true score:5 >> calendar  |<<quiz score:-5 >> cron      |
|<<quiz score:-5 >> ignore                    |<<quiz value:true score:5 >> single       |
|<<quiz value:true score:5 >> suppress |<<quiz score:-5 >> handler |
|<<quiz value:true score:5 >> pair         |<<quiz value:true score:5 >> pairwithwindow |
|<<quiz score:-5>> triplet                     |<<quiz value:true score:5 >>singlewiththreshold |
|<<quiz score:-5 >> count                     |<<quiz score:-5>>threshold                              |

<<score>>

The code to create this is:
{{{
; 3:  Select all the valid SEC rule types
|<<quiz value:true score:5 >> calendar  |<<quiz score:-5 >> cron      |
|<<quiz score:-5 >> ignore                    |<<quiz value:true score:5 >> single       |
|<<quiz value:true score:5 >> suppress |<<quiz score:-5 >> handler |
|<<quiz value:true score:5 >> pair         |<<quiz value:true score:5 >> pairwithwindow |
|<<quiz score:-5>> triplet                     |<<quiz value:true score:5 >>singlewiththreshold |
|<<quiz score:-5 >> count                     |<<quiz score:-5>>threshold                              |

<<score>>
}}}

!! Respond as an Essay Answer
;4: Create a replacement for the following pair with window rule using contexts and single commands:
{{{
type=PairWithWindow
desc=Pair: the first event match
ptype=regexp
pattern=(Event) one
action=write - Pair: no event two seen
desc2=Pair the second event match
ptype2=regexp
pattern2=$1 two
action2= write - Pair: event one and two were seen
window = 20
}}}
Here is the sample input for [[play_events]]:
{{{
# will find both in the 20 second window
0 Event one
3 Event one
3 Something two
10 Event two
2 Event two
# will fail to find both in window
0 Event one
22 Event two
}}}
<<slider {{config.options['']=false;'';}} ./Answer1 "Answer ..." "Answer to question">>
<part Answer1 hidden>
{{{
type = single
desc = The first event match
ptype = regexp
pattern = (Event) one
context = ! seen_$1_one
action = create seen_Event_one 20 write - Single: No event two seen

type = single
desc = The first event match - suppress while searching for event two
ptype = regexp
pattern = (Event) one
context = seen_$1_one
action = none

type = single
desc = The second event match
ptype = regexp
pattern = (Event) two
context = seen_$1_one
action = delete seen_$1_one; write - Single: event one and two were seen
}}}
</part>

Edit this tiddler to see the code used to make this work.
To create tiddlers that can automatically show up in the [[reference]] tiddler:
# create a content tiddler using the @@new content tiddler@@ and add the {{{reference}}} tag to it.

Like Chapters, references are in alphabetic order. If you want another order editing ChapterList and replacing the matchtags macro with a manually ordered list of references. This way you can order the most used reference tiddlers at the top.
The themes are created using CSS. You can see a couple of themes: InstructorSlideShowStyleSheet SlideShowTheme in this coursebook. For other info on creating slide, I suggest visiting the SlideShowPlugin author's site: 	http://www.math.ist.utl.pt/~psoares/addons.html and asking questions on the tiddlywiki google group: <<tiddler [[Resources::tiddlywikiGoogleGroup]]>>.
Edit the tags on the tiddler prepending: {{{chapter story content}}} as first tags on the tiddler. Change title of tiddler if needed to make it show up in the correct place in the Chapter list in the MainMenu.  Note that content of the chapter tiddler is ignored by the chapter mechanism. Only links to other tiddlers int he chapter control tiddler are used. If you want the content of the tiddler to be displayed, move it to a new tiddler tagged with content and create a link to the new tiddler.

For the first tiddler in a chapter, prepend {{{<<tiddler ChapterStart>>}}} to the first line of the tiddler. This will make the tiddler start on a new page when printed.
! Creating the Presentation
There are two ways to create a presentation:
# From the right hand sidebar, choose @@new presentation@@
## a tiddler tagged with {{{presentation content story}}} is created
## add a title in the top single line box. Presentations are sorted by title so a standard title prefix "Presentation  1" with two spaces before the 1 allows sorting to work properly as it sorts {{{Presentation  1}}} before "Presentation 11". Note that some browsers (IE for example) don't display the full presentation title in the pull down list in the MainMenu on the left hand side of the display. As a result you should make title unique in first 15 characters to allow the user to properly identify and select the presentation from the pull down list.
## add double bracketed references to the titles of the slides to be displayed in this presentation to the tiddler. For example: {{{[[Introduction to the topic]] [[More info on topic]]}}} ...
## if a slide is missing, it will be in italics and not normal bolded text
## click on each slide title reference to create/edit the slide. Add the tags {{{slide content}}} to the beginning of the tag list (in the bottom single line box if needed.
# edit existing tiddler
## add the tags {{{presentation content story}}} as the first tags on the tiddler
## change title of tiddler if needed
## proceed as above with adding double bracketed references to the presentation tiddler.

The procedures above create a multi-tiddler presentation. If you want to create a single tiddler presentation, the process is similar:
# From the right hand sidebar, choose @@new presentation@@
# delete the {{{story}}} tag from the tiddler.
##  Rather than creating links/reference to tiddlers, each slide is separated from the next by the use of {{{-s-}}} markers in the tiddler. Each @@white-space:nowrap;{{{-s-}}}@@ sits on a line of it's own.
## You need to include a custom slideShow start button that uses the single keyword at the top of the tiddler.
*** For example: <<tiddler [[Creating a Presentation##SlideButton]]>>
*** {{{exclude}}} prevents any WikiWords or bracketed references from being part of the slide show
*** {{{comment}}} prevents the button from showing up on the slide
** Include the comment class in the button text so that WikiWords in the slideShow macro don't show up as slides in the presentation.

Tiddlers tagged with Presentation are automatically included in the PresentationList tiddler which formats the Presentation section in the MainMenu displayed on the left hand side of the coursebook. If you want to change the way the presentations are displayed, edit the PresentationList tiddler. Also if you want to order the presentations explicitly, you will need to edit the PresentationList tiddler and explicitly add links for all the presentations you want to have displayed.

/%
A tiddlywiki trick to create a hidden section that will be included in the visible topic using a tiddler macro call. This
gets around parsing issues when you have a lot of tiddlywiki markup involved.
!SlideButton
{{{
{{exclude comment{<<slideShow single  theme:InstructorSlideShowStyleSheet3 toc:header  footer:"copyright&copy; 2010"  label:"Start autoplay" tooltip:"Autoplay show in instructor projection mode" cycle auto:10>> }}}
}}}
!end
%/
There are two ways to make a slide:

# From the right sidebar, choose @@new slide@@
** a tiddler tagged with *slide content* is created.
** edit slide
** add reference to slide to a presentation tiddler. If the slide title is a WikiWord, just include the WikiWord otherwise place the slide title inside of double brackets. E.G. {{{[[slide title]]}}}. You can change the displayed name of the slide using the {{{[[descriptive string|slide title]]}}} linking mechanism
# edit existing tiddler
** add "slide content" as first tags on tiddler
** add reference to tiddler to existing presentation tiddler as above.

Add content to your slide using [[standard tiddlywiki markup|FormattingCheatSheet]] or you can embed raw html in the tiddler by surrounding the html with {{{<html>}}} and {{{</html>}}} tags. If you want to place tiddlywiki markup inside of your html block, you will want to install the [[HtmlFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo]] from 	http://www.TiddlyTools.com/#HTMLFormattingPlugin. ([img(16px,)[warning-icon.png]] Note that you will need to tag the plugin with the tag @@structure@@ so that it will be exported to the coursebook framework.)
The student textbook is a exported copy of the instructor book.

Use the:
* @@Instructor@@->@@save studentbook@@
* @@Instructor@@->@@save content@@
links in the right hand sidebar.

As with normal student and instructor text books, additional info in instructor book.

{{comment{
As discussed previously, the framework and content are separate entities that are combined to make the coursebook. The separate content allows updating of only the content in the coursebook without updating the javascript and other programmatic elements that make the coursebook work.
}}}
Besides producing PDF, you can create a snapshot of the page with the html required to display the same was as in tiddlywiki. Note that links (unless explicitly written using html) popups, sliders and other active content won't work as there is no javascript in the snapshot page to provide the functionality. However this may be a useful mechanism for somebody.

The [[snapshot plugin|http://www.tiddlytools.com/#SnapshotPluginInfo%20SnapshotPlugin]] can be [[imported|Using the Backstage Link##Importing a new plugin]] from http://www.tiddlytools.com and used to create a snapshot. The [[SnapshotPluginInfo|http://www.tiddlytools.com/#SnapshotPluginInfo]] tiddler describes how to use the plugin.
A chapter is an ordered list of tiddlers. The first tiddler in the chapter should start with:
{{{
<<tiddler ChapterStart>>
}}}

This will create a page break when printing the cgapter so it starts on a new page.
Follow it with the text of the tiddler on the same line right after the closing >>'s.

All the tiddlers for a chapter are gathered into a master chapter tiddler.
Author: John Rouillard rouilj+coursebook@cs.~NOSPAMumb.edu (remove NOSPAM from the address before sending)

Thanks to the following TiddlyWiki plugin authors for their adaptations and changes to plugins in response to the needs of this coursebook.

A special mention to Eric L. Shulman for his SectionLinksPlugin and many others. Also credit must be given for his extensive help in IRC with debugging this coursebook.

Paulo Soares: SlideShowPlugin

Plus I must thank the staff at the University of Massachusetts at Boston Math and Computer Science departments for their continued support.
ReadMe
[[Welcome]]
The tiddlers marked with DeletedTiddler have been superseded by other tiddlers. To cleanup your coursebook, delete them.

If there are any tiddlers you need to delete, there will be a grey box marked "tagging" on the top left (not to be confused with the "tags" box on the right). You can go through each tiddler and find out why it was deleted and preserve any notes you may have for that tiddler before you delete it.

The following link will delete them automatically, it can not be undone, you will have to reload this tiddlywiki before saving or go to backups to recover the tiddlers.

<script label="Remove the tiddlers marked with DeletedTiddlers">
var tids=store.getTaggedTiddlers('DeletedTiddler'); for (var t=0; t<tids.length; t++) store.deleteTiddler(tids[t].title);
displayMessage('Deleted ' + tids.length + ' tiddlers.');
</script>

After deleting the tiddlers, you need to save the coursebook using the ''save changes'' link in the right hand sidebar. Note that there may not be any indication that the coursebook has changed.
* Instructor has tools for improving editing/creation
* Instructor tiddlywiki has themes for presentations
* Student is a read-mostly config
* Instructor book can publish documents
There are two ways to start a presentation:
# Choose the presentation title link from the presentation link section
** In the instructor coursebook it starts the presentation with the [[instructor theme|InstructorSlideShowStyleSheet]].
** In the student coursebook it starts the presentation with the [[student theme|SlideShowTheme]]
# Open the presentation control tiddler and chose the Instructor, Student or Print display mode.
/***
|Name|DisplayOpenTiddlersPlugin|
|Location|http://www.orst.edu/~woodswa/tiddlywikiplugs.html|
|Version|1.0|
|Author|Walt Woods|
|Requirements||

!Description
Displays similar to the popular BreadCrumbsPlugin by AlanHecht, this plugin instead keeps a list of currently open tiddlers.

!History
09-06-2009: JohnRouillard modified seperator between items on tiddler line.
08-06-2007: Initial version.

!Code
***/
//{{{
version.extensions.DisplayOpenTiddlers = {major: 1, minor: 0, revision: 0};

function addOpenTiddlerLine(title, element)
{
 if (title != openTiddlerClosing)
 {
  if (tiddlerLine != "")
   tiddlerLine += " &bull; ";
  tiddlerLine += "[[" + title + "]]";
 }
}

function refreshOpenTiddlersList()
{
 if (!document.getElementById("openTiddlers")) {
  var ta = document.createElement("div");
  ta.id = "openTiddlers";
  ta.style.visibility= "hidden";
  var targetArea = document.getElementById("tiddlerDisplay")||document.getElementById("storyDisplay");
  targetArea.parentNode.insertBefore(ta,targetArea);
 }

 var tiddlers = document.getElementById("openTiddlers");
 tiddlers.style.visibility = "visible";
 removeChildren(tiddlers);
 
 tiddlerLine = "";
 story.forEachTiddler(addOpenTiddlerLine);
 wikify(tiddlerLine,tiddlers)
}

Story.prototype.displayTiddlerDisplayOpenTiddlers = Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
{
 this.displayTiddlerDisplayOpenTiddlers(srcElement,title,template,animate,slowly);
 openTiddlerClosing = "";
 refreshOpenTiddlersList();
}

Story.prototype.closeTiddlerDisplayOpenTiddlers = Story.prototype.closeTiddler;
Story.prototype.closeTiddler = function(title,animate,unused)
{
 this.closeTiddlerDisplayOpenTiddlers(title,animate,unused);
 openTiddlerClosing = title;
 refreshOpenTiddlersList();
}
//}}}
! Dynamic content - footnotes, annotations, popups, sliders oh my

There are multiple ways to add dynamic content: i.e. content that displays something when triggered by mouse click, hover ...

|Technique                    |Popup  |Footnote    |Annotation  | Slider |h
|Display Location           |at site   |end tiddler |at site          |at site |
|Printable                       |yes       |yes            |no                |yes if open |
|Covers Text                  |yes       |no              |yes              |no moves text |

Annotations vs footnotes (really endnotes). Footnotes are displayed at the end of the tiddler and are displayed in print. Footnotes print after the tiddler is displayed. So the footnotes for the current chapter may be pushed to the top of the page for the next chapter when printed. Annotations are displayed in place, but obscure text and can not be printed, also their contents can't be clicked on or interacted with.

Popups used when I have a larger amount of text to show. More than 2-3 sentences. It should not be used for core content since it obscures text when displayed. Popups particularly good for navigation features, lists of terms/jumps to other tiddlers. It can be intereacted with by the user unlike annotations which disappear when the mouse is moved off the trigger.

Sliders like popups are good for large amounts of text. Can be printed and don't obscure other text.
They can be made to display or not display by default. They may simplify the layout of large text segments or allow optional segments to be hidden but still easily accessible if the student is interested.
$1
<!--{{{-->
<!--added convert macro to toolbar-->
<div class='toolbar'><span  macro='toolbar [[ToolbarCommands::EditToolbar]]'></span>
<span class='toolbar' macro='tiddler QuickEdit_convert'></span> </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 excludeLists'></span></div>
<!--}}}-->
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|interactively select/export tiddlers to a separate file|
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2010.02.25 2.9.5 added merge checkbox option and improved 'merge' status message
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 0.0.0 development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 9, revision: 5, date: new Date(2010,2,25)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers='<<exportTiddlers inline>>';

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		text:'export',
		tooltip:'Export selected tiddlers to another file',
		content:'<<exportTiddlers inline>>'
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf('importTask')+1,0,'exportTask');
}

config.macros.exportTiddlers = {
	$: function(id) { return document.getElementById(id); }, // abbreviation
	label: 'export tiddlers',
	prompt: 'Copy selected tiddlers to an export document',
	okmsg: '%0 tiddler%1 written to %2',
	failmsg: 'An error occurred while creating %1',
	overwriteprompt: '%0\ncontains %1 tiddler%2 that will be discarded or replaced',
	mergestatus: '%0 tiddler%1 added, %2 tiddler%3 updated, %4 tiddler%5 unchanged',
	statusmsg: '%0 tiddler%1 - %2 selected for export',
	newdefault: 'export.html',
	datetimefmt: '0MM/0DD/YYYY 0hh:0mm:0ss',  // for 'filter date/time' edit fields
	type_TW: "tw", type_PS: "ps", type_TX: "tx", type_CS: "cs", type_NF: "nf", // file type tokens
	type_map: { // maps type param to token values
		tiddlywiki:"tw", tw:"tw", wiki: "tw",
		purestore: "ps", ps:"ps", store:"ps",
		plaintext: "tx", tx:"tx", text: "tx",
		comma:     "cs", cs:"cs", csv:  "cs",
		newsfeed:  "nf", nf:"nf", xml:  "nf", rss:"nf"
	},
	handler: function(place,macroName,params) {
		if (params[0]!='inline')
			{ createTiddlyButton(place,this.label,this.prompt,this.togglePanel); return; }
		var panel=this.createPanel(place);
		panel.style.position='static';
		panel.style.display='block';
	},
	createPanel: function(place) {
		var panel=this.$('exportPanel');
		if (panel) { panel.parentNode.removeChild(panel); }
		setStylesheet(store.getTiddlerText('ExportTiddlersPlugin##css',''),'exportTiddlers');
		panel=createTiddlyElement(place,'span','exportPanel',null,null)
		panel.innerHTML=store.getTiddlerText('ExportTiddlersPlugin##html','');
		this.initFilter();
		this.refreshList(0);
		var fn=this.$('exportFilename');
		if (window.location.protocol=='file:' && !fn.value.length) {
			// get new target path/filename
			var newPath=getLocalPath(window.location.href);
			var slashpos=newPath.lastIndexOf('/'); if (slashpos==-1) slashpos=newPath.lastIndexOf('\\'); 
			if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
			fn.value=newPath+this.newdefault;
		}
		return panel;
	},
	togglePanel: function(e) { var e=e||window.event;
		var cme=config.macros.exportTiddlers; // abbrev
		var parent=resolveTarget(e).parentNode;
		var panel=cme.$('exportPanel');
		if (panel==undefined || panel.parentNode!=parent)
			panel=cme.createPanel(parent);
		var isOpen=panel.style.display=='block';
		if(config.options.chkAnimate)
			anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,'none'));
		else
			panel.style.display=isOpen?'none':'block' ;
		if (panel.style.display!='none') {
			cme.refreshList(0);
			cme.$('exportFilename').focus(); 
			cme.$('exportFilename').select();
		}
		e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
	},
	process: function(which) { // process panel control interactions
		var theList=this.$('exportList'); if (!theList) return false;
		var count = 0;
		var total = store.getTiddlers('title').length;
		switch (which.id) {
			case 'exportFilter':
				count=this.filterExportList();
				var panel=this.$('exportFilterPanel');
				if (count==-1) { panel.style.display='block'; break; }
				this.$('exportStart').disabled=(count==0);
				this.$('exportDelete').disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) { alert('No tiddlers were selected'); panel.style.display='block'; }
				break;
			case 'exportStart':
				this.go();
				break;
			case 'exportDelete':
				this.deleteTiddlers();
				break;
			case 'exportHideFilter':
			case 'exportToggleFilter':
				var panel=this.$('exportFilterPanel')
				panel.style.display=(panel.style.display=='block')?'none':'block';
				break;
			case 'exportSelectChanges':
				var lastmod=new Date(document.lastModified);
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=='') continue;
					var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
					theList.options[t].selected=(tiddler.modified>lastmod);
					count += (tiddler.modified>lastmod)?1:0;
				}
				this.$('exportStart').disabled=(count==0);
				this.$('exportDelete').disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) alert('There are no unsaved changes');
				break;
			case 'exportSelectAll':
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=='') continue;
					theList.options[t].selected=true;
					count += 1;
				}
				this.$('exportStart').disabled=(count==0);
				this.$('exportDelete').disabled=(count==0);
				this.displayStatus(count,count);
				break;
			case 'exportSelectOpened':
				for (var t=0; t<theList.options.length; t++) theList.options[t].selected=false;
				var tiddlerDisplay=this.$('tiddlerDisplay');
				for (var t=0; t<tiddlerDisplay.childNodes.length;t++) {
					var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
					for (var i=0; i<theList.options.length; i++) {
						if (theList.options[i].value!=tiddler) continue;
						theList.options[i].selected=true; count++; break;
					}
				}
				this.$('exportStart').disabled=(count==0);
				this.$('exportDelete').disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) alert('There are no tiddlers currently opened');
				break;
			case 'exportSelectRelated':
				// recursively build list of related tiddlers
				function getRelatedTiddlers(tid,tids) {
					var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
					tids.push(t.title);
					if (!t.linksUpdated) t.changed();
					for (var i=0; i<t.links.length; i++)
						if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
					return tids;
				}
				// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
				var tids=[];
				for (var i=0; i<theList.options.length; i++)
					if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
				// select related tiddlers (includes original selected tiddlers)
				for (var i=0; i<theList.options.length; i++)
					theList.options[i].selected=tids.contains(theList.options[i].value);
				this.displayStatus(tids.length,total);
				break;
			case 'exportListSmaller':	// decrease current listbox size
				var min=5;
				theList.size-=(theList.size>min)?1:0;
				break;
			case 'exportListLarger':	// increase current listbox size
				var max=(theList.options.length>25)?theList.options.length:25;
				theList.size+=(theList.size<max)?1:0;
				break;
			case 'exportClose':
				this.$('exportPanel').style.display='none';
				break;
		}
		return false;
	},
	displayStatus: function(count,total) {
		var txt=this.statusmsg.format([total,total!=1?'s':'',!count?'none':count==total?'all':count]);
		clearMessage();	displayMessage(txt);
		return txt;
	},
	refreshList: function(selectedIndex) {
		var theList = this.$('exportList'); if (!theList) return;
		// get the sort order
		var sort;
		if (!selectedIndex)   selectedIndex=0;
		if (selectedIndex==0) sort='modified';
		if (selectedIndex==1) sort='title';
		if (selectedIndex==2) sort='modified';
		if (selectedIndex==3) sort='modifier';
		if (selectedIndex==4) sort='tags';

		// unselect headings and count number of tiddlers actually selected
		var count=0;
		for (var t=5; t < theList.options.length; t++) {
			if (!theList.options[t].selected) continue;
			if (theList.options[t].value!='')
				count++;
			else { // if heading is selected, deselect it, and then select and count all in section
				theList.options[t].selected=false;
				for ( t++; t<theList.options.length && theList.options[t].value!=''; t++) {
					theList.options[t].selected=true;
					count++;
				}
			}
		}

		// disable 'export' and 'delete' buttons if no tiddlers selected
		this.$('exportStart').disabled=(count==0);
		this.$('exportDelete').disabled=(count==0);

		// show selection count
		var tiddlers = store.getTiddlers('title');
		if (theList.options.length) this.displayStatus(count,tiddlers.length);

		// if a [command] item, reload list... otherwise, no further refresh needed
		if (selectedIndex>4) return;

		// clear current list contents
		while (theList.length > 0) { theList.options[0] = null; }
		// add heading and control items to list
		var i=0;
		var indent=String.fromCharCode(160)+String.fromCharCode(160);
		theList.options[i++]=
			new Option(tiddlers.length+' tiddlers in document', '',false,false);
		theList.options[i++]=
			new Option(((sort=='title'   )?'>':indent)+' [by title]', '',false,false);
		theList.options[i++]=
			new Option(((sort=='modified')?'>':indent)+' [by date]', '',false,false);
		theList.options[i++]=
			new Option(((sort=='modifier')?'>':indent)+' [by author]', '',false,false);
		theList.options[i++]=
			new Option(((sort=='tags'    )?'>':indent)+' [by tags]', '',false,false);

		// output the tiddler list
		switch(sort) {
			case 'title':
				for(var t = 0; t < tiddlers.length; t++)
					theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
				break;
			case 'modifier':
			case 'modified':
				var tiddlers = store.getTiddlers(sort);
				// sort descending for newest date first
				tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
				var lastSection = '';
				for(var t = 0; t < tiddlers.length; t++) {
					var tiddler = tiddlers[t];
					var theSection = '';
					if (sort=='modified') theSection=tiddler.modified.toLocaleDateString();
					if (sort=='modifier') theSection=tiddler.modifier;
					if (theSection != lastSection) {
						theList.options[i++] = new Option(theSection,'',false,false);
						lastSection = theSection;
					}
					theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
				}
				break;
			case 'tags':
				var theTitles = {}; // all tiddler titles, hash indexed by tag value
				var theTags = new Array();
				for(var t=0; t<tiddlers.length; t++) {
					var title=tiddlers[t].title;
					var tags=tiddlers[t].tags;
					if (!tags || !tags.length) {
						if (theTitles['untagged']==undefined) { theTags.push('untagged'); theTitles['untagged']=new Array(); }
						theTitles['untagged'].push(title);
					}
					else for(var s=0; s<tags.length; s++) {
						if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
						theTitles[tags[s]].push(title);
					}
				}
				theTags.sort();
				for(var tagindex=0; tagindex<theTags.length; tagindex++) {
					var theTag=theTags[tagindex];
					theList.options[i++]=new Option(theTag,'',false,false);
					for(var t=0; t<theTitles[theTag].length; t++)
						theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
				}
				break;
			}
		theList.selectedIndex=selectedIndex; // select current control item
		this.$('exportStart').disabled=true;
		this.$('exportDelete').disabled=true;
		this.displayStatus(0,tiddlers.length);
	},
	askForFilename: function(here) {
		var msg=here.title; // use tooltip as dialog box message
		var path=getLocalPath(document.location.href);
		var slashpos=path.lastIndexOf('/'); if (slashpos==-1) slashpos=path.lastIndexOf('\\'); 
		if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
		var filetype=this.$('exportFormat').value.toLowerCase();
		var defext='html';
		if (filetype==this.type_TX) defext='txt';
		if (filetype==this.type_CS) defext='csv';
		if (filetype==this.type_NF) defext='xml';
		var file=this.newdefault.replace(/html$/,defext);
		var result='';
		if(window.Components) { // moz
			try {
				netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
				var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
				var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
				picker.init(window, msg, nsIFilePicker.modeSave);
				var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
				thispath.initWithPath(path);
				picker.displayDirectory=thispath;
				picker.defaultExtension=defext;
				picker.defaultString=file;
				picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
				if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
			}
			catch(e) { alert('error during local file access: '+e.toString()) }
		}
		else { // IE
			try { // XPSP2 IE only
				var s = new ActiveXObject('UserAccounts.CommonDialog');
				s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|XML files|*.xml|';
				s.FilterIndex=defext=='txt'?2:'html'?3:'xml'?4:1;
				s.InitialDir=path;
				s.FileName=file;
				if (s.showOpen()) var result=s.FileName;
			}
			catch(e) {  // fallback
				var result=prompt(msg,path+file);
			}
		}
		return result;
	},
	initFilter: function() {
		this.$('exportFilterStart').checked=false; this.$('exportStartDate').value='';
		this.$('exportFilterEnd').checked=false;  this.$('exportEndDate').value='';
		this.$('exportFilterTags').checked=false; this.$('exportTags').value='';
		this.$('exportFilterText').checked=false; this.$('exportText').value='';
		this.showFilterFields();
	},
	showFilterFields: function(which) {
		var show=this.$('exportFilterStart').checked;
		this.$('exportFilterStartBy').style.display=show?'block':'none';
		this.$('exportStartDate').style.display=show?'block':'none';
		var val=this.$('exportFilterStartBy').value;
		this.$('exportStartDate').value
			=this.getFilterDate(val,'exportStartDate').formatString(this.datetimefmt);
		if (which && (which.id=='exportFilterStartBy') && (val=='other'))
			this.$('exportStartDate').focus();

		var show=this.$('exportFilterEnd').checked;
		this.$('exportFilterEndBy').style.display=show?'block':'none';
		this.$('exportEndDate').style.display=show?'block':'none';
		var val=this.$('exportFilterEndBy').value;
		this.$('exportEndDate').value
			=this.getFilterDate(val,'exportEndDate').formatString(this.datetimefmt);
		 if (which && (which.id=='exportFilterEndBy') && (val=='other'))
			this.$('exportEndDate').focus();

		var show=this.$('exportFilterTags').checked;
		this.$('exportTags').style.display=show?'block':'none';

		var show=this.$('exportFilterText').checked;
		this.$('exportText').style.display=show?'block':'none';
	},
	getFilterDate: function(val,id) {
		var result=0;
		switch (val) {
			case 'file':
				result=new Date(document.lastModified);
				break;
			case 'other':
				result=new Date(this.$(id).value);
				break;
			default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
				var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
				var oneday=86400000;
				if (id=='exportStartDate')
					result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
				else
					result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
				break;
		}
		return result;
	},
	filterExportList: function() {
		var theList  = this.$('exportList'); if (!theList) return -1;
		var filterStart=this.$('exportFilterStart').checked;
		var val=this.$('exportFilterStartBy').value;
		var startDate=config.macros.exportTiddlers.getFilterDate(val,'exportStartDate');
		var filterEnd=this.$('exportFilterEnd').checked;
		var val=this.$('exportFilterEndBy').value;
		var endDate=config.macros.exportTiddlers.getFilterDate(val,'exportEndDate');
		var filterTags=this.$('exportFilterTags').checked;
		var tags=this.$('exportTags').value;
		var filterText=this.$('exportFilterText').checked;
		var text=this.$('exportText').value;
		if (!(filterStart||filterEnd||filterTags||filterText)) {
			alert('Please set the selection filter');
			this.$('exportFilterPanel').style.display='block';
			return -1;
		}
		if (filterStart&&filterEnd&&(startDate>endDate)) {
			var msg='starting date/time:\n'
			msg+=startDate.toLocaleString()+'\n';
			msg+='is later than ending date/time:\n'
			msg+=endDate.toLocaleString()
			alert(msg);
			return -1;
		}
		// if filter by tags, get list of matching tiddlers
		// use getMatchingTiddlers() (if MatchTagsPlugin is installed) for full boolean expressions
		// otherwise use getTaggedTiddlers() for simple tag matching
		if (filterTags) {
			var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
			var t=fn.apply(store,[tags]);
			var tagged=[];
			for (var i=0; i<t.length; i++) tagged.push(t[i].title);
		}
		// scan list and select tiddlers that match all applicable criteria
		var total=0;
		var count=0;
		for (var i=0; i<theList.options.length; i++) {
			// get item, skip non-tiddler list items (section headings)
			var opt=theList.options[i]; if (opt.value=='') continue;
			// get tiddler, skip missing tiddlers (this should NOT happen)
			var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
			var sel=true;
			if ( (filterStart && tiddler.modified<startDate)
			|| (filterEnd && tiddler.modified>endDate)
			|| (filterTags && !tagged.contains(tiddler.title))
			|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
				sel=false;
			opt.selected=sel;
			count+=sel?1:0;
			total++;
		}
		return count;
	},
	deleteTiddlers: function() {
		var list=this.$('exportList'); if (!list) return;
		var tids=[];
		for (i=0;i<list.length;i++)
			if (list.options[i].selected && list.options[i].value.length)
				tids.push(list.options[i].value);
		if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
		store.suspendNotifications();
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			var msg="'"+tid.title+"' is tagged with 'systemConfig'.\n\n";
			msg+='Removing this tiddler may cause unexpected results.  Are you sure?'
			if (tid.tags.contains('systemConfig') && !confirm(msg)) continue;
			store.removeTiddler(tid.title);
			story.closeTiddler(tid.title);
		}
		store.resumeNotifications();
		alert(tids.length+' tiddlers deleted');
		this.refreshList(0); // reload listbox
		store.notifyAll(); // update page display
	},
	go: function() {
		if (window.location.protocol!='file:') // make sure we are local
			{ displayMessage(config.messages.notFileUrlError); return; }
		// get selected tidders, target filename, target type, and notes
		var list=this.$('exportList'); if (!list) return;
		var tids=[]; for (var i=0; i<list.options.length; i++) {
			var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
			var tid=store.getTiddler(opt.value); if (!tid) continue;
			tids.push(tid);
		}
		if (!tids.length) return; // no tiddlers selected
		var target=this.$('exportFilename').value.trim();
		if (!target.length) {
			displayMessage('A local target path/filename is required',target);
			return;
		}
		var merge=this.$('exportMerge').checked;
		var filetype=this.$('exportFormat').value.toLowerCase();
		var notes=this.$('exportNotes').value.replace(/\n/g,'<br>');
		var total={val:0};
		var out=this.assembleFile(target,filetype,tids,notes,total,merge);
		if (!total.val) return; // cancelled file overwrite
		var link='file:///'+target.replace(/\\/g,'/');
		var samefile=link==decodeURIComponent(window.location.href);
		var p=getLocalPath(document.location.href);
		if (samefile) {
			if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
			if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
		}
		var ok=saveFile(target,out);
		displayMessage((ok?this.okmsg:this.failmsg).format([total.val,total.val!=1?'s':'',target]),link);
	},
	plainTextHeader:
		 'Source:\n\t%0\n'
		+'Title:\n\t%1\n'
		+'Subtitle:\n\t%2\n'
		+'Created:\n\t%3 by %4\n'
		+'Application:\n\tTiddlyWiki %5 / %6 %7\n\n',
	plainTextTiddler:
		'- - - - - - - - - - - - - - -\n'
		+'|     title: %0\n'
		+'|   created: %1\n'
		+'|  modified: %2\n'
		+'| edited by: %3\n'
		+'|      tags: %4\n'
		+'- - - - - - - - - - - - - - -\n'
		+'%5\n',
	plainTextFooter:
		'',
	newsFeedHeader:
		 '<'+'?xml version="1.0"?'+'>\n'
		+'<rss version="2.0">\n'
		+'<channel>\n'
		+'<title>%1</title>\n'
		+'<link>%0</link>\n'
		+'<description>%2</description>\n'
		+'<language>en-us</language>\n'
		+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
		+'<pubDate>%3</pubDate>\n'
		+'<lastBuildDate>%3</lastBuildDate>\n'
		+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
		+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
	newsFeedTiddler:
		'\n%0\n',
	newsFeedFooter:
		'</channel></rss>',
	pureStoreHeader:
		 '<html><body>'
		+'<style type="text/css">'
		+'	#storeArea {display:block;margin:1em;}'
		+'	#storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
		+'	#pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
		+'</style>'
		+'<div id="pureStoreHeading">'
		+'	TiddlyWiki "PureStore" export file<br>'
		+'	Source'+': <b>%0</b><br>'
		+'	Title: <b>%1</b><br>'
		+'	Subtitle: <b>%2</b><br>'
		+'	Created: <b>%3</b> by <b>%4</b><br>'
		+'	TiddlyWiki %5 / %6 %7<br>'
		+'	Notes:<hr><pre>%8</pre>'
		+'</div>'
		+'<div id="storeArea">',
	pureStoreTiddler:
		'%0\n%1',
	pureStoreFooter:
		'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
	assembleFile: function(target,filetype,tids,notes,total,merge) {
		var revised='';
		var now = new Date().toLocaleString();
		var src=convertUnicodeToUTF8(document.location.href);
		var title = convertUnicodeToUTF8(wikifyPlain('SiteTitle').htmlEncode());
		var subtitle = convertUnicodeToUTF8(wikifyPlain('SiteSubtitle').htmlEncode());
		var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
		var twver = version.major+'.'+version.minor+'.'+version.revision;
		var v=version.extensions.ExportTiddlersPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
		var headerargs=[src,title,subtitle,now,user,twver,'ExportTiddlersPlugin',pver,notes];
		switch (filetype) {
			case this.type_TX: // plain text
				var header=this.plainTextHeader.format(headerargs);
				var footer=this.plainTextFooter;
				break;
			case this.type_CS: // comma-separated
				var fields={};
				for (var i=0; i<tids.length; i++) for (var f in tids[i].fields) fields[f]=f;
				var names=['title','created','modified','modifier','tags','text'];
				for (var f in fields) names.push(f);
				var header=names.join(',')+'\n';
				var footer='';
				break;
			case this.type_NF: // news feed (XML)
				headerargs[0]=store.getTiddlerText('SiteUrl','');
				var header=this.newsFeedHeader.format(headerargs);
				var footer=this.newsFeedFooter;
				break;
			case this.type_PS: // PureStore (no code)
				var header=this.pureStoreHeader.format(headerargs);
				var footer=this.pureStoreFooter;
				break;
			case this.type_TW: // full TiddlyWiki
			default:
				var currPath=getLocalPath(window.location.href);
				var original=loadFile(currPath);
				if (!original) { displayMessage(config.messages.cantSaveError); return; }
				var posDiv = locateStoreArea(original);
				if (!posDiv) { displayMessage(config.messages.invalidFileError.format([currPath])); return; }
				var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
				var footer = '\n'+original.substr(posDiv[1]);
				break;
		}
		var out=this.getData(target,filetype,tids,fields,merge);
		var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
		// if full TW, insert page title and language attr, and reset all MARKUP blocks...
		if (filetype==this.type_TW) {
			var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
			revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
			revised=updateLanguageAttribute(revised);
			var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
			revised=updateMarkupBlock(revised,'PRE-HEAD',
				titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
			revised=updateMarkupBlock(revised,'POST-HEAD',
				titles.contains('MarkupPostHead')?'MarkupPostHead':null);
			revised=updateMarkupBlock(revised,'PRE-BODY',
				titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
			revised=updateMarkupBlock(revised,'POST-SCRIPT',
				titles.contains('MarkupPostBody')?'MarkupPostBody':null);
		}
		total.val=out.length;
		return revised;
	},
	getData: function(target,filetype,tids,fields,merge) {
		// output selected tiddlers and gather list of titles (for use with merge)
		var out=[]; var titles=[];
		var url=store.getTiddlerText('SiteUrl','');
		for (var i=0; i<tids.length; i++) {
			out.push(this.formatItem(store,filetype,tids[i],url,fields));
			titles.push(tids[i].title);
		}
		// if TW or PureStore format, ask to merge with existing tiddlers (if any)
		if (filetype==this.type_TW || filetype==this.type_PS) {
			var txt=loadFile(target);
			if (txt && txt.length) {
				var remoteStore=new TiddlyWiki();
				if (version.major+version.minor*.1+version.revision*.01<2.52) txt=convertUTF8ToUnicode(txt);
				if (remoteStore.importTiddlyWiki(txt)) {
					var existing=remoteStore.getTiddlers('title');
					var msg=this.overwriteprompt.format([target,existing.length,existing.length!=1?'s':'']);
					if (merge) {
						var added=titles.length; var updated=0; var kept=0;
						for (var i=0; i<existing.length; i++)
							if (titles.contains(existing[i].title)) {
								added--; updated++;
							} else {
								out.push(this.formatItem(remoteStore,filetype,existing[i],url));
								kept++;
							}
						displayMessage(this.mergestatus.format(
							[added,added!=1?'s':'',updated,updated!=1?'s':'',kept,kept!=1?'s':'',]));
					}
					else if (!confirm(msg)) out=[]; // empty the list = don't write file
				}
			}
		}
		return out;
	},
	formatItem: function(s,f,t,u,fields) {
		if (f==this.type_TW)
			var r=s.getSaver().externalizeTiddler(s,t);
		if (f==this.type_PS)
			var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
		if (f==this.type_NF)
			var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
		if (f==this.type_TX)
			var r=this.plainTextTiddler.format([t.title, t.created.toLocaleString(), t.modified.toLocaleString(),
				t.modifier, String.encodeTiddlyLinkList(t.tags), t.text]);
		if (f==this.type_CS) {
			function toCSV(t) { return '"'+t.replace(/"/g,'""')+'"'; } // always encode CSV
			var out=[ toCSV(t.title), toCSV(t.created.toLocaleString()), toCSV(t.modified.toLocaleString()),
				toCSV(t.modifier), toCSV(String.encodeTiddlyLinkList(t.tags)), toCSV(t.text) ];
			for (var f in fields) out.push(toCSV(t.fields[f]||''));
			var r=out.join(',');
		}
		return r||"";
	}
}
//}}}
/***
!!!Control panel CSS
//{{{
!css
#exportPanel {
	display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;
	background-color: #eee; color:#000; font-size: 8pt; line-height:110%;
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;
	padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em;
}
#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }
#exportPanel table {
	width:100%; border:0px; padding:0px; margin:0px;
	font-size:8pt; line-height:110%; background:transparent;
}
#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }
#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }
#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}
#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%; }
#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }
#exportPanel .box {
	border:1px solid black; padding:3px; margin-bottom:5px;
	background:#f8f8f8; -moz-border-radius:5px;-webkit-border-radius:5px; }
#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }
#exportPanel .rad { width:auto;border:0 }
#exportPanel .chk { width:auto;border:0 }
#exportPanel .btn { width:auto; }
#exportPanel .btn1 { width:98%; }
#exportPanel .btn2 { width:48%; }
#exportPanel .btn3 { width:32%; }
#exportPanel .btn4 { width:24%; }
#exportPanel .btn5 { width:19%; }
!end
//}}}
!!!Control panel HTML
//{{{
!html
<!-- target path/file  -->
<div>
<div style="float:right;padding-right:.5em">
<input type="checkbox" style="width:auto" id="exportMerge" CHECKED
	title="combine selected tiddlers with existing tiddlers (if any) in export file"> merge
</div>
export to:<br>
<input type="text" id="exportFilename" size=40 style="width:93%"><input 
	type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" 
	onclick="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">
</div>

<!-- output format -->
<div>
format:
<select id="exportFormat" size=1>
	<option value="TW">TiddlyWiki HTML document (includes core code)</option>
	<option value="PS">TiddlyWiki "PureStore" HTML file (tiddler data only)</option>
	<option value="TX">TiddlyWiki plain text TXT file (tiddler source listing)</option>
	<option value="CS">Comma-Separated Value (CSV) data file</option>
	<option value="NF">RSS NewsFeed XML file</option>
</select>
</div>

<!-- notes -->
<div>
notes:<br>
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> 
</div>

<!-- list of tiddlers -->
<table><tr align="left"><td>
	select:
	<a href="JavaScript:;" id="exportSelectAll"
		onclick="return config.macros.exportTiddlers.process(this)" title="select all tiddlers">
		&nbsp;all&nbsp;</a>
	<a href="JavaScript:;" id="exportSelectChanges"
		onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">
		&nbsp;changes&nbsp;</a>
	<a href="JavaScript:;" id="exportSelectOpened"
		onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">
		&nbsp;opened&nbsp;</a>
	<a href="JavaScript:;" id="exportSelectRelated"
		onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">
		&nbsp;related&nbsp;</a>
	<a href="JavaScript:;" id="exportToggleFilter"
		onclick="return config.macros.exportTiddlers.process(this)" title="show/hide selection filter">
		&nbsp;filter&nbsp;</a>
</td><td align="right">
	<a href="JavaScript:;" id="exportListSmaller"
		onclick="return config.macros.exportTiddlers.process(this)" title="reduce list size">
		&nbsp;&#150;&nbsp;</a>
	<a href="JavaScript:;" id="exportListLarger"
		onclick="return config.macros.exportTiddlers.process(this)" title="increase list size">
		&nbsp;+&nbsp;</a>
</td></tr></table>
<select id="exportList" multiple size="10" style="margin-bottom:5px;"
	onchange="config.macros.exportTiddlers.refreshList(this.selectedIndex)">
</select><br>

<!-- selection filter -->
<div id="exportFilterPanel" style="display:none">
<table><tr align="left"><td>
	selection filter
</td><td align="right">
	<a href="JavaScript:;" id="exportHideFilter"
		onclick="return config.macros.exportTiddlers.process(this)" title="hide selection filter">hide</a>
</td></tr></table>
<div class="box">

<input type="checkbox" class="chk" id="exportFilterStart" value="1"
	onclick="config.macros.exportTiddlers.showFilterFields(this)"> starting date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
	<select size=1 id="exportFilterStartBy"
		onchange="config.macros.exportTiddlers.showFilterFields(this);">
		<option value="0">today</option>
		<option value="1">yesterday</option>
		<option value="7">a week ago</option>
		<option value="30">a month ago</option>
		<option value="file">file date</option>
		<option value="other">other (mm/dd/yyyy hh:mm)</option>
	</select>
</td><td width="50%">
	<input type="text" id="exportStartDate" onfocus="this.select()"
		onchange="config.macros.exportTiddlers.$('exportFilterStartBy').value='other';">
</td></tr></table>

<input type="checkbox" class="chk" id="exportFilterEnd" value="1"
	onclick="config.macros.exportTiddlers.showFilterFields(this)"> ending date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
	<select size=1 id="exportFilterEndBy"
		onchange="config.macros.exportTiddlers.showFilterFields(this);">
		<option value="0">today</option>
		<option value="1">yesterday</option>
		<option value="7">a week ago</option>
		<option value="30">a month ago</option>
		<option value="file">file date</option>
		<option value="other">other (mm/dd/yyyy hh:mm)</option>
	</select>
</td><td width="50%">
	<input type="text" id="exportEndDate" onfocus="this.select()"
		onchange="config.macros.exportTiddlers.$('exportFilterEndBy').value='other';">
</td></tr></table>

<input type="checkbox" class="chk" id=exportFilterTags value="1"
	onclick="config.macros.exportTiddlers.showFilterFields(this)"> match tags<br>
<input type="text" id="exportTags" onfocus="this.select()">

<input type="checkbox" class="chk" id=exportFilterText value="1"
	onclick="config.macros.exportTiddlers.showFilterFields(this)"> match titles/tiddler text<br>
<input type="text" id="exportText" onfocus="this.select()">

</div> <!--box-->
</div> <!--panel-->

<!-- action buttons -->
<div style="text-align:center">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
	id="exportFilter" value="apply filter">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
	id="exportStart" value="export tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
	id="exportDelete" value="delete tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
	id="exportClose" value="close">
</div><!--center-->
!end
//}}}
***/
 
/***
|Name|ExportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|Documentation for ExportTiddlersPlugin|
interactively select and extract tiddlers from your ~TiddlyWiki document, and write them into another file, using one of several different file formats:
* ~TiddlyWiki - a complete, stand-alone, standard TiddlyWiki HTML document
* ~PureStore - a small HTML archive file containing tiddler data only (no core code)
* ~PlainText - a simple TXT text file with tiddler source listings
* Comma - a "Comma Separated Value" data/spreadsheet file
* ~NewsFeed  - an XML-format file that can be published for RSS syndication.
!!!!!Usage
<<<
{{{
<<exportTiddlers>> (sidebar menu item)
<<exportTiddlers inline>> (embedded control panel)
}}}

Inline control panel (live):
<<exportTiddlers inline>>

Optional "special tiddlers" used by this plugin:
* SiteUrl<br>URL for official server-published version of document being viewed (used in XML export). Default: //none//
<<<
!!!!!Revisions
<<<
2010.02.25 2.9.5 added merge checkbox option and improved 'merge' status message
2009.09.12 2.9.4 fixed 'return false' to prevent IE page transitions
2009.07.06 2.9.3 moved HTML to section for size reduction
2009.07.03 2.9.2 TW252 fixup: don't call convertUTF8ToUnicode() for local loadFile() I/O
2009.04.30 2.9.1 custom fields in CSV output
2009.04.19 2.9.0 added CSV format
2009.02.26 2.8.5 use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
2008.09.29 2.8.4 in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
2008.09.26 2.8.3 in go(), if rewriting *current* file and chkSaveBackups and/or chkGenerateAnRssFeed is enabled, then write a backup file or RSS feed, respectively.
2008.09.24 2.8.2 in assembleFile(), make sure that markup block is updated if corresponding Markup* tiddler is exported.
2008.09.19 2.8.1 in formatItem(), removed unnecessary convertUnicodeToUTF8() (was causing double-conversion!)
2008.09.11 2.8.0 extensive code cleanup: moved all global functions inside macro object. Re-wrote file generator and I/O to support TiddlyWiki, PlainText, PureStore, and NewsFeed file formats.  Replaced inline 'match tags' code with use of getMatchingTiddlers() from [[MatchTagsPlugin]] (if installed), with fallback to core getTaggedTiddlers() otherwise.
2008.05.27 2.7.0 added ability to 'merge' with existing export file.  Also, revised 'matchTags' functionality to be more robust and more efficient
2008.05.12 2.6.1 automatically add 'export' task to backstage (moved from BackstageTweaks)
2008.03.10 2.6.0 added "delete tiddlers" button
2007.12.04 *.*.* update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.11.10 2.5.1 removed debugging alert messages from promptForExportFilename()
2007.10.31 2.5.0 code reduction: removed incomplete/unused interface and supporting functions for exporting directly to http, https or ftp servers.  Plugin now supports exporting to local file only.  Also, updated TW document output to generate TW2.2 compatible file format.
2007.10.30 2.4.2 added automatic shadow tiddler definition for [[ExportTiddlers]]
2007.07.16 2.4.1 in exportTWHeader(), reset HTML source 'markup' so installed markup is NOT copied to new file.
2007.06.30 2.4.0 added "select related tiddlers" feature.  Recursively scans the tiddler links[] info to find all tiddlers referenced by any of the currently selected tiddler, and then selects them all (including the original tiddlers).
2007.04.19 2.3.0 in exportData(), pass SiteURL value as param to saveToRss().  Fixes 'undefined' appearing in tiddler link in XML output.  Also, in refreshExportList(), added 'sort by tags'.  Also, added 'group select'... selecting a heading (date,author,tag) auto-selects all tiddlers in that group.
2007.03.02 2.2.6 in onClickExportButton(), when selecting open tiddlers for TW2.2, look for "storyDisplay" with fallback to "tiddlerDisplay" for TW2.1 or earlier
2007.03.01 2.2.5 removed hijack of store.saveChanges()
2006.11.08 2.2.4 added promptForExportFilename() and replaced type="file" control with edit field + browse button ("...").
2006.10.12 2.2.3 in exportDIVFooter(), write POST-BODY-START/END markers for compatibility with TW2.1 core file format.
2006.05.11 2.2.2 in createExportPanel, removed call to addNotification() to reduce unneeded feedback messages and increase overall document performance.
2006.05.02 2.2.1 Use displayMessage() to show number of selected tiddlers instead of updating listbox 'header' item after each selection.  Prevents awkward 'scroll-to-top' behavior that made multi-select via ctrl-click nearly impossible.
2006.04.29 2.2.0 New features: free-form "Notes" text inserted in the header of PureStore files.
2006.03.29 2.1.3 added calls to convertUnicodeToUTF8() for generated output, so it better handles international characters.
2006.02.12 2.1.2 more FF1501 bug fixes.
2006.02.04 2.1.1 added var to unintended globals to avoids FireFox1501 crash bug
2006.02.02 2.1.0 Added support for output of complete TiddlyWiki documents
2006.01.21 2.0.1 Defer initial panel creation and only register a notification function when panel first is created
in saveChanges 'hijack', create panel as needed.  Note: if window.event is not available to identify the click location, the export panel is positioned relative to the 'tiddlerDisplay' element of the TW document.
2005.12.27 2.0.0 Update for TW2.0.
2005.12.24 0.9.5 Minor adjustments to CSS to force correct link colors regardless of TW stylesheet selection
2005.12.16 0.9.4 Dynamically create/remove exportPanel so only one instance exists at a time
2005.11.15 0.9.2 added non-Ajax post to bypass cross-domain security restrictions.
2005.11.08 0.9.1 moved HTML, CSS and control initialization into exportInit() function and call from macro handler instead of at load time.
2005.10.28 0.9.0 added 'select opened tiddlers' feature. Based on a suggestion by Geoff Slocock
2005.10.24 0.8.3 Corrected hijack of 'save changes' when using http:
2005.10.18 0.8.2 added AJAX functions
2005.10.18 0.8.1 Corrected timezone handling and error checking/reporting when filtering tiddlers. More style tweaks, minor text changes and some assorted layout cleanup.
2005.10.17 0.8.0 First pre-release.
2005.10.16 0.7.0 filter by tags
2005.10.15 0.6.0 filter by title/text
2005.10.14 0.5.0 export to local file (DIV or XML)
2005.10.14 0.4.0 filter by start/end date
2005.10.13 0.3.0 panel interaction
2005.10.11 0.2.0 panel layout
2005.10.10 0.1.0 code framework
2005.10.09 0.0.0 development started
<<<
/%
|Description|Saving changes for online documents if the network goes down|
%/
{{small{
__Saving changes to online documents if your network connection goes down while editing__

If you have been editing a document online (e.g., using an account on http://www.TiddlySpot.com with [[UploadPlugin]]), and your internet connection has gone down while editing, it is not possible to save your changes in the usual manner because, without the internet, the remotely-stored document is //inaccessible//.

Unfortunately, you also cannot save the document locally because of security restrictions that prevent access to your local filesystem when working with a server-hosted document (i.e., viewed via http:).

Fortunately, there is a ''manual work-around that will let you 'rescue' TiddlyWiki's internal //storeArea// for the current document, including your unsaved changes to tiddler content'' by using the following command link:

{{big center{<<tiddler RescueStoreAreaCommand with: "rescue storeArea">>}}}
When clicked, this link ''opens a new window and writes a copy of the storeArea into that window.''  The content in that window is displayed as plain-text, and includes //only the storeArea DIVs that define the tiddlers, without any of the surrounding TiddlyWiki core code.//  To preserve this storeArea, ''select and copy/paste the displayed content into a local text file for safe-keeping.''

Then, to merge this 'rescued store area' with the rest of the TW core, use a plain-text editor (not the browser) to open a ''copy'' of any locally-stored TW document.  If a locally-stored TiddlyWiki document is not available, you will have to wait until your network connection has been re-established, so that you can download your TiddlyWiki document from the server, or [[obtain an empty TiddlyWiki document from http://www.TiddlyWiki.com|http://www.TiddlyWiki.com/empty.html]].

Then, find the 'storeArea' in that document, which looks like this:
{{{
<!--POST-SHADOWAREA-->
<div id="storeArea">
.... *** replace this part *** ...
</div>
<!--POST-STOREAREA-->
}}}
Select everything //inside the storeArea DIV//, and replace it with the rescued store area content, and then save the file.  If all goes well, the saved file can then be opened in your browser as a complete TW document, *with* all the saved content in place!

Note: The command link shown above may also be installed directly into your browser as an [[InstantBookmarklet|InstantBookmarklets]]. To create a bookmarklet, simply ''//drag-and-drop the command link directly onto your browser's toolbar//'' or right-click and use 'bookmark this link' (or 'add to favorites') to add the bookmarklet to your browser's bookmarks menu.  Once installed, you can use this command with //any// TiddlyWiki document, even when [[RescueStoreAreaCommand]] and [[InlineJavascriptPlugin]] have not been installed in that document!
}}}
A TiddlyWiki is a single html file that acts like a wiki.
----
TiddlyWiki is driven by javascript and css.
----
TiddlyWiki is cross platform and runs in:
* ~FireFox
* Internet Explorer
* Chrome
* Safari
----
TiddlyWiki was written by Jeremy Ruston, and is supported by British Telecom
----
The basic unit of content in a TiddlyWiki is the tiddler which plays the role of a web page in other wiki's.
----
A tiddler (the basic unit of content in a tiddlywiki) is a form of microcontent.
----
There are many macros for TiddlyWiki that allows reuse of content in different tiddlers.
----
TiddlyWiki is published by UnaMesa – a non-profit association – under a BSD  open source license and is thus freely available.
----
//J. Ruston//
<<<
A TiddlyWiki is like a blog because it's divided up into neat little chunks (tiddlers), but it encourages you to read it by hyperlinking  rather than sequentially: if you like, a non-linear blog analogue that binds the individual microcontent  items into a cohesive whole. I think that TiddlyWiki represents a novel medium for writing, and will promote its own distinctive writing style.
<<<
----
TiddlyWiki can also be used as a personal productivity tool using the methods in David Allen's book //Getting Things Done//.
----
TiddlyWiki has a number of verticals: adaptations for a specific purpose including:
* twab - address book
* multiple //Getting Things Done// implementations
* genealogy tool
* database
----
TiddlyWiki has an extensive tagging system including TagglyTagging that allows structured relationships between tiddlers.
----
There are hundreds of plugins that enhance:
* searching
* tag manipulation
* formatting
* and much more ...


/***
|''Name:''|FieldsEditorPlugin|
|''Description:''|//create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.|
|''Version:''|1.0.2|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.2.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demo:
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], see [[FieldEditor example]]
!Installation:
*import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
*save and reload
*optionnaly : add the following css text in your StyleSheet : {{{#popup tr.fieldTableRow td {padding:1px 3px 1px 3px;}}}}
!Code
***/

//{{{

config.commands.fields.handlePopup = function(popup,title) {
	var tiddler = store.fetchTiddler(title);
	if(!tiddler)
		return;
	var fields = {};
	store.forEachField(tiddler,function(tiddler,fieldName,value) {fields[fieldName] = value;},true);
	var items = [];
	for(var t in fields) {
		var editCommand = "<<untiddledCall editFieldDialog "+escape(title)+" "+escape(t)+">>";
		var deleteCommand = "<<untiddledCall deleteField "+escape(title)+" "+escape(t)+">>";
		var renameCommand = "<<untiddledCall renameField "+escape(title)+" "+escape(t)+">>";
		items.push({field: t,value: fields[t], actions: editCommand+renameCommand+deleteCommand});
	}
	items.sort(function(a,b) {return a.field < b.field ? -1 : (a.field == b.field ? 0 : +1);});
	var createNewCommand = "<<untiddledCall createField "+escape(title)+">>";
	items.push({field : "", value : "", actions:createNewCommand });
	if(items.length > 0)
		ListView.create(popup,items,this.listViewTemplate);
	else
		createTiddlyElement(popup,"div",null,null,this.emptyText);
}

config.commands.fields.listViewTemplate = {
	columns: [
		{name: 'Field', field: 'field', title: "Field", type: 'String'},
		{name: 'Actions', field: 'actions', title: "Actions", type: 'WikiText'},
		{name: 'Value', field: 'value', title: "Value", type: 'WikiText'}
	],
	rowClasses: [
			{className: 'fieldTableRow', field: 'actions'}
	],
	buttons: [	//can't use button for selected then delete, because click on checkbox will hide the popup
	]
}

config.macros.untiddledCall = {  // when called from listview, tiddler is unset, so we need to pass tiddler as parameter
	handler : function(place,macroName,params,wikifier,paramString) {
		var macroName = params.shift();
		if (macroName) var macro = config.macros[macroName];
		var title = params.shift();
		if (title) var tiddler = store.getTiddler(unescape(title));
		if (macro) macro.handler(place,macroName,params,wikifier,paramString,tiddler);		
	}
}

config.macros.deleteField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"delete", "delete "+fieldName,this.onClickDeleteField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickDeleteField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName && confirm("delete field " + fieldName+" from " + title +" tiddler ?")) {
			delete tiddler.fields[fieldName];
			store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
			story.refreshTiddler(title,"ViewTemplate",true);
		}
		return false;
	}
}

config.macros.createField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly) {
			var btn = createTiddlyButton(place,"create new", "create a new field",this.onClickCreateField);
			btn.setAttribute("title",tiddler.title);
		}
	},
	onClickCreateField : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		if (tiddler) {
			var fieldName = prompt("Field name","");
			if (store.getValue(tiddler,fieldName)) {
				window.alert("This field already exists.");
			}
			else if (fieldName) {
				var v = prompt("Field value","");
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.editFieldDialog = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"edit", "edit this field",this.onClickEditFieldDialog);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickEditFieldDialog : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		var fieldName=this.getAttribute("fieldName");
		if (tiddler && fieldName) {
			var value = tiddler.fields[fieldName];
			value = value ? value : "";
			var lines = value.match(/\n/mg);
			lines = lines ? true : false;
			if (!lines || confirm("This field contains more than one line. Only the first line will be kept if you edit it here. Proceed ?")) {
				var v = prompt("Field value",value);
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.renameField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"rename", "rename "+fieldName,this.onClickRenameField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickRenameField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName) {
			var newName = prompt("Rename " + fieldName + " as ?", fieldName);
			if (newName) {
				tiddler.fields[newName]=tiddler.fields[fieldName];
				delete tiddler.fields[fieldName];
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.shadowTiddlers.StyleSheetFieldsEditor = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow td {padding : 1px 3px}\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow .button {border:0; padding : 0 0.2em}\n";
config.shadowTiddlers.StyleSheetFieldsEditor +="/*}}}*/";
store.addNotification("StyleSheetFieldsEditor", refreshStyles);

//}}}
/***
|Name|FileDropPlugin|
|Source|http://www.TiddlyTools.com/#FileDropPlugin|
|Version|2.1.4|
|Author|BradleyMeck and Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|drag-and-drop files/directories to create tiddlers|
''requires FireFox or another Mozilla-compatible browser.''
!!!!!Usage
<<<
This plugin automatically creates tiddlers from files that are dropped onto an open TiddlyWiki document.  You can drop multiple selected files and/or folders to create many tiddlers at once.  New tiddler titles are created using the filename of each dropped file (i.e., omitting the path).  If a title is already in use, you are prompted to enter a new title for that file.  If you drop a folder, you will be asked if you want to create a simple 'directory list' of files in a single tiddler or create one tiddler for each file in that folder.  

By default, it is assumed that all dropped files contain text.  However, if [[AttachFilePlugin]], [[AttachFilePluginFormatters]] and [[AttachFileMIMETypes]] are installed, then you can drop ''//binary data files//'' as well as text files.  If the MIME type of a dropped file is not "text/plain", then AttachFilePlugin is used to create an 'attachment' tiddler, rather than creating a simple text tiddler.

When creating text tiddlers, you can embed a //link// to the original external file at the top of the new tiddler, in addition to (or instead of) the text content itself.  The format for this link (see Configuration, below) uses embedded ''//replacement markers//'' that allow you to generate a variety of wiki-formatted output, where:
*%0 = filename (without path)
*%1 = local """file://...""" URL
*%2 = local path and filename (OS-native format)
*%3 = relative path (if subdirectory of current document directory)
*%4 = file size
*%5 = file date
*%6 = current date
*%7 = current ~TiddlyWiki username
*\n = newline
By default, the link format uses the filename (%0) and local URL (%1), enclosed within a //hidden section// syntax, like this:
{{{
/%
!link
[[%0|%1]]
!end
%/
}}}
This permits the link to be embedded along with the text content, without changing the appearance of that content when the tiddler is viewed.  To display the link in your tiddler content, use:
{{{
<<tiddler TiddlerName##link>>
}}}
<<<
!!!!!Configuration
<<<
__FileDropPlugin options:__
<<option chkFileDropContent>>Copy file content into tiddlers if smaller than: <<option txtFileDropDataLimit>> bytes
&nbsp; //(note: excess text content will be truncated, oversized binary files will skipped, 0=no limit)//
<<option chkFileDropLink>>Generate external links to files, using this format:{{editor{<html><nowiki><textarea rows="4" onchange="
config.macros.option.propagateOption('txtFileDropLinkFormat','value',this.value.escapeLineBreaks(),'input');
"></textarea></html><<tiddler {{
	var ta=place.lastChild.getElementsByTagName('textarea')[0];
	var v=config.options.txtFileDropLinkFormat.unescapeLineBreaks();
	ta.value=v;
"";}}>>}}}<<option chkFileDropTrimFilename>>Omit file extensions from tiddler titles
<<option chkFileDropDisplay>>Automatically display newly created tiddlers
Tag newly created tiddlers with: <<option txtFileDropTags>>

__FileDropPlugin+AttachFilePlugin options:__ //(binary file data as encoded 'base64' text)//
<<option chkFileDropAttachLocalLink>> attachment includes reference to local path/filename
>Note: if the plugin does not seem to work, enter ''about:config'' in the Firefox address bar, and make sure that {{{signed.applets.codebase_principal_support}}} is set to ''true''
<<<
!!!!!Examples (custom handler functions)
<<<
Adds a single file with confirmation and prompting for title:
{{{
config.macros.fileDrop.addEventListener('application/x-moz-file',
	function(nsiFile) {
		var msg='You have dropped the file:\n'
			+nsiFile.path+'\n'
			+'onto the page, it will be imported as a tiddler. Is that ok?'
		if(confirm(msg)) {
			var newDate = new Date();
			var title = prompt('what would you like to name the tiddler?');
			store.saveTiddler(title,title,loadFile(nsiFile.path),config.options.txtUserName,newDate,[]);
		}
		return true;
	});
}}}
Adds a single file without confirmation, using path/filename as tiddler title:
{{{
config.macros.fileDrop.addEventListener('application/x-moz-file',
	function(nsiFile) {
		var newDate = new Date();
		store.saveTiddler(nsiFile.path,nsiFile.path,loadFile(nsiFile.path),config.options.txtUserName,newDate,[]);
		story.displayTiddler(null,nsiFile.path)
		return true;
	});
}}}
<<<
!!!!!Revisions
<<<
2010.03.06 2.1.4 added event listener for 'dragover' (for FireFox 3.6+)
2009.10.10 2.1.3 fixed IE code error
2009.10.08 2.1.2 fixed chkFileDropContent bypass handling for binary attachments
2009.10.07 2.1.0 added chkFileDropContent and chkFileDropLink/txtFileDropLinkFormat
2009.08.19 2.0.0 fixed event listener registration for FireFox 3.5+.  Also, merged with FileDropPluginConfig, with code cleanup/reduction
2008.08.11 1.5.1 added chkFileDropAttachLocalLink option to allow suppression of local path/file link
2007.xx.xx *.*.* add suspend/resume of notifications to improve performance when multiple files are handled
2007.01.01 0.9.9 extensions for AttachFilePlugin
2006.11.04 0.1.1 initial release by Bradley Meck
<<<
!!!!!Code
***/
//{{{
version.extensions.FileDropPlugin={major:2, minor:1, revision:4, date: new Date(2010,3,6)};

config.macros.fileDrop = {
	customDropHandlers: [],
	addEventListener: function(paramflavor,func,inFront) {
		var obj={}; obj.flavor=paramflavor; obj.handler=func;
		if (!inFront) this.customDropHandlers.push(obj);
		else this.customDropHandlers.shift(obj);
	},
	dragDropHandler: function(evt) {
		netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		var dragService = Components.classes['@mozilla.org/widget/dragservice;1'].getService(Components.interfaces.nsIDragService);
		var dragSession = dragService.getCurrentSession();
		var transferObject = Components.classes['@mozilla.org/widget/transferable;1'].createInstance();
		transferObject = transferObject.QueryInterface(Components.interfaces.nsITransferable);
		transferObject.addDataFlavor('application/x-moz-file');
		var numItems = dragSession.numDropItems;
		if (numItems>1) {
			clearMessage();
			displayMessage('Reading '+numItems+' files...');
			store.suspendNotifications();
		}
		for (var i = 0; i < numItems; i++) {
			dragSession.getData(transferObject, i);
			var dataObj = {};
			var dropSizeObj = {};
			for(var ind=0; ind<config.macros.fileDrop.customDropHandlers.length; ind++) {
				var item = config.macros.fileDrop.customDropHandlers[ind];
				if(dragSession.isDataFlavorSupported(item.flavor)) {
					transferObject.getTransferData(item.flavor, dataObj, dropSizeObj);
					var droppedFile = dataObj.value.QueryInterface(Components.interfaces.nsIFile);
					var result = item.handler.call(item,droppedFile);
					evt.stopPropagation();
					evt.preventDefault();
					if (result) break;
				}
			}
		}
		if (numItems>1) {
			store.resumeNotifications();
			store.notifyAll();
			displayMessage(numItems+' files have been processed');
		}
	}
}
//}}}
/***
!!!!!window event handlers
***/
//{{{
if(!window.event) {
	window.addEventListener('dragdrop',	// FireFox3.1-
		config.macros.fileDrop.dragDropHandler, true);
	window.addEventListener('drop',		// FireFox3.5+
		config.macros.fileDrop.dragDropHandler, true);
	window.addEventListener('dragover',	// FireFox3.6+
		function(e){e.stopPropagation();e.preventDefault();}, true); 
}
//}}}
/***
!!!!!handler for files, directories and binary attachments (see [[AttachFilePlugin]])
***/
//{{{
var defaults={
	chkFileDropDisplay:		true,
	chkFileDropTrimFilename:	false,
	chkFileDropContent:		true,
	chkFileDropLink:		true,
	txtFileDropLinkFormat:		'/%\\n!link\\n[[%0|%1]]\\n!end\\n%/',
	txtFileDropDataLimit:		'32768',
	chkFileDropAttachLocalLink:	true,
	txtFileDropTags:		''
};
for (var id in defaults) if (config.options[id]===undefined)
	config.options[id]=defaults[id];

config.macros.fileDrop.addEventListener('application/x-moz-file',function(nsiFile) {
	var co=config.options; // abbrev
	var header='Index of %0\n^^(as of %1)^^\n|!filename| !size | !modified |\n';
	var item='|[[%0|%1]]| %2|%3|\n';
	var footer='Total of %0 bytes in %1 files\n';
	var now=new Date();
	var files=[nsiFile];
	if (nsiFile.isDirectory()) {
		var folder=nsiFile.directoryEntries;
		var files=[];
		while (folder.hasMoreElements()) {
			var f=folder.getNext().QueryInterface(Components.interfaces.nsILocalFile);
			if (f instanceof Components.interfaces.nsILocalFile && !f.isDirectory()) files.push(f);
		}
		var msg=nsiFile.path.replace(/\\/g,'/')+'\n\n';
		msg+='contains '+files.length+' files... ';
		msg+='select OK to attach all files or CANCEL to create a list...';
		if (!confirm(msg)) { // create a list in a tiddler
			var title=nsiFile.leafName; // tiddler name is last directory name in path
			while (title && title.length && store.tiddlerExists(title)) {
				if (confirm(config.messages.overwriteWarning.format([title]))) break;
				title=prompt('Enter a new tiddler title',nsiFile.path.replace(/\\/g,'/'));
			}
			if (!title || !title.length) return true; // cancelled
			var text=header.format([nsiFile.path.replace(/\\/g,'/'),now.toLocaleString()]);
			var total=0;
			for (var i=0; i<files.length; i++) { var f=files[i];
				var name=f.leafName;
				if (co.chkFileDropTrimFilename)
					{ var p=name.split('.'); if (p.length>1) p.pop(); name=p.join('.'); }
				var path='file:///'+f.path.replace(/\\/g,'/');
				var size=f.fileSize; total+=size;
				var when=new Date(f.lastModifiedTime).formatString('YYYY.0MM.0DD 0hh:0mm:0ss');
				text+=item.format([name,path,size,when]);
			}
			text+=footer.format([total,files.length]);
			var newtags=co.txtFileDropTags?co.txtFileDropTags.readBracketedList():[];
			store.saveTiddler(null,title,text,co.txtUserName,now,newtags);
			if (co.chkFileDropDisplay) story.displayTiddler(null,title);
			return true;
		}
	}
	if (files.length>1) store.suspendNotifications();
	for (i=0; i<files.length; i++) {
		var file=files[i];
		if (file.isDirectory()) continue; // skip over nested directories
		var type='text/plain';
		var title=file.leafName; // tiddler name is file name
		if (co.chkFileDropTrimFilename)
			{ var p=title.split('.'); if (p.length>1) p.pop(); title=p.join('.'); }
		var name=file.leafName;
		var path=file.path;
		var url='file:///'+path.replace(/\\/g,'/');
		var size=file.fileSize;
		var when=new Date(file.lastModifiedTime);
		var now=new Date();
		var who=config.options.txtUserName;
		var h=document.location.href;
		var cwd=getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf('/')+1)));
		var relpath=path.startsWith(cwd)?'./'+path.substr(cwd.length):path;
		while (title && title.length && store.tiddlerExists(title)) {
			if (confirm(config.messages.overwriteWarning.format([title]))) break;
			title=prompt('Enter a new tiddler title',path.replace(/\\/g,'/'));
		}
		if (!title || !title.length) continue; // cancelled
		if (config.macros.attach) {
			type=config.macros.attach.getMIMEType(name,'');
			if (!type.length)
				type=prompt('Unknown file type.  Enter a MIME type','text/plain');
			if (!type||!type.length) continue; // cancelled
		}
		var newtags=co.txtFileDropTags?co.txtFileDropTags.readBracketedList():[];
		if (type=='text/plain' || !co.chkFileDropContent) {
			var txt=''; var fmt=co.txtFileDropLinkFormat.unescapeLineBreaks();
			if (co.chkFileDropLink) txt+=fmt.format([name,url,path,relpath,size,when,now,who]);
			if (co.chkFileDropContent) {
				var out=loadFile(path); var lim=co.txtFileDropDataLimit;
				txt+=co.txtFileDropDataLimit?out.substr(0,lim):out;
				if (size>lim) txt+='\n----\nfilesize ('+size+')'
					+' is larger than FileDrop limit ('+lim+')...\n'
					+'additional content has been omitted';
			}
			store.saveTiddler(null,title,txt,co.txtUserName,now,newtags);
		} else {
			var embed=co.chkFileDropContent
				&& (!co.txtFileDropDataLimit||size<co.txtFileDropDataLimit);
			newtags.push('attachment'); newtags.push('excludeMissing');
			config.macros.attach.createAttachmentTiddler(path,
				now.formatString(config.macros.timeline.dateFormat),
				'attached by FileDropPlugin', newtags, title,
				embed, co.chkFileDropAttachLocalLink, false,
				relpath, '', type,!co.chkFileDropDisplay);
		}
		if (co.chkFileDropDisplay) story.displayTiddler(null,title);
	}
	if (files.length>1) { store.resumeNotifications(); store.notifyAll(); }
	return true;
})
//}}}
/***
|Name|FileDropPluginConfig|
|Source|http://www.TiddlyTools.com/#FileDropPluginConfig|
|Version|1.5.1|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|FileDropPlugin, AttachFilePlugin|
|Overrides||
|Options|##Configuration|
|Description|Adds drag-and-drop handlers for creating binary attachments or directory lists|

__TiddlyTools FileDrop+AttachFile extended handler:__
* use just filename instead of whole path as tiddler title
* check for existing tiddler and prompt for new name
* handle folder drops (drops each file or creates a file list in a tiddler)
* use AttachFilePlugin if MIME type is not text/plain
* autotag created tiddlers (e.g., "temporary", "dropped", etc.)
* option to suppress automatic display of newly created tiddlers
* suspend/resume notifications when handling multiple files (performance improvement)
!!!!!Configuration
<<<
<<option chkFileDropTrimFilename>> Omit file extensions from tiddler titles when creating new tiddlers
&nbsp;&nbsp;{{{usage: <<option chkFileDropTrimFilename>> }}}
<<option chkFileDropDisplay>> Automatically display newly created tiddlers
&nbsp;&nbsp;{{{usage: <<option chkFileDropDisplay>> }}}
Tag newly created tiddlers with: <<option txtFileDropTags>>
&nbsp;&nbsp;{{{usage: <<option txtFileDropTags>>}}}

__FileDrop+AttachFile configuration options:__
<<option chkFileDropAttachLocalLink>> Include reference to local path/filename
&nbsp;&nbsp;{{{usage: <<option chkFileDropAttachLocalLink>> }}}
<<option chkFileDropAttachEncodeData>> Include binary file data as encoded "base64" text
&nbsp;&nbsp;{{{usage: <<option chkFileDropAttachEncodeData>> }}}
...only if file is smaller than: <<option txtFileDropAttachDataLimit>> bytes
&nbsp;&nbsp;{{{usage: <<option txtFileDropAttachDataLimit>>}}}

See [[FileDropPlugin]] for more documentation on handler implementation specifics, including sample code for default drop handlers.
<<<
!!!!!Revisions
<<<
2008.08.11 [1.5.1] added chkFileDropAttachLocalLink option to allow suppression of local path/file link
2007.01.01 [0.9.9] initial release with extensions for AttachFilePlugin
<<<
!!!!!Code
***/
//{{{
if (config.options.chkFileDropAttachEncodeData==undefined)
	config.options.chkFileDropAttachEncodeData=true;
if (config.options.chkFileDropAttachLocalLink==undefined)
	config.options.chkFileDropAttachLocalLink=true;
if (config.options.txtFileDropAttachDataLimit==undefined)
	config.options.txtFileDropAttachDataLimit=32768;
if (config.options.txtFileDropTags==undefined)
	config.options.txtFileDropTags="";
if (config.options.chkFileDropDisplay==undefined)
	config.options.chkFileDropDisplay=true;
if (config.options.chkFileDropTrimFilename==undefined)
	config.options.chkFileDropTrimFilename=false;

config.macros.fileDrop.addEventListener("application/x-moz-file",function(nsiFile)
{
	var header="Index of %0\n^^(as of %1)^^\n|!filename| !size | !modified |\n";
	var item="|[[%0|%1]]| %2|%3|\n";
	var footer="Total of %0 bytes in %1 files\n";

	var now=new Date();
	var files=[nsiFile];
	if (nsiFile.isDirectory()) {
		var folder=nsiFile.directoryEntries;
		var files=[];
		while (folder.hasMoreElements()) {
			var f=folder.getNext().QueryInterface(Components.interfaces.nsILocalFile);
			if (f instanceof Components.interfaces.nsILocalFile && !f.isDirectory()) files.push(f);
		}
		var msg=nsiFile.path.replace(/\\/g,"/")+"\n\n";
		msg+="contains "+files.length+" files... ";
		msg+="select OK to attach all files or CANCEL to create a list...";
		if (!confirm(msg)) { // create a list in a tiddler
			var title=nsiFile.leafName; // tiddler name is last directory name in path
			while (title && title.length && store.tiddlerExists(title)) {
				if (confirm(config.messages.overwriteWarning.format([title]))) break; // use existing title
				title=prompt("Please enter a different tiddler title for this file",nsiFile.path.replace(/\\/g,"/"));
			}
			if (!title || !title.length) return true; // aborted by user... we're done!
			var text=header.format([nsiFile.path.replace(/\\/g,"/"),now.toLocaleString()]);
			var total=0;
			for (var i=0; i<files.length; i++) { var f=files[i];
				var name=f.leafName;
				if (config.options.chkFileDropTrimFilename)
					{ var p=name.split("."); if (p.length>1) p.pop(); name=p.join("."); }
				var path="file:///"+f.path.replace(/\\/g,"/");
				var size=f.fileSize; total+=size;
				var when=new Date(f.lastModifiedTime).formatString("YYYY.0MM.0DD 0hh:0mm:0ss");
				text+=item.format([name,path,size,when]);
			}
			text+=footer.format([total,files.length]);
			var newtags=config.options.txtFileDropTags?config.options.txtFileDropTags.readBracketedList():[];
			store.saveTiddler(null,title,text,config.options.txtUserName,now,newtags);
			if (config.options.chkFileDropDisplay) story.displayTiddler(null,title);
			return true;
		}
	}
	if (files.length>1) store.suspendNotifications();
	for (i=0; i<files.length; i++) {
		var file=files[i];
		if (file.isDirectory()) continue; // skip over nested directories
		var type="text/plain";
		var title=file.leafName; // tiddler name is file name
		if (config.options.chkFileDropTrimFilename)
			{ var p=title.split("."); if (p.length>1) p.pop(); title=p.join("."); }
		var path=file.path;
		var size=file.fileSize;
		while (title && title.length && store.tiddlerExists(title)) {
			if (confirm(config.messages.overwriteWarning.format([title]))) break; // use existing title
			title=prompt("Please enter a different tiddler title for this file",path.replace(/\\/g,"/"));
		}
		if (!title || !title.length) continue; // cancelled by user... skip this file
		if (config.macros.attach) {
			type=config.macros.attach.getMIMEType(file.leafName,"");
			if (!type.length)
				type=prompt("Unrecognized file type.  Please enter a MIME type for this file","text/plain");
			if (!type||!type.length) continue; // cancelled by user... skip this file
		}
		var newtags=config.options.txtFileDropTags?config.options.txtFileDropTags.readBracketedList():[];
		if (type=="text/plain")
			store.saveTiddler(null,title,loadFile(path),config.options.txtUserName,now,newtags);
		else {
			// only encode data if enabled and file is smaller than limit.  Default is 32768 (32K) bytes.
			var embed=config.options.chkFileDropAttachEncodeData
				&& file.fileSize<config.options.txtFileDropAttachDataLimit;
			newtags.push("attachment"); newtags.push("excludeMissing");
			var localfile="";
			if (config.options.chkFileDropAttachLocalLink) {
				// if file is in current document folder,
				// remove path prefix and use relative reference
				var localfile=path;
				var h=document.location.href;
				folder=getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf("/")+1)));
				if (localfile.substr(0,folder.length)==folder)
					localfile='./'+localfile.substr(folder.length);
			}
			config.macros.attach.createAttachmentTiddler(path,
				now.formatString(config.macros.timeline.dateFormat),
				"attached by FileDropPlugin", newtags,
				title, embed, config.options.chkFileDropAttachLocalLink, false,
				localfile, "", type,!config.options.chkFileDropDisplay);
		}
		if (config.options.chkFileDropDisplay) story.displayTiddler(null,title);
	}
	if (files.length>1) { store.resumeNotifications(); store.notifyAll(); }
	if (window.FFDEBUG) console.log(new Date()-now);
	return true;
})
//}}}
/***
|''Name:''|FootnotesPlugin|
|''Description:''|Create automated tiddler footnotes.|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#FootnotesPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.01|
|''Date:''|10/25/07|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.2|

!!Usage:
*To create a footnote, just put the footnote text inside triple backticks.
*Footnotes are numbered automatically, and listed at the bottom of the tiddler.
*{{{Creating a footnote is easy. ```This is the text for my footnote```}}}
*[[Example|FootnotesDemo]]
***/
// /%
//!BEGIN-PLUGIN-CODE
config.footnotesPlugin = {
	backLabel: "back",
	prompt:"show footnote"
};

config.formatters.unshift( {
    name: "footnotes",
    match: "```",
    lookaheadRegExp: /```((?:.|\n)*?)```/g,
    handler: function(w)
    {
        // rouilj to prevent function from erroring when rendered during an rss export operation
        // just exit if not being rendered within a story.
        if (!story.findContainingTiddler(place)) return;
        // end patch
        this.lookaheadRegExp.lastIndex = w.matchStart;
        var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
        if(lookaheadMatch && lookaheadMatch.index == w.matchStart )
            {
			var tiddler = story.findContainingTiddler(w.output);
			if (!tiddler.notes)
				tiddler.notes = [];
			var title = tiddler.getAttribute("tiddler");
			tiddler.notes.pushUnique(lookaheadMatch[1]);
			var pos = tiddler.notes.indexOf(lookaheadMatch[1]) + 1;
			createTiddlyButton(w.output,pos,config.footnotesPlugin.prompt,function(){var x = document.getElementById(title+"ftn"+pos);window.scrollTo(0,ensureVisible(x)+(ensureVisible(x)<findScrollY()?(findWindowHeight()-x.offsetHeight):0));return false;},"ftnlink",title+"ftnlink"+pos);			
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
            }
    }
});

old_footnotes_refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function(title,template,force)
{
    var tiddler = old_footnotes_refreshTiddler.apply(this,arguments);
	if (tiddler && tiddler.notes && tiddler.notes.length)
	{
		var holder = createTiddlyElement(null,"div",null,"footnoteholder");
		var list = createTiddlyElement(holder,"ol",title+"footnoteholder");
		for (var i=0; i<tiddler.notes.length; i++)
		{
			var ftn = createTiddlyElement(list,"li",title+"ftn"+(i+1),"footnote");
			wikify(tiddler.notes[i]+" ",ftn);
			createTiddlyButton(ftn,"["+config.footnotesPlugin.backLabel+"]",config.footnotesPlugin.backLabel,function(){window.scrollTo(0,ensureVisible(document.getElementById(this.parentNode.id.replace("ftn","ftnlink"))));return false;},"ftnbklink");
		}
		var count = tiddler.childNodes.length;
		for (var j=0; j<count; j++){
			if(hasClass(tiddler.childNodes[j],"viewer")){
				var viewer = tiddler.childNodes[j];	
			}
		}
		viewer.appendChild(holder);
		tiddler.notes = [];
	}
    return tiddler;
};

setStylesheet(
".tiddler a.ftnlink {vertical-align: super; font-size: 0.8em; color:red;}\n"+
".tiddler a.ftnlink:hover, .tiddler .footnoteholder a.ftnbklink:hover{color:#fff;background:red;}\n"+
".tiddler div.footnoteholder{margin:1.8em 1.0em; padding:0.1em 1.0em 0.1em 1.0em ;border-left: 1px solid #ccc;}"+
".tiddler footnoteholder ol {font-size: 0.9em; line-height: 1.2em;}\n"+
".tiddler .footnoteholder li.footnote {margin: 0 0 5px 0;}\n"+
".tiddler .footnoteholder a.ftnbklink{color:red;}\n","FootNotesStyles");
//!END-PLUGIN-CODE
// %/
!Inline Formatting
|!Option|!Syntax|!Output|
|bold font|{{{''bold''}}}|''bold''|
|italic type|{{{//italic//}}}|//italic//|
|underlined text|{{{__underlined__}}}|__underlined__|
|strikethrough text|{{{--strikethrough--}}}|--strikethrough--|
|superscript text|{{{^^super^^script}}}|^^super^^script|
|subscript text|{{{~~sub~~script}}}|~~sub~~script|
|highlighted text|{{{@@highlighted@@}}}|@@highlighted@@|
|preformatted text|<html><code>{{{preformatted}}}</code></html>|{{{preformatted}}}|
!Block Elements
!!Headings
{{{
!Heading 1
!!Heading 2
!!!Heading 3
!!!!Heading 4
!!!!!Heading 5
}}}
<<<
!Heading 1
!!Heading 2
!!!Heading 3
!!!!Heading 4
!!!!!Heading 5
<<<
!!Lists
{{{
* unordered list, level 1
** unordered list, level 2
*** unordered list, level 3

# ordered list, level 1
## ordered list, level 2
### unordered list, level 3

; definition list, term
: definition list, description
}}}
<<<
* unordered list, level 1
** unordered list, level 2
*** unordered list, level 3

# ordered list, level 1
## ordered list, level 2
### unordered list, level 3

; definition list, term
: definition list, description
<<<
!!Blockquotes
{{{
> blockquote, level 1
>> blockquote, level 2
>>> blockquote, level 3

<<<
blockquote
<<<
}}}
<<<
> blockquote, level 1
>> blockquote, level 2
>>> blockquote, level 3

> blockquote
<<<
!!Preformatted Text
<html><pre>
{{{
preformatted (e.g. code)
}}}
</pre></html>
<<<
{{{
preformatted (e.g. code)
}}}
<<<
!!Tables
{{{
|CssClass|k
|!heading column 1|!heading column 2|
|row 1, column 1|row 1, column 2|
|row 2, column 1|row 2, column 2|
|>|COLSPAN|
|ROWSPAN| … |
|~| … |
|CssProperty:value;…| … |
|caption|c
}}}
''Annotation:''
* The {{{>}}} marker creates a "colspan", causing the current cell to merge with the one to the right.
* The {{{~}}} marker creates a "rowspan", causing the current cell to merge with the one above.
<<<
|CssClass|k
|!heading column 1|!heading column 2|
|row 1, column 1|row 1, column 2|
|row 2, column 1|row 2, column 2|
|>|COLSPAN|
|ROWSPAN| … |
|~| … |
|CssProperty:value;…| … |
|caption|c
<<<
!!Images /% TODO %/
cf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]
!Hyperlinks
* [[WikiWords|WikiWord]] are automatically transformed to hyperlinks to the respective tiddler
** the automatic transformation can be suppressed by preceding the respective WikiWord with a tilde ({{{~}}}): {{{~WikiWord}}}
* [[PrettyLinks]] are enclosed in square brackets and contain the desired tiddler name: {{{[[tiddler name]]}}}
** optionally, a custom title or description can be added, separated by a pipe character ({{{|}}}): {{{[[title|target]]}}}<br>'''N.B.:''' In this case, the target can also be any website (i.e. URL).
!Custom Styling
* {{{@@CssProperty:value;CssProperty:value;…@@}}}<br>''N.B.:'' CSS color definitions should use lowercase letters to prevent the inadvertent creation of WikiWords.
* <html><code>{{customCssClass{…}}}</code></html>
* raw HTML can be inserted by enclosing the respective code in HTML tags: {{{<html> … </html>}}}
!Special Markers
* {{{<br>}}} forces a manual line break
* {{{----}}} creates a horizontal ruler
* [[HTML entities|http://www.tiddlywiki.com/#HtmlEntities]]
* {{{<<macroName>>}}} calls the respective [[macro|Macros]]
* To hide text within a tiddler so that it is not displayed, it can be wrapped in {{{/%}}} and {{{%/}}}.<br/>This can be a useful trick for hiding drafts or annotating complex markup.
* To prevent wiki markup from taking effect for a particular section, that section can be enclosed in three double quotes: e.g. {{{"""WikiWord"""}}}.
!usage
{{{[img[Frontscreen.png]]}}}
[img[Frontscreen.png]]
!notes
//none//
!type
image/png
!file
./support/images/Frontscreen.png
!url

!data
{{adiv{
<<showWhen window.location.protocol!='file:'>>
You ''MUST'' download the coursebook to your local disk from: <<wikify {{location.href}}>> (using the browser's download/save link mechanism). You are currently viewing it using http or https and ''can not'' save it while viewing it from the net.
{{adiv{
<<showWhen ! (config.browser.isIE || (navigator.userAgent.indexOf('Firefox') != -1)) >>
You must also download/save to disk <<wikify {{location.href}}>> in the same directory as the coursebook since you are not using Internet Explorer or Firefox.
}}}
}}} {{adiv{
<<showWhen window.location.protocol=='file:'>>
If you are seeing this tiddler when you first load the file, there is no content loaded in your coursebook yet. Follow the directions below to prepare this coursebook.

# Enter your username for signing your edits: <<option txtUserName>>.
# Click the outlined `button' below to load content into this empty book:<br /> <<loadTiddlers "label:Import new content from %0" updates {{store.getTiddlerSlice('GettingStarted','courseHomeContent')}} {{config.options['chkLoadTiddlersShowReport']=false;}} >>.{{aspan{<<showWhenExists Welcome>>@@<br />''Content has been loaded successfully''.@@}}}
# Once the content is loaded (it can take a minute),  click on <<saveChanges>> to save the changes.
# Then click to <html><a style="border: 1px solid #DDBB44" onClick="window.location.reload()">reload the page</a></html> or use F5 in your browser.
}}}

/%
Original content of this tiddler is located below.
----
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
%/


/%
URL's for LISA 2009

courseHome: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09
courseHomeBook: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09/SEC_tw.html
courseHomeTs: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09/TiddlySaver.jar
courseHomeContent: http://coursebook.tiddlyspot.com/coursebook_ps.html
courseHomeRss: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09/SEC_tw.xml
%/
{{adiv{
<<showWhen window.location.protocol!='file:'>>
You ''MUST'' download the coursebook to your local disk from: <<wikify {{location.href}}>> (using the browser's download/save link mechanism). You are currently viewing it using http or https and ''can not'' save it while viewing it from the net.
{{adiv{
<<showWhen ! (config.browser.isIE || (navigator.userAgent.indexOf('Firefox') != -1)) >>
You must also download/save to disk <<wikify {{location.href}}>> in the same directory as the coursebook since you are not using Internet Explorer or Firefox.
}}}
}}} {{adiv{
<<showWhen window.location.protocol=='file:'>>
If you are seeing this tiddler when you first load the file, there is no content loaded in your coursebook yet. Follow the directions below to prepare this coursebook.

# Enter your username for signing your edits: <<option txtUserName>>.
# Click the outlined `button' below to load content into this empty book:<br /> <<loadTiddlers "label:Import new content from %0" updates {{store.getTiddlerSlice('GettingStarted','courseHomeContent')}} {{config.options['chkLoadTiddlersShowReport']=false;}} >>.{{aspan{<<showWhenExists Welcome>>@@<br />''Content has been loaded successfully''.@@}}}
# Once the content is loaded (it can take a minute),  click on <<saveChanges>> to save the changes.
# Then click to <html><a style="border: 1px solid #DDBB44" onClick="window.location.reload()">reload the page</a></html> or use F5 in your browser.
}}}

/%
Original content of this tiddler is located below.
----
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
%/


/%
URL's for LISA 2009

courseHome: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09
courseHomeBook: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09/SEC_tw.html
courseHomeTs: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09/TiddlySaver.jar
courseHomeContent: http://coursebook.tiddlyspot.com/coursebook_ps.html
courseHomeRss: http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09/SEC_tw.xml
%/
<part chapterControlTiddler>
; Chapter Control Tiddler
:A tiddler tagged with the {{{chapter}}} tag. Each control tiddler has a control panel at the top that allows you to display the contents of the chapter. Changes to tiddler links in the chapter tiddler change the tiddlers that are considered part of the chapter.
</part>
<part multiTiddlerPresentation>
; multi-tiddler presentation
: a presentation where each slide is a different tiddler. This is the recommended form for presentations being distributed to students. See [[Chapter  1 - Types of Presentations##Multi-tiddler Presentations]].
</part>
<part presentationControlTiddler>
; Presentation Control Tiddler
:A tiddler tagged with the {{{presentation}}} tag. Each control tiddler has a control panel at the top that allows you to start the presentation in Instructor, Student or Print mode. Changes to this tiddler change the slides that are presented as part of the presentation.
</part>
<part singleTiddlerPresentation>
; single tiddler presentation
: a presentation where each slide is a delimited secton of a single tiddler. This is useful for kiosk type presentations that are meant to loop and stand alone. It is not the recommended form for presentations being distributed to students. See [[Chapter  1 - Types of Presentations##Single Tiddler Presentations]].
</part>
<part slice>
;slice
:A way of storing names and values inside a tiddler that can be extracted by using a reference in the form: {{{tiddlerName::sliceName}}}. Slices are defined using {{{slicename: sliceValue}}}  on a single line in a tiddler. There are alternate forms for creating a slice. See http://tiddlywiki.org/wiki/Tiddler_Slices for the details.
</part>
<part sync>
;sync
:1) The act of importing new copies of tiddlers from an external tiddlywiki. The act of syncing overwrites the imported tiddlers losing any changes made to them. The normal one-click [[sync tool|sync]] in the coursebook only updates content tiddlers. Note tiddlers are always preserved. <br />2) Do not confuse this with the sync mechanism in the backstage toolbar. The sync mechanism in the backstage toolbar replaces the plugins that make the coursebook work with the original published versions. Do not use [[sync from the backstage toolbar|Using the Backstage Link]] unless you are very experienced in managing  tiddlywiki.
</part>
<part transcluded>
;transcluded; transclude
:Including the contents or partial content of another tiddler in the current tiddler using the {{{<<tiddler>>}}} macro. Transcluded content can be in the form of: <<tiddler Glossary##transcludedTypes>> Tiddlers are referenced as {{{<<tiddler tiddlerName>>}}}. Sections are referenced as {{{<<tiddler tiddlerName##sectionTitle>>}}}, slices are referenced as {{{<<tiddler tiddlerName::sliceName>>}}} and parts (available with the PartTiddlerPlugin) are referenced as {{{<<tiddler tiddlerName/partName>>}}}. If the reference includes spaces, the reference must be surrounded by single quotes, double quotes or {{{[[...]]}}} doubled square brackets. For example: {{{<<tiddler "My Tiddler##Section One">>}}}
</part>
<part tiddlyWiki>
; ~TiddlyWiki
:A single file editable web page driven by javascript.
</part>
<part wikiWord>
; ~WikiWord
:A specially formatted word starting with a capital letter and having at least one more capital letter in the word. Also called camel case worids because the capital letters are like the humps on a camel. The unique thing about WikiWords is that they are automatically recognised as links to tiddlers with the same name. No other special formatting other than naming the tiddler is required to create a hyperlink.
</part>

/%
!transcludedTypes
* (whole) tiddlers
* sections
* slices
* parts.
!end
%/
<<tiddler SlideSubstyle##levelOne with: url("goal.jpg")>> {{overlay1{Presentations}}} {{overlay2{Textbook}}} {{overlay3{Notebook}}}

{{comment{
picture of a goal

[img[goal.jpg]]

Teaching tool for the Simple Event Correlator workshop at LISA 2009.
Meant to replace the usual tools:
*  powerpoint presentation
*  pdf's of slides for offline use/notes
*  supplimentary info as pdf or printed hardcopy
Since I had real working exercises, laptops/computers in class were required so an interactive coursebook was a possibility.
}}}
/***
|Name|GotoPlugin|
|Source|http://www.TiddlyTools.com/#GotoPlugin|
|Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
|Version|1.9.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|view any tiddler by entering it's title - displays list of possible matches|
''View a tiddler by typing its title and pressing //enter//.''  As you type, a list of possible matches is displayed.  You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press escape to close the listbox to resume typing.  When the listbox is not displayed, pressing //escape// clears the current input.
!!!Documentation
>see [[GotoPluginInfo]]
!!!Configuration
<<<
*Match titles only after {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters are entered.<br>Use down-arrow to start matching with shorter input.  //Note: This option value is also set/used by [[SearchOptionsPlugin]]//.
*To set the maximum height of the listbox, you can create a tiddler tagged with <<tag systemConfig>>, containing:
//{{{
config.macros.gotoTiddler.listMaxSize=10;  // change this number
//}}}
<<<
!!!Revisions
<<<
2009.05.22 [1.9.2] use reverseLookup() for IncludePlugin
|please see [[GotoPluginInfo]] for additional revision details|
2006.05.05 [0.0.0] started
<<<
!!!Code
***/
//{{{
version.extensions.GotoPlugin= {major: 1, minor: 9, revision: 2, date: new Date(2009,5,22)};

// automatically tweak shadow SideBarOptions to add <<gotoTiddler>> macro above <<search>>
config.shadowTiddlers.SideBarOptions=config.shadowTiddlers.SideBarOptions.replace(/<<search>>/,"{{button{goto}}}\n<<gotoTiddler>><<search>>");

if (config.options.txtIncrementalSearchMin===undefined) config.options.txtIncrementalSearchMin=3;

config.macros.gotoTiddler= { 
	listMaxSize: 10,
	listHeading: 'Found %0 matching title%1...',
	searchItem: "Search for '%0'...",
	handler:
	function(place,macroName,params,wikifier,paramString,tiddler) {
		var quiet	=params.contains("quiet");
		var showlist	=params.contains("showlist");
		var search	=params.contains("search");
		params = paramString.parseParams("anon",null,true,false,false);
		var instyle	=getParam(params,"inputstyle","");
		var liststyle	=getParam(params,"liststyle","");
		var filter	=getParam(params,"filter","");
		var html=this.html;
		var keyevent=window.event?"onkeydown":"onkeypress"; // IE event fixup for ESC handling
		html=html.replace(/%keyevent%/g,keyevent);
		html=html.replace(/%search%/g,search);
		html=html.replace(/%quiet%/g,quiet);
		html=html.replace(/%showlist%/g,showlist);
		html=html.replace(/%display%/g,showlist?'block':'none');
		html=html.replace(/%position%/g,showlist?'static':'absolute');
		html=html.replace(/%instyle%/g,instyle);
		html=html.replace(/%liststyle%/g,liststyle);
		html=html.replace(/%filter%/g,filter);
		if (config.browser.isIE) html=this.IEtableFixup.format([html]);
		var span=createTiddlyElement(place,'span');
		span.innerHTML=html; var form=span.getElementsByTagName("form")[0];
		if (showlist) this.fillList(form.list,'',filter,search,0);
	},
	html:
	'<form onsubmit="return false" style="display:inline;margin:0;padding:0">\
		<input name=gotoTiddler type=text autocomplete="off" accesskey="G" style="%instyle%"\
			title="Enter title text... ENTER=goto, SHIFT-ENTER=search for text, DOWN=select from list"\
			onfocus="this.select(); this.setAttribute(\'accesskey\',\'G\');"\
			%keyevent%="return config.macros.gotoTiddler.inputEscKeyHandler(event,this,this.form.list,%search%,%showlist%);"\
			onkeyup="return config.macros.gotoTiddler.inputKeyHandler(event,this,%quiet%,%search%,%showlist%);">\
		<select name=list style="display:%display%;position:%position%;%liststyle%"\
			onchange="if (!this.selectedIndex) this.selectedIndex=1;"\
			onblur="this.style.display=%showlist%?\'block\':\'none\';"\
			%keyevent%="return config.macros.gotoTiddler.selectKeyHandler(event,this,this.form.gotoTiddler,%showlist%);"\
			onclick="return config.macros.gotoTiddler.processItem(this.value,this.form.gotoTiddler,this,%showlist%);">\
		</select><input name="filter" type="hidden" value="%filter%">\
	</form>',
	IEtableFixup:
	"<table style='width:100%;display:inline;padding:0;margin:0;border:0;'>\
		<tr style='padding:0;margin:0;border:0;'><td style='padding:0;margin:0;border:0;'>\
		%0</td></tr></table>",
	getItems:
	function(list,val,filter) {
		if (!list.cache || !list.cache.length || val.length<=config.options.txtIncrementalSearchMin) {
			// starting new search, fetch and cache list of tiddlers/shadows/tags
			list.cache=new Array();
			if (filter.length) {
				var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
				var tiddlers=store.sortTiddlers(fn.apply(store,[filter]),'title');
			} else 
				var tiddlers=store.reverseLookup('tags','excludeLists');
			for(var t=0; t<tiddlers.length; t++) list.cache.push(tiddlers[t].title);
			if (!filter.length) {
				for (var t in config.shadowTiddlers) list.cache.pushUnique(t);
				var tags=store.getTags();
				for(var t=0; t<tags.length; t++) list.cache.pushUnique(tags[t][0]);
			}
		}
		var found = [];
		var match=val.toLowerCase();
		for(var i=0; i<list.cache.length; i++)
			if (list.cache[i].toLowerCase().indexOf(match)!=-1) found.push(list.cache[i]);
		return found;
	},
	getItemSuffix:
	function(t) {
		if (store.tiddlerExists(t)) return "";  // tiddler
		if (store.isShadowTiddler(t)) return " (shadow)"; // shadow
		return " (tag)"; // tag 
	},
	fillList:
	function(list,val,filter,search,key) {
		if (list.style.display=="none") return; // not visible... do nothing!
		var indent='\xa0\xa0\xa0';
		var found = this.getItems(list,val,filter); // find matching items...
		found.sort(); // alpha by title
		while (list.length > 0) list.options[0]=null; // clear list
		var hdr=this.listHeading.format([found.length,found.length==1?"":"s"]);
		list.options[0]=new Option(hdr,"",false,false);
		for (var t=0; t<found.length; t++) list.options[list.length]=
			new Option(indent+found[t]+this.getItemSuffix(found[t]),found[t],false,false);
		if (search)
			list.options[list.length]=new Option(this.searchItem.format([val]),"*",false,false);
		list.size=(list.length<this.listMaxSize?list.length:this.listMaxSize); // resize list...
		list.selectedIndex=key==38?list.length-1:key==40?1:0;
	},
	keyProcessed:
	function(ev) { // utility function
		ev.cancelBubble=true; // IE4+
		try{event.keyCode=0;}catch(e){}; // IE5
		if (window.event) ev.returnValue=false; // IE6
		if (ev.preventDefault) ev.preventDefault(); // moz/opera/konqueror
		if (ev.stopPropagation) ev.stopPropagation(); // all
		return false;
	},
	inputEscKeyHandler:
	function(event,here,list,search,showlist) {
		if (event.keyCode==27) {
			if (showlist) { // clear input, reset list
				here.value=here.defaultValue;
				this.fillList(list,'',here.form.filter.value,search,0);
			}
			else if (list.style.display=="none") // clear input
				here.value=here.defaultValue;
			else list.style.display="none"; // hide list
			return this.keyProcessed(event);
		}
		return true; // key bubbles up
	},
	inputKeyHandler:
	function(event,here,quiet,search,showlist) {
		var key=event.keyCode;
		var list=here.form.list;
		var filter=here.form.filter;
		// non-printing chars bubble up, except for a few:
		if (key<48) switch(key) {
			// backspace=8, enter=13, space=32, up=38, down=40, delete=46
			case 8: case 13: case 32: case 38: case 40: case 46: break; default: return true;
		}
		// blank input... if down/enter... fall through (list all)... else, and hide or reset list
		if (!here.value.length && !(key==40 || key==13)) {
			if (showlist) this.fillList(here.form.list,'',here.form.filter.value,search,0);
			else list.style.display="none";
			return this.keyProcessed(event);
		}
		// hide list if quiet, or below input minimum (and not showlist)
		list.style.display=(!showlist&&(quiet||here.value.length<config.options.txtIncrementalSearchMin))?'none':'block';
		// non-blank input... enter=show/create tiddler, SHIFT-enter=search for text
		if (key==13 && here.value.length) return this.processItem(event.shiftKey?'*':here.value,here,list,showlist);
		// up or down key, or enter with blank input... shows and moves to list...
		if (key==38 || key==40 || key==13) { list.style.display="block"; list.focus(); }
		this.fillList(list,here.value,filter.value,search,key);
		return true; // key bubbles up
	},
	selectKeyHandler:
	function(event,list,editfield,showlist) {
		if (event.keyCode==27) // escape... hide list, move to edit field
			{ editfield.focus(); list.style.display=showlist?'block':'none'; return this.keyProcessed(event); }
		if (event.keyCode==13 && list.value.length) // enter... view selected item
			{ this.processItem(list.value,editfield,list,showlist); return this.keyProcessed(event); }
		return true; // key bubbles up
	},
	processItem:
	function(title,here,list,showlist) {
		if (!title.length) return;
		list.style.display=showlist?'block':'none';
		if (title=="*")	{ story.search(here.value); return false; } // do full-text search
		if (!showlist) here.value=title;
		story.displayTiddler(null,title); // show selected tiddler
		return false;
	}
}
//}}}
/***
|Name|GotoPluginInfo|
|Source|http://www.TiddlyTools.com/#GotoPlugin|
|Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
|Version|1.9.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for GotoPlugin|
''View a tiddler by typing its title and pressing //enter//.''  As you type, a list of possible matches is displayed.  You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press escape to close the listbox to resume typing.  When the listbox is not displayed, pressing //escape// clears the current input.
!!!!!Usage/Examples
<<<
syntax: {{{<<gotoTiddler quiet search inputstyle:... liststyle:... filter:...>>}}}
All parameters are optional.
* ''quiet'' (//keyword//)<br>list will not be automatically display as each character is typed.  Use //down// or //enter// to view the list.
* ''showlist'' (//keyword//)<br>list will always be displayed, inline, directly below the input field.
* ''search'' (//keyword//)<br>adds an extra 'command item' to the list that can be used to invoke a full-text search using the entered value.  This can be especially useful when no matching tiddler titles have been found.
* ''inputstyle:'' and ''liststyle:''<br>are CSS declarations that modify the default input and listbox styles, respectively.  Note: the CSS styles must be surrounded by ({{{"..."}}} or {{{'...'}}}) or ({{{[[...]]}}}) (e.g., {{{liststyle:"border:1px dotted blue;color:green;..."}}}.
* ''filter:''<br>is a single tag value (or a boolean tag expression if MatchTagsPlugin is installed), and is used to limit the search to only those tiddlers matching the indicated tag or tag expression (e.g., {{{<<gotoTiddler filter:"faq or help">>}}})
{{{<<gotoTiddler>>}}}
<<gotoTiddler>>
{{{<<gotoTiddler search>>}}}
<<gotoTiddler search>>
{{{<<gotoTiddler showlist filter:"pluginInfo" liststyle:"height:10em;width:auto;">>}}}
<<gotoTiddler showlist filter:"pluginInfo" liststyle:"height:10em;width:auto;">>
<<<
!!!!!Configuration
<<<
*Match titles only after {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters are entered.<br>Use down-arrow to start matching with shorter input.  //Note: This option value is also set/used by [[SearchOptionsPlugin]]//.
*To set the maximum height of the listbox, you can create a tiddler tagged with <<tag systemConfig>>, containing:
//{{{
config.macros.gotoTiddler.listMaxSize=10;  // change this number
//}}}
<<<
!!!!!Revisions
<<<
2009.05.22 [1.9.2] use reverseLookup() for IncludePlugin
2009.04.12 [1.9.1] support multiple instances with different filters by using per-element tiddler cache instead of shared static cache
2009.04.05 [1.9.0] added 'showlist' parameter for inline display with listbox always visible.
2009.03.23 [1.8.0] added txtIncrementalSearchMin (default=3).  Avoids fetching long lists.  Use down arrow to force search with short input.
2008.12.15 [1.7.1] up arrow from input field now moves to end of droplist (search for input).  Also, shift+enter cam now be used to quickly invoke search for text.
2008.10.16 [1.7.0] in macro handler(), changed to use //named// params instead of positional params, and added optional "filter:" param for tag filtering.  Removed 'insert' handling (now provided by [[QuickEditPlugin]]).
2008.10.02 [1.6.1] for IE, wrap controls in a table.  Corrects placement of listbox so it is below input field.
2008.10.02 [1.6.0] added 'search' param for optional "Search for:" item that invokes full text search (especially useful when no title matches are found)
2008.02.17 [1.5.0] ENTER key always displays tiddler based on current input regardless of whether input matches any existing tiddler
2007.10.31 [1.4.3] removed extra trailing comma on last property of config.macros.gotoTiddler object.  This fixes an error under InternetExplorer that was introduced 6 days ago... sure, I should have found it sooner, but... WHY DON'T PEOPLE TELL ME WHEN THINGS ARE BROKEN!!!!
2007.10.25 [1.4.2] added onclick handler for input field, so that clicking in field hides the listbox.
2007.10.25 [1.4.1] re-wrote getItems() to cache list of tiddlers/shadows/tags and use case-folded simple text match instead of regular expression to find matching tiddlers.  This *vastly* reduces processing overhead between keystrokes, especially for documents with many (>1000) tiddlers.  Also, removed local definition of replaceSelection(), now supported directly by the TW2.2+ core, as well as via backward-compatible plugin
2007.04.25 [1.4.0] renamed macro from "goto" to "gotoTiddler".  This was necessary to avoid a fatal syntax error in Opera (and other browsers) that require strict adherence to ECMAScript 1.5 standards which defines the identifier "goto" as "reserved for FUTURE USE"... *sigh*
2007.04.21 [1.3.2] in html definition, removed DIV around droplist (see 1.2.6 below).  It created more layout problems then it solved. :-(
2007.04.01 [1.3.1] in processItem(), ensure that correct textarea field is found by checking for edit=="text" attribute
2007.03.30 [1.3.0] tweak SideBarOptions shadow to automatically add {{{<<goto>>}}} when using default sidebar content
2007.03.30 [1.2.6] in html definition, added DIV around droplist to fix IE problem where list appears next to input field instead of below it.  
2007.03.28 [1.2.5] in processItem(), set focus to text area before setting selection (needed for IE to get correct selection 'range')
2007.03.28 [1.2.4] added prompt for 'pretty text' when inserting a link into tiddler content
2007.03.28 [1.2.3] added local copy of core replaceSelection() and modified for different replace logic
2007.03.27 [1.2.2] in processItem(), use story.getTiddlerField() to retrieve textarea control
2007.03.26 [1.2.1] in html, use either 'onkeydown' (IE) or 'onkeypress' (Moz) event to process <esc> key sooner, to prevent <esc> from 'bubbling up' to the tiddler (which will close the current editor).
2007.03.26 [1.2.0] added support for optional "insert" keyword param.
2006.05.10 [1.1.2] when filling listbox, set selection to 'heading' item... auto-select first tiddler title when down/enter moves focus into listbox
2006.05.08 [1.1.1] added accesskey ("G") to input field html (also set when field gets focus).  Also, inputKeyHandler() skips non-printing/non-editing keys. 
2006.05.08 [1.1.0] added heading to listbox for better feedback (also avoids problems with 1-line droplist)
2006.05.07 [1.0.0] list matches against tiddlers/shadows/tags.  input field auto-completion... 1st enter=complete matching input (or show list)... 2nd enter=view tiddler.  "quiet" param controls when listbox appears.  handling for enter (13), escape(27), and down(40) keys.   Change 'ondblclick' to 'onclick' to avoid unintended triggering of tiddler editor).  Shadow titles inserted into list instead of appended to the end.
2006.05.05 [0.0.0] started
<<<
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{

window.hideWhenLastTest = false;

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


merge(config.macros,{

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

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

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

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

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

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

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

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

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

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

	hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.title == params[0], place);
	}},

	showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.title != params[0], place);
	}},

	'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !window.hideWhenLastTest, place);
	}}

});

//}}}
The directions on creating chapters and presentations assume as top down construction style. Create the containing/referring tiddlers first then create the content. However you can also create content directly and then link them back into large units (or not).
To create new content:
#  choose @@new content tiddler@@ from the sidebar
** a tiddler tagged with *content* is created.
** edit tiddler adding content
** add a reference to content tiddler to a chapter or other tiddler (optional)
*** If the tiddler title is a [[wikiword|Glossary/wikiWord]], just type the wikiword otherwise surround the title with double square brackets, e.g. {{{[[slide title]]}}}.

Because TiddlyWiki also functions as a non-linear textbook, linking all the content tiddlers into a chapter or presentation or another tiddler is not required. By using search, no links to a tiddler may be needed, although it is a good idea to provide some. You can find unlinked (orphaned) tiddlers by looking at the more tab in the sidebar and choosing the orphans subtab. If you have a tiddler that you want to keep unlinked, tag it with {{{excludeOrphans}} to remove it from the orphans tab.
In the right hand sidebar, choose @@new chapter tiddler@@. A   tiddler tagged with {{{chapter story content}}} is created. If this chapter is not supposed to be published to the student, replace the content tag with {{{InstructorOnly}}}.

Note that chapters in the main menu are sorted by title so the new tiddler is created with the standard title prefix "Chapter  1" with two spaces before the 1. This allows proper sorting it sorts {{{Chapter  1}}} before {{{Chapter 11}}}. Also some browsers (IE for example) don't display the full chapter title in the pull down list. As a result make your title unique in the first 15 or so characters so the student can look for the title in the title links section and select the properly named chapter from the pull down selection list.
The icons used in this coursebook were created by http://pixel-mixer.com. There are more in this set and can be seen at: http://www.iconarchive.com/category/application/basic-icons-by-pixelmixer.html

The following icons with suggested uses are available in this coursebook (shown reduced to 24 pixel size):

;[img(24px,)[block-icon.png]]
:error, danger, not recommended
;[img(24px,)[bookmark-icon.png]]
:bookmark
;[img(24px,)[bubble-icon.png]]
:idea, concept
;[img(24px,)[clipboard-icon.png]]
:record
;[img(24px,)[delete-icon.png]]
:delete, alternate danger don't do this
;[img(24px,)[flag-icon.png]]
:flag, mark as notable
;[img(24px,)[info-icon.png]]
:information
;[img(24px,)[label-icon.png]]
:label
;[img(24px,)[pencil-icon.png]]
:make note of
;[img(24px,)[search-icon.png]]
:reminder, references prior item, look at
;[img(24px,)[tick-icon.png]]
:recommended, tip
;[img(24px,)[warning-icon.png]]
:warning, caution
./support/
./support/images/
./support/icons/
/***
|Name|ImagePathPlugin|
|Source|http://www.TiddlyTools.com/#ImagePathPlugin|
|Version|0.7.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin,formatter|
|Requires||
|Overrides|'image' formatter|
|Description|Tell TiddlyWiki where to look for image files.  Permits multiple 'fallback' locations|
|Status|ALPHA - initial development/testing only - may be unstable - do not distribute|

!!!!!Usage
<<<
This plugin adds "resolvePath()" fallback processing to the {{{[img[...]]}}} formatter's handler, so that local image file references can be successfully resolved, even if the files cannot be located on the local filesystem.

The plugin tries alternative file "paths" that are listed, one per line, in an optional tiddler, [[ImagePathList]].  Each path in the list is combined with the image filename, which is then checked for existence, until the file is located.  If no alternative is found, or [[ImagePathList]] is not present, then a 'last-ditch' fallback is attempted using the remote system and path specified in [[SiteUrl]] (if present).

If no fallback attempt is successful (i.e., because no [[ImagePathList]] OR [[SiteUrl]] tiddlers have been defined), the plugin simply passes the original image file value along for default handling by the browser without any "path resolution" being applied.(i.e, the current TW core behavior occurs).

| ''Important note: This plugin may cause one or more security alert messages to appear, because it uses browser-specific functions that can require security permission in order to access the local filesystem to check for the existence of a given image file.  If you block local access, the 'last-ditch' fallback using the remote [[SiteUrl]] (if present) will be attempted.'' |

Note: the image formatter code contained here also includes support for AttachFilePlugin extensions (if installed).  AttachFilePlugin includes its own fallback mechanism for handling embedded vs. local file vs. remote URL references to the attached binary file.  Both methods may be used: ImagePathPlugin provides fallback for images contained in tiddler content, while AttachFilePlugin works well for access to non-image binary files (or images used in CSS as backgrounds, textures, etc.)
<<<
!!!!!Examples
<<<
coming soon...
<<<
!!!!!Revisions
<<<
''2007.04.13 [0.7.1]'' in testFile(), convert any file:// references to local native format before checking for existence.
''2007.03.26 [0.7.0]'' for IE, use onError handling to trigger call to resolvePath() so it will only be invoked if the original path/file is not found by the browser-native lookup.  This avoids an unneeded call to fileExists() and the accompanying ActiveX security alert message box (as well as being slightly more efficient...)
''2007.03.25 [0.6.0]'' code cleanup (moved global functions into config.formatterHelpers) plus documentation re-write
''2007.03.24 [0.5.0]'' initial implementation - ALPHA - do not distribute
<<<
!!!!!Code
***/
//{{{
version.extensions.ImagePathPlugin= {major: 0, minor: 7, revision: 1, date: new Date(2007,4,13)};
//}}}
//{{{
// name of path definition tiddler
if (config.options.txtPathTiddler==undefined) config.options.txtPathTiddler="ImagePathList";
//}}}
//{{{
// low-level wrapper for platform-specific tests for local file existence
// returns true/false without visible error display
// Uses Components for FF and ActiveX FSO object for MSIE
// NOTE: this can cause a security warning on some browsers
config.formatterHelpers.fileExists=function(theFile) {
	var found=false;
	// DEBUG: alert('testing fileExists('+theFile+')...');
	if(window.Components) {
		try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
		catch(e) { return false; } // security access denied
		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		try { file.initWithPath(theFile); }
		catch(e) { return false; } // invalid directory
		found = file.exists();
	}
	else { // use ActiveX FSO object for MSIE 
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		found = fso.FileExists(theFile)
	}
	// DEBUG: alert(theFile+" "+(found?"exists":"not found"));
	return found;
}
//}}}
//{{{
// higher-level logic for checking local file existence.
// with secondary check for finding relative file references
// and automatic OK of http-based references without checking local filesystem
config.formatterHelpers.testFile=function(theFile) {
	if (document.location.protocol!="file:") return true; // viewing remote document, can't test local filesystem... assume OK
	if (theFile.substr(0,5)=="http:") return true; // remote HTTP reference... assume OK
	if (theFile.substr(0,5)=="file:") theFile=getLocalPath(theFile); // convert local FILE reference to native format
	if (this.fileExists(theFile)) return true; // file exists locally... OK to use!
	// file might have been relative, add path from current document and try again
	var docPath=document.location.href;
	var slashpos=docPath.lastIndexOf("/"); if (slashpos==-1) slashpos=docPath.lastIndexOf("\\"); 
	if (slashpos!=-1 && slashpos!=docPath.length-1) docPath=docPath.substr(0,slashpos+1); // trim off filename
	if (this.fileExists(getLocalPath(docPath+theFile)))
		return true; // ah ha!... file exists relative to current document... OK to use!
	return false; // file not found on local system
}
//}}}
//{{{
// given a path/file string, check for existence and
// try alternatives (if any) defined in a tiddler
// with last-ditch using system/path from SiteUrl (if any)
config.formatterHelpers.resolvePath=function(theFile,testoriginal) {
	if (testoriginal && this.testFile(theFile)) return theFile; // FOUND FILE - use specified path/file without modification
	// get the filename portion only
	var slashpos=theFile.lastIndexOf("/"); if (slashpos==-1) slashpos=theFile.lastIndexOf("\\"); 
	var theName=(slashpos==-1)?theFile:theFile.substr(slashpos+1);
	// get list of fallbacks (if any)
	var pathText=store.getTiddlerText(config.options.txtPathTiddler);
	if (pathText && pathText.length) {
		var paths=pathText.split("\n");
		for (p=0; p<paths.length; p++) // combine path+filename until one works...
			if (this.testFile(paths[p]+theName))
				return paths[p]+theName; // FOUND FILE - use alternative path+filename
	}
	// try "last ditch" fallback using SiteURL - assumes that original path/file was relative to document location
	var siteURL=store.getTiddlerText("SiteUrl");
	if (!siteURL||!siteURL.length) return theFile; // NO FALLBACK - use original path/file and hope for the best
	// trim filename (if any) from site URL
	var slashpos=siteURL.lastIndexOf("/"); if (slashpos==-1) slashpos=siteURL.lastIndexOf("\\"); 
	if (slashpos!=-1 && slashpos!=siteURL.length-1) siteURL=siteURL.substr(0,slashpos+1);
	return siteURL+theFile; // LAST DITCH: use system/path from SiteUrl combined with original file/path
}
//}}}
//{{{
// replace standard handler for image formatter
// adds call to resolvePath() to handle fallback processing
// includes support for AttachFilePlugin as well
config.formatters[config.formatters.findByField("name","image")].handler=function(w) {
	if (!this.lookaheadRegExp)  // fixup for TW2.0.x
		this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		// Simple bracketted link
		var e = w.output;
		if(lookaheadMatch[5]) {
			var link = lookaheadMatch[5];
			if (!config.formatterHelpers.isExternalLink) // fixup for TW2.0.x
				var external=!store.tiddlerExists(link)&&!store.isShadowTiddler(link);
			else
				var external=config.formatterHelpers.isExternalLink(link);
			if (external) {
				if (config.macros.attach && config.macros.attach.isAttachment(link)) { // ELS - attachments
					e = createExternalLink(w.output,link);
					e.href=config.macros.attach.getAttachment(link);
					e.title = config.macros.attach.linkTooltip + link;
				} else
					e = createExternalLink(w.output,link);
			} else 
				e = createTiddlyLink(w.output,link,false,null,w.isStatic);
			addClass(e,"imageLink");
		}
		var img = createTiddlyElement(e,"img");
		if(lookaheadMatch[1])
			img.align = "left";
		else if(lookaheadMatch[2])
			img.align = "right";
		if(lookaheadMatch[3])
			img.title = lookaheadMatch[3];
		if (config.macros.attach!=undefined && config.macros.attach.isAttachment(lookaheadMatch[4])) // ELS - attachments
			img.src=config.macros.attach.getAttachment(lookaheadMatch[4]);
		else {
			if (config.browser.isIE || config.browser.isSafari) { // ELS - path processing
				// IE and Safari use browser's onError handling to check the original file...
				// avoids extra security alert messages due to use of Components/ActiveX for filesystem access
				img.onerror=(function(){this.src=config.formatterHelpers.resolvePath(this.src,false);return false;});
				img.src=lookaheadMatch[4]; // ELS - path processing
			} else {
				// if NOT IE or Safari, always check the original path/file before rendering
				img.src=config.formatterHelpers.resolvePath(lookaheadMatch[4],true);
			}
		}
		w.nextMatch = this.lookaheadRegExp.lastIndex;
	}
}
//}}}
/***
|Name|ImageSizePlugin|
|Source|http://www.TiddlyTools.com/#ImageSizePlugin|
|Version|1.2.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin,formatter|
|Requires||
|Overrides|'image' formatter|
|Description|adds support for resizing images|
This plugin adds optional syntax to scale an image to a specified width and height and/or interactively resize the image with the mouse.
!!!!!Usage
<<<
The extended image syntax is:
{{{
[img(w+,h+)[...][...]]
}}}
where ''(w,h)'' indicates the desired width and height (in CSS units, e.g., px, em, cm, in, or %). Use ''auto'' (or a blank value) for either dimension to scale that dimension proportionally (i.e., maintain the aspect ratio). You can also calculate a CSS value 'on-the-fly' by using a //javascript expression// enclosed between """{{""" and """}}""". Appending a plus sign (+) to a dimension enables interactive resizing in that dimension (by dragging the mouse inside the image). Use ~SHIFT-click to show the full-sized (un-scaled) image. Use ~CTRL-click to restore the starting size (either scaled or full-sized).
<<<
!!!!!Examples
<<<
{{{
[img(100px+,75px+)[images/meow2.jpg]]
}}}
[img(100px+,75px+)[images/meow2.jpg]]
{{{
[<img(34%+,+)[images/meow.gif]]
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img(  1%+,+)[images/meow.gif]]
}}}
[<img(34%+,+)[images/meow.gif]]
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img(  1%+,+)[images/meow.gif]]
{{tagClear{
}}}
<<<
!!!!!Revisions
<<<
2009.02.24 [1.2.1] cleanup width/height regexp, use '+' suffix for resizing
2009.02.22 [1.2.0] added stretchable images
2008.01.19 [1.1.0] added evaluated width/height values
2008.01.18 [1.0.1] regexp for "(width,height)" now passes all CSS values to browser for validation
2008.01.17 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImageSizePlugin= {major: 1, minor: 2, revision: 1, date: new Date(2009,2,24)};
//}}}
//{{{
var f=config.formatters[config.formatters.findByField("name","image")];
f.match="\\[[<>]?[Ii][Mm][Gg](?:\\([^,]*,[^\\)]*\\))?\\[";
f.lookaheadRegExp=/\[([<]?)(>?)[Ii][Mm][Gg](?:\(([^,]*),([^\)]*)\))?\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg;
f.handler=function(w) {
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var floatLeft=lookaheadMatch[1];
		var floatRight=lookaheadMatch[2];
		var width=lookaheadMatch[3];
		var height=lookaheadMatch[4];
		var tooltip=lookaheadMatch[5];
		var src=lookaheadMatch[6];
		var link=lookaheadMatch[7];

		// Simple bracketted link
		var e = w.output;
		if(link) { // LINKED IMAGE
			if (config.formatterHelpers.isExternalLink(link)) {
				if (config.macros.attach && config.macros.attach.isAttachment(link)) {
					// see [[AttachFilePluginFormatters]]
					e = createExternalLink(w.output,link);
					e.href=config.macros.attach.getAttachment(link);
					e.title = config.macros.attach.linkTooltip + link;
				} else
					e = createExternalLink(w.output,link);
			} else 
				e = createTiddlyLink(w.output,link,false,null,w.isStatic);
			addClass(e,"imageLink");
		}

		var img = createTiddlyElement(e,"img");
		if(floatLeft) img.align="left"; else if(floatRight) img.align="right";
		if(width||height) {
			var x=width.trim(); var y=height.trim();
			var stretchW=(x.substr(x.length-1,1)=='+'); if (stretchW) x=x.substr(0,x.length-1);
			var stretchH=(y.substr(y.length-1,1)=='+'); if (stretchH) y=y.substr(0,y.length-1);
			if (x.substr(0,2)=="{{")
				{ try{x=eval(x.substr(2,x.length-4))} catch(e){displayMessage(e.description||e.toString())} }
			if (y.substr(0,2)=="{{")
				{ try{y=eval(y.substr(2,y.length-4))} catch(e){displayMessage(e.description||e.toString())} }
			img.style.width=x.trim(); img.style.height=y.trim();
			config.formatterHelpers.addStretchHandlers(img,stretchW,stretchH);
		}
		if(tooltip) img.title = tooltip;

		// GET IMAGE SOURCE
		if (config.macros.attach && config.macros.attach.isAttachment(src))
			src=config.macros.attach.getAttachment(src); // see [[AttachFilePluginFormatters]]
		else if (config.formatterHelpers.resolvePath) { // see [[ImagePathPlugin]]
			if (config.browser.isIE || config.browser.isSafari) {
				img.onerror=(function(){
					this.src=config.formatterHelpers.resolvePath(this.src,false);
					return false;
				});
			} else
				src=config.formatterHelpers.resolvePath(src,true);
		}
		img.src=src;
		w.nextMatch = this.lookaheadRegExp.lastIndex;
	}
}

config.formatterHelpers.addStretchHandlers=function(e,stretchW,stretchH) {
	e.title=((stretchW||stretchH)?'DRAG=stretch/shrink, ':'')
		+'SHIFT-CLICK=show full size, CTRL-CLICK=restore initial size';
	e.statusMsg='width=%0, height=%1';
	e.style.cursor='move';
	e.originalW=e.style.width;
	e.originalH=e.style.height;
	e.minW=Math.max(e.offsetWidth/20,10);
	e.minH=Math.max(e.offsetHeight/20,10);
	e.stretchW=stretchW;
	e.stretchH=stretchH;
	e.onmousedown=function(ev) { var ev=ev||window.event;
		this.sizing=true;
		this.startX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
		this.startY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
		this.startW=this.offsetWidth;
		this.startH=this.offsetHeight;
		return false;
	};
	e.onmousemove=function(ev) { var ev=ev||window.event;
		if (this.sizing) {
			var s=this.style;
			var currX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
			var currY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
			var newW=(currX-this.offsetLeft)/(this.startX-this.offsetLeft)*this.startW;
			var newH=(currY-this.offsetTop )/(this.startY-this.offsetTop )*this.startH;
			if (this.stretchW) s.width =Math.floor(Math.max(newW,this.minW))+'px';
			if (this.stretchH) s.height=Math.floor(Math.max(newH,this.minH))+'px';
			clearMessage(); displayMessage(this.statusMsg.format([s.width,s.height]));
		}
		return false;
	};
	e.onmouseup=function(ev) { var ev=ev||window.event;
		if (ev.shiftKey) { this.style.width=this.style.height=''; }
		if (ev.ctrlKey)  { this.style.width=this.originalW; this.style.height=this.originalH; }
		this.sizing=false;
		clearMessage();
		return false;
	};
	e.onmouseout=function(ev) { var ev=ev||window.event;
		this.sizing=false;
		clearMessage();
		return false;
	};
}
//}}}
The plugins in this package provide interactive functionality for importing/exporting tiddlers to/from other TiddlyWiki documents.  Additional plugins provide enhanced local/remote file I/O features, including "save as", "save from web" and "upload" functionality.
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|interactive controls for import/export with filtering.|
Combine tiddlers from any two TiddlyWiki documents.  Interactively select and copy tiddlers from another TiddlyWiki source document.  Includes prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  When done, a list of all imported tiddlers is written into [[ImportedTiddlers]].
!!!!!Documentation
<<<
see [[ImportTiddlersPluginInfo]] for details
<<<
!!!!!interactive control panel
<<<
<<importTiddlers inline>>
{{clear{
^^(see also: [[ImportTiddlers]] shadow tiddler)^^}}}
<<<
!!!!!Revisions
<<<
2009.10.06 4.6.0 added createTiddlerFromFile (import text files)
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImportTiddlersPlugin= {major: 4, minor: 6, revision: 0, date: new Date(2009,10,6)};

// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;

// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;

// default shadow definition
config.shadowTiddlers.ImportTiddlers='<<importTiddlers inline>>';

// use shadow tiddler content in backstage panel
if (config.tasks) config.tasks.importTask.content='<<tiddler ImportTiddlers>>' // TW2.2 or above
//}}}
//{{{
// backward-compatiblity for TW2.0.x and TW1.2.x
if (config.macros.importTiddlers==undefined) config.macros.importTiddlers={};
if (typeof merge=='undefined') {
	function merge(dst,src,preserveExisting) {
		for(var i in src) { if(!preserveExisting || dst[i] === undefined) dst[i] = src[i]; }
		return dst;
	}
}
if (config.browser.isGecko===undefined)
	config.browser.isGecko=(config.userAgent.indexOf('gecko')!=-1);
//}}}
//{{{
merge(config.macros.importTiddlers,{
	$: function(id) { return document.getElementById(id); }, // abbreviation
	label: 'import tiddlers',
	prompt: 'Copy tiddlers from another document',
	openMsg: 'Opening %0',
	openErrMsg: 'Could not open %0 - error=%1',
	readMsg: 'Read %0 bytes from %1',
	foundMsg: 'Found %0 tiddlers in %1',
	filterMsg: "Filtered %0 tiddlers matching '%1'",
	summaryMsg: '%0 tiddler%1 in the list',
	summaryFilteredMsg: '%0 of %1 tiddler%2 in the list',
	plural: 's are',
	single: ' is',
	countMsg: '%0 tiddlers selected for import',
	processedMsg: 'Processed %0 tiddlers',
	importedMsg: 'Imported %0 of %1 tiddlers from %2',
	loadText: 'please load a document...',
	closeText: 'close',
	doneText: 'done',
	startText: 'import',
	stopText: 'stop',
	local: true,		// default to import from local file
	src: '',		// path/filename or URL of document to import (retrieved from SiteUrl)
	proxy: '',		// URL for remote proxy script (retrieved from SiteProxy)
	useProxy: false,	// use specific proxy script in front of remote URL
	inbound: null,		// hash-indexed array of tiddlers from other document
	newTags: '',		// text of tags added to imported tiddlers
	addTags: true,		// add new tags to imported tiddlers
	listsize: 10,		// # of lines to show in imported tiddler list
	importTags: true,	// include tags from remote source document when importing a tiddler
	keepTags: true,		// retain existing tags when replacing a tiddler
	sync: false,		// add 'server' fields to imported tiddlers (for sync function)
	lastFilter: '',		// most recent filter (URL hash) applied
	lastAction: null,	// most recent collision button performed
	index: 0,		// current processing index in import list
	sort: ''		// sort order for imported tiddler listbox
});
//}}}
//{{{
// hijack core macro handler
if (config.macros.importTiddlers.coreHandler==undefined)
	config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler;

config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
		if (config.macros.importTiddlers.coreHandler)
			config.macros.importTiddlers.coreHandler.apply(this,arguments);
		else 
			createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
	} else if (params[0]=='link') { // show link to floating panel
		createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
	} else if (params[0]=='inline') {// show panel as INLINE tiddler content
		createImportPanel(place);
		this.$('importPanel').style.position='static';
		this.$('importPanel').style.display='block';
	} else if (config.macros.loadTiddlers)
		config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}
//}}}
//{{{
// Handle link click to create/show/hide control panel
function onClickImportMenu(e) { var e=e||window.event;
	var parent=resolveTarget(e).parentNode;
	var panel=document.getElementById('importPanel');
	if (panel==undefined || panel.parentNode!=parent) panel=createImportPanel(parent);
	var isOpen=panel.style.display=='block';
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,false,'none'));
	else
		panel.style.display=isOpen?'none':'block';
	e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
}
//}}}
//{{{
// Create control panel: HTML, CSS
function createImportPanel(place) {
	var cmi=config.macros.importTiddlers; // abbrev
	var panel=cmi.$('importPanel');
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(store.getTiddlerText('ImportTiddlersPlugin##css'),'importTiddlers');
	panel=createTiddlyElement(place,'span','importPanel',null,null)
	panel.innerHTML=store.getTiddlerText('ImportTiddlersPlugin##html');
	refreshImportList();
	if (!cmi.src.length) cmi.src=store.getTiddlerText('SiteUrl')||'';
	cmi.$('importSourceURL').value=cmi.src;
	if (!cmi.proxy.length) cmi.proxy=store.getTiddlerText('SiteProxy')||'SiteProxy';
	cmi.$('importSiteProxy').value=cmi.proxy;
	if (config.browser.isGecko) { // FF3 FIXUP
		cmi.$('fileImportSource').style.display='none';
		cmi.$('importLocalPanelFix').style.display='block';
	}
	cmi.$('chkSync').checked=cmi.sync;
	cmi.$('chkImportTags').checked=cmi.importTags;
	cmi.$('chkKeepTags').checked=cmi.keepTags;
	cmi.$('chkAddTags').checked=cmi.addTags;
	cmi.$('txtNewTags').value=cmi.newTags;
	cmi.$('txtNewTags').style.display=cmi.addTags?'block':'none';
	cmi.$('chkSync').checked=cmi.sync;
	cmi.$('chkImportReport').checked=config.options.chkImportReport;
	return panel;
}
//}}}
//{{{
// process control interactions
function onClickImportButton(which,event) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var list=cmi.$('importList'); if (!list) return false;
	var thePanel=cmi.$('importPanel');
	var theCollisionPanel=cmi.$('importCollisionPanel');
	var theNewTitle=cmi.$('importNewTitle');
	var count=0;
	switch (which.id)
		{
		case 'importFromFile':	// show local panel
		case 'importFromWeb':	// show HTTP panel
			cmi.local=(which.id=='importFromFile');
			cmi.showPanel('importLocalPanel',cmi.local);
			cmi.showPanel('importHTTPPanel',!cmi.local);
			break;
		case 'importOptions':	// show/hide options panel
			cmi.showPanel('importOptionsPanel',cmi.$('importOptionsPanel').style.display=='none');
			break;
		case 'fileImportSource':
		case 'importLoad':		// load import source into hidden frame
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			if (cmi.src=='') break;
			// Load document, read it's DOM and fill the list
			cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
			break;
		case 'importSelectFeed':	// select a pre-defined systemServer feed URL
			var p=Popup.create(which); if (!p) return false;
			var tids=store.getTaggedTiddlers('systemServer');
			if (!tids.length)
				createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
			for (var t=0; t<tids.length; t++) {
				var u=store.getTiddlerSlice(tids[t].title,'URL');
				var d=store.getTiddlerSlice(tids[t].title,'Description');
				if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,'description');
				if (!d||!d.length) d=u;
				createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
					function(){
						var u=this.getAttribute('url');
						document.getElementById('importSourceURL').value=u;
						config.macros.importTiddlers.src=u;
						document.getElementById('importLoad').onclick();
					},
					null,null,null,{url:u});
			}
			Popup.show();
			event.cancelBubble = true;
			if (event.stopPropagation) event.stopPropagation();
			return false;
			// create popup with feed list
			// onselect, insert feed URL into input field.
			break;
		case 'importSelectAll':		// select all tiddler list items (i.e., not headings)
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				if (list.options[t].value=='') continue;
				list.options[t].selected=true;
				count++;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			cmi.$('importStart').disabled=!count;
			break;
		case 'importSelectNew':		// select tiddlers not in current document
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=='') continue;
				list.options[t].selected=!store.tiddlerExists(list.options[t].value);
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			cmi.$('importStart').disabled=!count;
			break;
		case 'importSelectChanges':		// select tiddlers that are updated from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value==''||!store.tiddlerExists(list.options[t].value)) continue;
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			cmi.$('importStart').disabled=!count;
			break;
		case 'importSelectDifferences':		// select tiddlers that are new or different from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=='') continue;
				if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			cmi.$('importStart').disabled=!count;
			break;
		case 'importApplyFilter':	// filter list to include only matching tiddlers
			importReport();		// if an import was in progress, generate a report
			clearMessage();
			if (!cmi.all) // no tiddlers loaded = '0 selected'
				{ displayMessage(cmi.countMsg.format([0])); return false; }
			var hash=cmi.$('importLastFilter').value;
			cmi.inbound=cmi.filterByHash('#'+hash,cmi.all);
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importStart':		// initiate the import processing
			importReport();		// if an import was in progress, generate a report
			cmi.$('importApplyToAll').checked=false;
			cmi.$('importStart').value=cmi.stopText;
			if (cmi.index>0) cmi.index=-1; // stop processing
			else cmi.index=importTiddlers(0); // or begin processing
			importStopped();
			break;
		case 'importClose':		// unload imported tiddlers or hide the import control panel
			// if imported tiddlers not loaded, close the import control panel
			if (!cmi.inbound) { thePanel.style.display='none'; break; }
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importSkip':	// don't import the tiddler
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported = cmi.inbound[j];
			theImported.status='skipped after asking';			// mark item as skipped
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index+1);	// resume with NEXT item
			importStopped();
			break;
		case 'importRename':		// change name of imported tiddler
			cmi.lastAction=which;
			var theItem		= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported		= cmi.inbound[j];
			theImported.status	= 'renamed from '+theImported.title;	// mark item as renamed
			theImported.set(theNewTitle.value,null,null,null,null);		// change the tiddler title
			theItem.value		= theNewTitle.value;			// change the listbox item text
			theItem.text		= theNewTitle.value;			// change the listbox item text
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importMerge':	// join existing and imported tiddler content
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported	= cmi.inbound[j];
			var theExisting	= store.getTiddler(theItem.value);
			var theText	= theExisting.text+'\n----\n^^merged from: ';
			theText		+='[['+cmi.src+'#'+theItem.value+'|'+cmi.src+'#'+theItem.value+']]^^\n';
			theText		+='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
			var theDate	= new Date();
			var theTags	= theExisting.getTags()+' '+theImported.getTags();
			theImported.set(null,theText,null,theDate,theTags);
			theImported.status   = 'merged with '+theExisting.title;	// mark item as merged
			theImported.status  += ' - '+theExisting.modified.formatString('MM/DD/YYYY 0hh:0mm:0ss');
			theImported.status  += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with this item
			importStopped();
			break;
		case 'importReplace':		// substitute imported tiddler for existing tiddler
			cmi.lastAction=which;
			var theItem		  = list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported     = cmi.inbound[j];
			var theExisting	  = store.getTiddler(theItem.value);
			theImported.status  = 'replaces '+theExisting.title;		// mark item for replace
			theImported.status += ' - '+theExisting.modified.formatString('MM/DD/YYYY 0hh:0mm:0ss');
			theImported.status += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importListSmaller':		// decrease current listbox size, minimum=5
			if (list.options.length==1) break;
			list.size-=(list.size>5)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListLarger':		// increase current listbox size, maximum=number of items in list
			if (list.options.length==1) break;
			list.size+=(list.size<list.options.length)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListMaximize':	// toggle listbox size between current and maximum
			if (list.options.length==1) break;
			list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
			break;
		}
}
//}}}
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
	if (typeof place=='string') var place=document.getElementById(place);
	if (!place||!place.style) return;
	if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,'none'));
	else place.style.display=show?'block':'none';
}
//}}}
//{{{
function refreshImportList(selectedIndex) {
	var cmi=config.macros.importTiddlers; // abbrev
	var list=cmi.$('importList'); if (!list) return;
	// if nothing to show, reset list content and size
	if (!cmi.inbound) {
		while (list.length > 0) { list.options[0] = null; }
		list.options[0]=new Option(cmi.loadText,'',false,false);
		list.size=cmi.listsize;
		cmi.$('importLoad').disabled=false;
		cmi.$('importLoad').style.display='inline';
		cmi.$('importStart').disabled=true;
		cmi.$('importOptions').disabled=true;
		cmi.$('importOptions').style.display='none';
		cmi.$('fileImportSource').disabled=false;
		cmi.$('importFromFile').disabled=false;
		cmi.$('importFromWeb').disabled=false;
		cmi.$('importStart').value=cmi.startText;
		cmi.$('importClose').value=cmi.doneText;
		cmi.$('importSelectPanel').style.display='none';
		cmi.$('importOptionsPanel').style.display='none';
		return;
	}
	// there are inbound tiddlers loaded...
	cmi.$('importLoad').disabled=true;
	cmi.$('importLoad').style.display='none';
	cmi.$('importOptions').style.display='inline';
	cmi.$('importOptions').disabled=false;
	cmi.$('fileImportSource').disabled=true;
	cmi.$('importFromFile').disabled=true;
	cmi.$('importFromWeb').disabled=true;
	cmi.$('importClose').value=cmi.closeText;
	if (cmi.$('importSelectPanel').style.display=='none')
		cmi.showPanel('importSelectPanel',true);

	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) cmi.sort='title';		// heading
	if (selectedIndex==1) cmi.sort='title';
	if (selectedIndex==2) cmi.sort='modified';
	if (selectedIndex==3) cmi.sort='tags';
	if (selectedIndex>3) {
		// display selected tiddler count
		for (var t=0,count=0; t < list.options.length; t++) {
			if (!list.options[t].selected) continue;
			if (list.options[t].value!='')
				count+=1;
			else { // if heading is selected, deselect it, and then select and count all in section
				list.options[t].selected=false;
				for ( t++; t<list.options.length && list.options[t].value!=''; t++) {
					list.options[t].selected=true;
					count++;
				}
			}
		}
		clearMessage(); displayMessage(cmi.countMsg.format([count]));
	}
	cmi.$('importStart').disabled=!count;
	if (selectedIndex>3) return; // no refresh needed

	// get the alphasorted list of tiddlers
	var tiddlers=cmi.inbound;
	tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
	// clear current list contents
	while (list.length > 0) { list.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	if (cmi.all.length==tiddlers.length)
		var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
	else
		var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
	list.options[i++]=new Option(summary,'',false,false);
	list.options[i++]=new Option(((cmi.sort=='title'   )?'>':indent)+' [by title]','',false,false);
	list.options[i++]=new Option(((cmi.sort=='modified')?'>':indent)+' [by date]','',false,false);
	list.options[i++]=new Option(((cmi.sort=='tags')?'>':indent)+' [by tags]','',false,false);
	// output the tiddler list
	switch(cmi.sort) {
		case 'title':
			for(var t = 0; t < tiddlers.length; t++)
				list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case 'modified':
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
			var lastSection = '';
			for(var t = 0; t < tiddlers.length; t++) {
				var tiddler = tiddlers[t];
				var theSection = tiddler.modified.toLocaleDateString();
				if (theSection != lastSection) {
					list.options[i++] = new Option(theSection,'',false,false);
					lastSection = theSection;
				}
				list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
			}
			break;
		case 'tags':
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles['untagged']==undefined) { theTags.push('untagged'); theTitles['untagged']=new Array(); }
					theTitles['untagged'].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				list.options[i++]=new Option(theTag,'',false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	list.selectedIndex=selectedIndex;		  // select current control item
	if (list.size<cmi.listsize) list.size=cmi.listsize;
	if (list.size>list.options.length) list.size=list.options.length;
}
//}}}
//{{{
// re-entrant processing for handling import with interactive collision prompting
function importTiddlers(startIndex) {
	var cmi=config.macros.importTiddlers; // abbrev
	if (!cmi.inbound) return -1;
	var list=cmi.$('importList'); if (!list) return;
	var t;
	// if starting new import, reset import status flags
	if (startIndex==0)
		for (var t=0;t<cmi.inbound.length;t++)
			cmi.inbound[t].status='';
	for (var i=startIndex; i<list.options.length; i++) {
		// if list item is not selected or is a heading (i.e., has no value), skip it
		if ((!list.options[i].selected) || ((t=list.options[i].value)==''))
			continue;
		for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==t) break;
		var inbound = cmi.inbound[j];
		var theExisting = store.getTiddler(inbound.title);
		// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
		if (inbound.status=='added')
			continue;
		// don't import the 'ImportedTiddlers' history from the other document...
		if (inbound.title=='ImportedTiddlers')
			continue;
		// if tiddler exists and import not marked for replace or merge, stop importing
		if (theExisting && (inbound.status.substr(0,7)!='replace') && (inbound.status.substr(0,5)!='merge'))
			return i;
		// assemble tags (remote + existing + added)
		var newTags = '';
		if (cmi.importTags)
			newTags+=inbound.getTags()	// import remote tags
		if (cmi.keepTags && theExisting)
			newTags+=' '+theExisting.getTags(); // keep existing tags
		if (cmi.addTags && cmi.newTags.trim().length)
			newTags+=' '+cmi.newTags; // add new tags
		inbound.set(null,null,null,null,newTags.trim());
		// set the status to 'added' (if not already set by the 'ask the user' UI)
		inbound.status=(inbound.status=='')?'added':inbound.status;
		// set sync fields
		if (cmi.sync) {
			if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
			inbound.fields['server.page.revision']=inbound.modified.convertToYYYYMMDDHHMM();
			inbound.fields['server.type']='file';
			inbound.fields['server.host']=(cmi.local&&!cmi.src.startsWith('file:')?'file:///':'')+cmi.src;
		}
		// do the import!
		store.suspendNotifications();
		store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
		store.resumeNotifications();
		}
	return(-1);	// signals that we really finished the entire list
}
function importStopped() {
	var cmi=config.macros.importTiddlers; // abbrev
	var list=cmi.$('importList'); if (!list) return;
	var theNewTitle=cmi.$('importNewTitle');
	if (cmi.index==-1){ 
		cmi.$('importStart').value=cmi.startText;
		importReport();	// import finished... generate the report
	} else {
		// import collision...
		// show the collision panel and set the title edit field
		cmi.$('importStart').value=cmi.stopText;
		cmi.showPanel('importCollisionPanel',true);
		theNewTitle.value=list.options[cmi.index].value;
		if (cmi.$('importApplyToAll').checked && cmi.lastAction && cmi.lastAction.id!='importRename')
			onClickImportButton(cmi.lastAction);
	}
}
//}}}
//{{{
function importReport() {
	var cmi=config.macros.importTiddlers; // abbrev
	if (!cmi.inbound) return;
	// if import was not completed, the collision panel will still be open... close it now.
	var panel=cmi.$('importCollisionPanel'); if (panel) panel.style.display='none';
	// get the alphasorted list of tiddlers
	var tiddlers = cmi.inbound;
	// gather the statistics
	var count=0; var total=0;
	for (var t=0; t<tiddlers.length; t++) {
		if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
		if (tiddlers[t].status.substr(0,7)!='skipped') count++;
		total++;
	}
	// generate a report
	if (total) displayMessage(cmi.processedMsg.format([total]));
	if (count && config.options.chkImportReport) {
		// get/create the report tiddler
		var theReport = store.getTiddler('ImportedTiddlers');
		if (!theReport) { theReport=new Tiddler(); theReport.title='ImportedTiddlers'; theReport.text=''; }
		// format the report content
		var now = new Date();
		var newText = 'On '+now.toLocaleString()+', '+config.options.txtUserName
		newText +=' imported '+count+' tiddler'+(count==1?'':'s')+' from\n[['+cmi.src+'|'+cmi.src+']]:\n';
		if (cmi.addTags && cmi.newTags.trim().length)
			newText += 'imported tiddlers were tagged with: "'+cmi.newTags+'"\n';
		newText += '<<<\n';
		for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status)
			newText += '#[['+tiddlers[t].title+']] - '+tiddlers[t].status+'\n';
		newText += '<<<\n';
		// update the ImportedTiddlers content and show the tiddler
		theReport.text	 = newText+((theReport.text!='')?'\n----\n':'')+theReport.text;
		theReport.modifier = config.options.txtUserName;
		theReport.modified = new Date();
                store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
		story.displayTiddler(null,theReport.title,1,null,null,false);
		story.refreshTiddler(theReport.title,1,true);
	}
	// reset status flags
	for (var t=0; t<cmi.inbound.length; t++) cmi.inbound[t].status='';
	// mark document as dirty and let display update as needed
	if (count) { store.setDirty(true); store.notifyAll(); }
	// always show final message when tiddlers were actually loaded
	if (count) displayMessage(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g,' ')]));
}
//}}}
//{{{
// // File and XMLHttpRequest I/O
config.macros.importTiddlers.askForFilename=function(here) {
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf('/'); if (slashpos==-1) slashpos=path.lastIndexOf('\\'); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file='';
	var result='';
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeOpen);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}

config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
	if (src==undefined || !src.length) return null; // filename is required
	var original=src; // URL as specified
	var hashpos=src.indexOf('#'); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
	clearMessage();
	displayMessage(this.openMsg.format([src.replace(/%20/g,' ')]));
	if (src.substr(0,5)!='http:' && src.substr(0,5)!='file:') { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf('/'); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf('\\'); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!='http:') src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g,' '),'(filesystem error)']));
		} else {
			displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g,' ')]));
			if (version.major+version.minor*.1+version.revision*.01!=2.52) txt=convertUTF8ToUnicode(txt);
			if (callback) callback(true,original,txt,src,null);
		}
	} else {
		doHttp('GET',src,null,null,config.options.txtRemoteUsername,config.options.txtRemotePassword,callback,original,null);
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html){
	var remoteStore=new TiddlyWiki();
	remoteStore.importTiddlyWiki(html);
	return remoteStore.getTiddlers('title');	
}

config.macros.importTiddlers.readTiddlersFromCSV=function(CSV){
	var remoteStore=new TiddlyWiki();
	// GET NAMES
	var lines=CSV.replace(/\r/g,'').split('\n');
	var names=lines.shift().replace(/"/g,'').split(',');
	CSV=lines.join('\n');
	// ENCODE commas and newlines within quoted values
	var comma='!~comma~!'; var commaRE=new RegExp(comma,'g');
	var newline='!~newline~!'; var newlineRE=new RegExp(newline,'g');
	CSV=CSV.replace(/"([^"]*?)"/g,
		function(x){ return x.replace(/\,/g,comma).replace(/\n/g,newline); });
	// PARSE lines
	var lines=CSV.split('\n');
	for (var i=0; i<lines.length; i++) { if (!lines[i].length) continue;
		var values=lines[i].split(',');
		// DECODE commas, newlines, and doubled-quotes, and remove enclosing quotes (if any)
		for (var v=0; v<values.length; v++)
			values[v]=values[v].replace(commaRE,',').replace(newlineRE,'\n')
				.replace(/^"|"$/g,'').replace(/""/g,'"');
		// EXTRACT tiddler values
		var title=''; var text=''; var tags=[]; var fields={};
		var created=null; var when=new Date(); var who=config.options.txtUserName;
		for (var v=0; v<values.length; v++) { var val=values[v];
			if (names[v]) switch(names[v].toLowerCase()) {
				case 'title':	title=val.replace(/\[\]\|/g,'_'); break;
				case 'created': created=new Date(val); break;
				case 'modified':when=new Date(val); break;
				case 'modifier':who=val; break;
				case 'text':	text=val; break;
				case 'tags':	tags=val.readBracketedList(); break;
				default:	fields[names[v].toLowerCase()]=val; break;
			}
		}
		// CREATE tiddler in temporary store
		if (title.length)
			remoteStore.saveTiddler(title,title,text,who,when,tags,fields,true,created||when);
	}
	return remoteStore.getTiddlers('title');
}

config.macros.importTiddlers.createTiddlerFromFile=function(src,txt) {
	var t=new Tiddler();
	var pos=src.lastIndexOf("/"); if (pos==-1) pos=src.lastIndexOf("\\");
	t.title=pos==-1?src:src.substr(pos+1);
	t.text=txt; 
	t.created=t.modified=new Date();
	t.modifier=config.options.txtUserName;
	if (src.substr(src.length-3,3)=='.js') t.tags=['systemConfig'];
	return [t];
}

config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr){
	var cmi=config.macros.importTiddlers; // abbreviation
	var src=src.replace(/%20/g,' ');
	if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
	cmi.all=cmi.readTiddlersFromHTML(txt);
	if (!cmi.all||!cmi.all.length) cmi.all=cmi.readTiddlersFromCSV(txt)
	if (!cmi.all||!cmi.all.length) cmi.all=cmi.createTiddlerFromFile(src,txt)
	var count=cmi.all?cmi.all.length:0;
	var querypos=src.lastIndexOf('?'); if (querypos!=-1) src=src.substr(0,querypos);
	displayMessage(cmi.foundMsg.format([count,src]));
	cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
	cmi.$('importLastFilter').value=cmi.lastFilter;
	window.refreshImportList(0);
}

config.macros.importTiddlers.filterByHash=function(src,tiddlers){
	var hashpos=src.lastIndexOf('#'); if (hashpos==-1) return tiddlers;
	var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
	var tids=[];
	var params=hash.parseParams('anon',null,true,false,false);
	for (var p=1; p<params.length; p++) {
		switch (params[p].name) {
			case 'anon':
			case 'open':
				tids.pushUnique(params[p].value);
				break;
			case 'tag':
				if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
					var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
					for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
				} else for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].isTagged(params[p].value))
						tids.pushUnique(tiddlers[t].title);
				break;
			case 'story':
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].title==params[p].value) {
						tiddlers[t].changed();
						for (var s=0; s<tiddlers[t].links.length; s++)
							tids.pushUnique(tiddlers[t].links[s]);
						break;
					}
				break;
			case 'search':
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].text.indexOf(params[p].value)!=-1)
						tids.pushUnique(tiddlers[t].title);
				break;
		}
	}
	var matches=[];
	for (var t=0; t<tiddlers.length; t++)
		if (tids.contains(tiddlers[t].title))
			matches.push(tiddlers[t]);
	displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
	config.macros.importTiddlers.lastFilter=hash;
	return matches;
}
//}}}
/***
!!!Control panel CSS
//{{{
!css
#importPanel {
	display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;
	background-color: #eee; color:#000; font-size: 8pt; line-height:110%;
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;
	padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em;
}
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }
#importPanel select { width:100%;margin:0px;font-size:8pt;line-height:110%;}
#importPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}
#importPanel .box { border:1px solid #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;-webkit-border-radius:5px;}
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }
#importPanel .rad { width:auto; }
#importPanel .chk { width:auto; margin:1px;border:0; }
#importPanel .btn { width:auto; }
#importPanel .btn1 { width:98%; }
#importPanel .btn2 { width:48%; }
#importPanel .btn3 { width:32%; }
#importPanel .btn4 { width:23%; }
#importPanel .btn5 { width:19%; }
#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }
#backstagePanel #importPanel { left:10%; right:auto; }
!end
//}}}
!!!Control panel HTML
//{{{
!html
<!-- source and report -->
<table><tr><td align=left>
	import from
	<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED
		onclick="onClickImportButton(this,event)" title="show file controls"> local file
	<input type="radio" class="rad" name="importFrom" id="importFromWeb"  value="http"
		onclick="onClickImportButton(this,event)" title="show web controls"> web server
</td><td align=right>
	<input type=checkbox class="chk" id="chkImportReport"
		onClick="config.options['chkImportReport']=this.checked;"> create report
</td></tr></table>

<div class="box" id="importSourcePanel" style="margin:.5em">
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file  -->
enter or browse for source path/filename<br>
<input type="file" id="fileImportSource" size=57 style="width:100%"
	onKeyUp="config.macros.importTiddlers.src=this.value"
	onChange="config.macros.importTiddlers.src=this.value;document.getElementById('importLoad').onclick()">
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->
	<input type="text" id="fileImportSourceFix" style="width:90%"
		title="Enter a path/file to import"
		onKeyUp="config.macros.importTiddlers.src=this.value"
		onChange="config.macros.importTiddlers.src=this.value;document.getElementById('importLoad').onclick()">
	<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."
		title="Select a path/file to import"
		onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;
			document.getElementById('fileImportSourceFix').value=r;
			config.macros.importTiddlers.src=r;
			document.getElementById('importLoad').onclick()">
</div><!--end FF3 FIXUP-->
</div><!--end local-->
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->
<table><tr><td align=left>
	enter a URL or <a href="javascript:;" id="importSelectFeed"
		onclick="return onClickImportButton(this,event)" title="select a pre-defined 'systemServer' URL">
		select a server</a><br>
</td><td align=right>
	<input type="checkbox" class="chk" id="importUsePassword"
		onClick="config.macros.importTiddlers.usePassword=this.checked;
			config.macros.importTiddlers.showPanel('importIDPWPanel',this.checked,true);">password
	<input type="checkbox" class="chk" id="importUseProxy"
		onClick="config.macros.importTiddlers.useProxy=this.checked;
			config.macros.importTiddlers.showPanel('importSiteProxy',this.checked,true);">proxy
</td></tr></table>
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"
	onKeyUp="config.macros.importTiddlers.proxy=this.value"
	onChange="config.macros.importTiddlers.proxy=this.value;">
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"
	onKeyUp="config.macros.importTiddlers.src=this.value"
	onChange="config.macros.importTiddlers.src=this.value;">
<div id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>
username: <input type=text id="txtImportID" style="width:25%" 
	onChange="config.options.txtRemoteUsername=this.value;">
 password: <input type=password id="txtImportPW" style="width:25%" 
	onChange="config.options.txtRemotePassword=this.value;">
</div><!--end idpw-->
</div><!--end http-->
</div><!--end source-->

<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">
<table><tr><td align=left>
select:
<a href="javascript:;" id="importSelectAll"
	onclick="return onClickImportButton(this)" title="SELECT all tiddlers">
	all</a>
&nbsp;<a href="javascript:;" id="importSelectNew"
	onclick="return onClickImportButton(this)" title="SELECT tiddlers not already in destination document">
	added</a>
&nbsp;<a href="javascript:;" id="importSelectChanges"
	onclick="return onClickImportButton(this)" title="SELECT tiddlers that have been updated in source document">
	changes</a>
&nbsp;<a href="javascript:;" id="importSelectDifferences"
	onclick="return onClickImportButton(this)" title="SELECT tiddlers that have been added or are different from existing tiddlers">
	differences</a>
</td><td align=right>
<a href="javascript:;" id="importListSmaller"
	onclick="return onClickImportButton(this)" title="SHRINK list size">
	&nbsp;&#150;&nbsp;</a>
<a href="javascript:;" id="importListLarger"
	onclick="return onClickImportButton(this)" title="GROW list size">
	&nbsp;+&nbsp;</a>
<a href="javascript:;" id="importListMaximize"
	onclick="return onClickImportButton(this)" title="MAXIMIZE/RESTORE list size">
	&nbsp;=&nbsp;</a>
</td></tr></table>
<select id="importList" size=8 multiple
	onchange="setTimeout('refreshImportList('+this.selectedIndex+')',1)">
	<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->
</select>
<div style="text-align:center">
	<a href="javascript:;"
		title="click for help using filters..."
		onclick="alert('A filter consists of one or more space-separated combinations of: tiddlertitle, tag:[[tagvalue]], tag:[[tag expression]] (requires MatchTagsPlugin), story:[[TiddlerName]], and/or search:[[searchtext]]. Use a blank filter to restore the list of all tiddlers.'); return false;"
	>filter</a>
	<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"
		title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."
		onfocus="this.select()" value=""
		onKeyUp="config.macros.importTiddlers.lastFilter=this.value"
		onChange="config.macros.importTiddlers.lastFilter=this.value;">
	<input type="button" id="importApplyFilter" style="width:20%" value="apply"
		title="filter list of tiddlers to include only those that match certain criteria"
		onclick="return onClickImportButton(this)">
	</div>
</div><!--end select-->

<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">
	apply tags: <input type=checkbox class="chk" id="chkImportTags" checked
		onClick="config.macros.importTiddlers.importTags=this.checked;">from source&nbsp;
	<input type=checkbox class="chk" id="chkKeepTags" checked
		onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing&nbsp;
	<input type=checkbox class="chk" id="chkAddTags" 
		onClick="config.macros.importTiddlers.addTags=this.checked;
			config.macros.importTiddlers.showPanel('txtNewTags',this.checked,false);
			if (this.checked) document.getElementById('txtNewTags').focus();">add tags<br>
	<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15 onfocus="this.select()" 
		title="enter tags to be added to imported tiddlers" 
		onKeyUp="config.macros.importTiddlers.newTags=this.value;
		document.getElementById('chkAddTags').checked=this.value.length>0;" autocomplete=off>
	<nobr><input type=checkbox class="chk" id="chkSync" 
		onClick="config.macros.importTiddlers.sync=this.checked;">
		link tiddlers to source document (for sync later)</nobr>
</div><!--end options-->

<div id="importButtonPanel" style="text-align:center">
	<input type=button id="importLoad"	class="importButton btn3" value="open"
		title="load listbox with tiddlers from source document"
		onclick="onClickImportButton(this)">
	<input type=button id="importOptions"	class="importButton btn3" value="options..."
		title="set options for tags, sync, etc."
		onclick="onClickImportButton(this)">
	<input type=button id="importStart"	class="importButton btn3" value="import"
		title="start/stop import of selected source tiddlers into current document"
		onclick="onClickImportButton(this)">
	<input type=button id="importClose"	class="importButton btn3" value="done"
		title="clear listbox or hide control panel"
		onclick="onClickImportButton(this)">
</div>

<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">
	<table><tr><td style="width:65%" align="left">
		<table><tr><td align=left>
			tiddler already exists:
		</td><td align=right>
			<input type=checkbox class="chk" id="importApplyToAll" 
			onclick="document.getElementById('importRename').disabled=this.checked;"
			checked>apply to all
		</td></tr></table>
		<input type=text id="importNewTitle" size=15 autocomplete=off">
	</td><td style="width:34%" align="center">
		<input type=button id="importMerge"
			class="importButton" style="width:47%" value="merge"
			title="append the incoming tiddler to the existing tiddler"
			onclick="onClickImportButton(this)"><!--
		--><input type=button id="importSkip"
			class="importButton" style="width:47%" value="skip"
			title="do not import this tiddler"
			onclick="onClickImportButton(this)"><!--
		--><br><input type=button id="importRename"
			class="importButton" style="width:47%" value="rename"
			title="rename the incoming tiddler"
			onclick="onClickImportButton(this)"><!--
		--><input type=button id="importReplace"
			class="importButton" style="width:47%" value="replace"
			title="discard the existing tiddler"
			onclick="onClickImportButton(this)">
	</td></tr></table>
</div><!--end collision-->
!end
//}}}
***/
 
/***
|Name|ImportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for ImportTiddlersPlugin|
Combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a source document and import selected tiddlers, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Usage
<<<
{{{<<importTiddlers>>}}} or {{{<<importTiddlers core>>}}}
invokes 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)

{{{<<importTiddlers link label tooltip>>}}}
The ''link'' keyword creates an "import tiddlers" link that when clicked to show/hide import control panel.  ''label'' and ''tooltip'' are optional text parameters (enclosed in quotes or {{{[[...]]}}}, and allow you to override the default display text for the link and the mouseover help text, respectively.

{{{<<importTiddlers inline>>}}}
creates import control panel directly in tiddler content

<<importTiddlers inline>>

Enter a document URL or press "..." to select a TiddlyWiki file to import, and then press ''[open]''.  //Note: There may be a delay before the list of tiddlers appears.//  Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time.

Select one or more titles from the listbox.  Use CTRL-click or SHIFT-click to select/deselect individual titles.  Click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list, based on a comparison of the two documents:
*''all'' selects ALL tiddlers from the import source document, even if they have not been changed.
*''new'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document
*''changes'' selects only tiddlers that exist in both documents but that are newer in the source document
*''differences'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)

Press ''[import]'' to begin copying tiddlers to the current document.  If an 'inbound' tiddler matches one that already exists in the document, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''skip'', ''rename'', ''merge'' and ''replace''.
* to bypass importing the tiddler, press ''skip''
* to give the inbound tiddler a different name, so that both the old and new tiddlers will exist when the import is done, enter a new title in the input field and press ''rename'' 
* to combine the content from both tiddlers into a single tiddler so you can then edit it later to eliminate unwanted content, press ''merge''
* to overwrite the existing tiddler with the imported one (discarding the previous content), press ''[replace]''

''Import Report History''

Whenever tiddlers are imported, a report is generated into a tiddler named [[ImportedTiddlers]], recording when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom, as well as a list of the tiddlers that were processed.  When more tiddlers are imported at a later time, a new report is //added// to the existing [[ImportedTiddlers]], above the previous report (i.e., at the top of the tiddler), so that a history of imports is maintained.  If this record is not desired, you can delete [[ImportedTiddlers]] at any time.

Note: You can prevent a report from being generated for any given import activity by clearing the "create a report" checkbox before pressing the ''import'' button
<<<
!!!!!Installation Notes
<<<
* As of 6/27/2007, support for TW2.1.x and earlier have been moved to [[ImportTiddlersPluginPatch]].  ''//Only install the patch plugin when using TW2.1.x or earlier.//''
<<<
!!!!!Revisions
<<<
2009.10.06 4.6.0 added createTiddlerFromFile (import text files)
2009.09.27 4.5.5 in readTiddlersFromCSV(), strip \r from input and fixed handling for quoted values
2009.09.12 4.5.4 fixed 'return false' to prevent IE page transition. Also, moved html/css definitions to separate sections
2009.08.23 4.5.3 in importTiddlers(), add 'file:///' to local server.host sync field only if not already present in URL
2009.08.20 4.5.2 only use SiteURL/SiteProxy values if control panel value has not yet been set
2009.07.03 4.5.1 fixups for TW252: doHttp() doesn't return XHR and convertUTF8ToUnicode() not needed for local I/O
2009.05.04 4.5.0 import from CSV-formatted files
2009.03.04 4.4.2 in createImportPanel(), init option checkboxes so display matches internal state variables
2009.02.26 4.4.1 use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
2008.09.30 4.4.0 added fallback definition of merge() for use with TW2.0.x and TW1.2.x
2008.08.12 4.3.3 rewrite backstage and shadow tiddler definitions for easier customization
2008.08.05 4.3.2 rewrote loadRemoteFile() to eliminate use of platform-specific fileExists() function
2008.06.29 4.3.1 More layout/animation work for simpler sequential interaction.  Code reduction/cleanup
2008.06.28 4.3.0 HTML and CSS cleanup and tweaks to layout.  Added animation to panels
2008.06.22 4.2.0 For FireFox, use HTML with separate text+button control instead of type='file' control
2008.06.05 4.1.0 in filterByHash(), added support for boolean tag expressions using getMatchingTiddlers() (defined by MatchTagsPlugin)
2008.05.12 4.0.2 automatically tweak the backstage "import" task to add the ImportTiddlers control panel
2008.04.30 4.0.1 trim #... suffix for loading files/URLs in IE
2008.04.30 4.0.0 added source filtering (using URL paramifiers).  Also, abbreviations for code-size reduction.
2008.04.13 3.9.0 added 'apply to all' checkbox for collision processing
2008.03.26 3.8.0 added support for selecting pre-defined systemServer URLs
2008.03.25 3.7.0 added support for setting 'server' fields on imported tiddlers (for later synchronizing of changes)
2008.01.03 3.6.0 in loadRemoteFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.10.30 3.5.6 update [[ImportTiddlers]] shadow tiddler definition to include "inline" link
2007.06.27 3.5.5 added missing 'fields' params to saveTiddler() calls.  Fixes problem where importing tiddlers would lose the custom fields.  Also, moved functions for TW2.1.x to [[ImportTiddlersPluginPatch2.1.x]].
2007.06.25 3.5.4 added calls to store.suspendNotifications() and store.resumeNotifications().  Eliminates redisplay processing overhead DURING import activities
2007.04.29 3.5.3 in refreshImportList() when inbound tiddlers are loaded, change "close" button to "done", and disable certain controls to creates a modal condition, so that actions that reload tiddlers cannot be performed unless "done" is first pressed to end the mode..
2007.04.28 3.5.2 in handler(), added param support for custom link label/prompt
2007.04.19 3.5.1 in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content.  Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.03.22 3.5.0 in refreshImportList(), add handling for 'select section' when a heading is selected.  Makes it really easy to import by tag or date!
2007.03.21 3.4.0 split loadTiddlers functionality into separate plugin (see [[LoadTiddlersPlugin]])
2007.03.20 3.3.1 tweak to previous change to allow relative file references via http: (bypasses getLocalPath() so remote URL will be used)
2007.03.20 3.3.0 added support for local, relative file references: in loadRemoteFile(), check for fileExists().  If not found, prepend relative path and retry.
2007.02.24 3.2.1 re-labeled control panel "open" button to "load"
2007.02.09 3.2.0 loadTiddlers: added support for "noReload" tag (prevents overwriting existing tiddler, even if inbound tiddler is newer)
2007.02.08 3.1.3 loadTiddlers: added missing code and documentation for "newTags" handling (a feature change from long, long ago that somehow got lost!)
2006.11.14 3.1.2 fix macro handler parameter declaration (double-pasted param list corrupts IE)
2006.11.13 3.1.1 use apply() method to invoke hijacked core handler
2006.11.13 3.1.0 hijack built-in importTiddlers.handler() to co-exist with plugin interface.  If no params or 'core' keyword, display core interface.  "link" param embeds "import tiddlers" link that shows floating panel when clicked.
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)
2006.09.10 3.0.7 in readTiddlersFromHTML(), find end of store area by matching "POST-BODY-START" instead of "/body" 
2006.08.16 3.0.6 Use higher-level store.saveTiddler() instead of store.addTiddler() to avoid conflicts with adaptations that hijack low-level tiddler handling.  in CreateImportPanel(), removed "refresh listbox after every tiddler change".
2006.07.29 3.0.5 added noChangeMsg to loadTiddlers processing.  if not 'quiet' mode, reports skipped tiddlers.
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)
2006.04.12 3.0.3 moved many display messages to macro properties for easier L10N translations via 'lingo' definitions.
2006.04.12 3.0.2 more work on '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.
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
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.  Removed support for "importReplace/importPublic" tags and "force" param (unused feature). 
2006.03.30 2.9.1 when extracting store area from remote URL, look for "</body>" instead of "</body>\n</html>" so it will match even if the "\n" is absent from the source.
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.
2006.03.28 2.8.1 in loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (not in IE). Also, when extracting store area, look for "</body>\n</html>" and omit extra content that may have been added to the end of the file.
2006.02.21 2.8.0 added support for "tiddler:TiddlerName" filtering parameter in auto-import processing
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)
2006.02.21 2.7.0 Added "local file" and "web server" radio buttons.  Default remote URL uses value from [[SiteURL]].  Also, added 'proxy' option, using value from [[SiteProxy]] as prefix to permit cross-domain document access via server-side scripting.
2006.02.17 2.6.0 Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences.  fixed init of "add new tags" checkbox
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.
2006.02.14 2.5.3 FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()
2006.02.10 2.5.2 corrected unintended global variable in importReport().
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
2006.01.18 2.5.0 added checkbox for "create a report".  Default is to create/update the ImportedTiddlers report.
2006.01.15 2.4.1 added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic
2006.01.15 2.4.0 Added support for tagging tiddlers with importSkip, importReplace, and/or importPrivate to enable/disable overwriting or sharing with others when using auto-import macro syntax.  Defaults: don't overwrite existing tiddlers, and allow your tiddlers to be auto-imported by others.
2006.01.15 2.3.2 Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)
2006.01.15 2.3.1 Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME to prevent imported document's core code from being invoked.  Also, when importing local documents, use convertUTF8ToUnicode() to support international characters sets.
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 instead of waiting for remote hosts to respond to URL requests.  Added non-interactive 'batch' mode, using macro parameters to specify source path/file or URL, and select tiddlers to import.  Improved messages and added optional 'quiet' switch for batch mode to eliminate //most// feedback.
2006.01.11 2.2.0 Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck
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.
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.
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.
2005.12.27 2.0.0 Update for TW2.0
Defer initial panel creation and only register a notification function when panel first is created
2005.12.22 1.3.1 tweak formatting in importReport() and add 'discard report' link to output
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)
2005.11.29 1.2.1 fixed formatting of 'detail info' in importReport()
2005.11.11 1.2.0 added 'inline' param to embed controls in a tiddler
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.
2005.10.25 1.0.5 fixed typo in importReport() that prevented reports from being generated
2005.10.09 1.0.4 combined documentation with plugin code instead of using separate tiddlers
2005.08.05 1.0.3 moved CSS and HTML definitions into plugin code instead of using separate tiddlers
2005.07.27 1.0.2 core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()
2005.07.23 1.0.1 added parameter checks and corrected addNotification() usage
2005.07.20 1.0.0 Initial Release
<<<
On Sunday, August 08, 2010 15:28:52, JohnRouillard imported 75 tiddlers from
[[C:\Users\rouilj\Documents\coursebook\CoursebookV2.html|C:\Users\rouilj\Documents\coursebook\CoursebookV2.html]]:
<<<
#[[BookmarkList]] - replaces BookmarkList - 7/18/2010 22:38:00 by JohnRouillard
#[[Bugs And Feature Requests]] - replaces Bugs And Feature Requests - 7/27/2010 01:13:00 by YourName
#[[Changing the Style Sheet]] - added
#[[Chapter  1 - Types of Presentations]] - added
#[[Chapter  1 - Working with Presentations]] - replaces Chapter  1 - Working with Presentations - 7/18/2010 16:56:00 by JohnRouillard
#[[Chapter  2 - Chapters Defined]] - added
#[[Chapter  2 - Working with Chapters]] - added
#[[Chapter  3 - Non-tiddlywiki publication options]] - added
#[[Chapter  3 - Other Publication Options]] - added
#[[Chapter creation]] - replaces Chapter creation - 7/25/2010 16:13:00 by YourName
#[[ChapterList]] - replaces ChapterList - 7/23/2010 19:45:00 by JohnRouillard
#[[Creating Chapter Content]] - added
#[[Creating Chapter Content as Separate Tiddlers]] - added
#[[Creating Chapter Content as Single Large Tiddler]] - added
#[[Creating Chapter Content as Single Tiddler and Split Into Multiple Tiddlers]] - added
#[[Creating PDF's]] - added
#[[Creating Quizzes]] - added
#[[Creating Reference Tiddlers]] - added
#[[Creating a New Chapter from an Existing Tiddler]] - added
#[[Creating a Presentation]] - replaces Creating a Presentation - 7/18/2010 18:21:00 by YourName
#[[Creating visual html]] - added
#[[Credits]] - replaces Credits - 7/4/2010 21:44:00 by JohnRouillard
#[[FileDropPlugin]] - replaces FileDropPlugin - 3/8/2010 14:28:00 by ELSDesignStudios
#[[FileDropPluginConfig]] - replaces FileDropPluginConfig - 8/12/2008 00:41:00 by ELSDesignStudios
#[[Frontscreen.png]] - replaces Frontscreen.png - 10/24/2009 17:53:00 by JohnRouillard
#[[GettingStarted]] - replaces GettingStarted - 7/18/2010 17:51:00 by JohnRouillard
#[[GettingStarted - LISA]] - replaces GettingStarted - LISA - 7/18/2010 17:56:00 by JohnRouillard
#[[Glossary]] - replaces Glossary - 7/27/2010 01:12:00 by YourName
#[[How to Create Additional Content]] - added
#[[How to Create a Chapter]] - added
#[[IconsSource]] - replaces IconsSource - 7/26/2010 23:20:00 by YourName
#[[ImagePathList]] - replaces ImagePathList - 7/26/2010 23:23:00 by YourName
#[[InstructorSidebarFunctions]] - replaces InstructorSidebarFunctions - 7/31/2010 01:31:00 by JohnRouillard
#[[MainMenu]] - replaces MainMenu - 7/17/2010 00:57:00 by JohnRouillard
#[[Opening a Chapter]] - added
#[[Opening a Presentation]] - replaces Opening a Presentation - 7/18/2010 16:13:00 by JohnRouillard
#[[Opening the Coursebook]] - replaces Opening the Coursebook - 10/31/2009 22:49:00 by JohnRouillard
#[[Printing]] - replaces Printing - 7/25/2010 16:30:00 by YourName
#[[Printing Chapters]] - added
#[[Printing Slide Set]] - replaces Printing Slide Set - 7/18/2010 17:25:00 by JohnRouillard
#[[QuizList]] - replaces QuizList - 8/25/2009 23:00:00 by JohnRouillard
#[[ReadMe]] - replaces ReadMe - 7/31/2010 03:13:00 by JohnRouillard
#[[Reference Appendix 1 - TiddlyWiki Page Layout]] - added
#[[Reference Appendix 1 - Working with a TiddlyWiki]] - added
#[[SideBarOptions]] - replaces SideBarOptions - 7/31/2010 01:32:00 by JohnRouillard
#[[SiteStartup]] - replaces SiteStartup - 7/18/2010 15:56:00 by JohnRouillard
#[[Slide Tips]] - replaces Slide Tips - 7/27/2010 01:12:00 by YourName
#[[SlideSubstyle]] - replaces SlideSubstyle - 7/31/2010 03:25:00 by JohnRouillard
#[[Splitting Chapters]] - replaces Splitting Chapters - 8/29/2009 20:22:00 by JohnRouillard
#[[Tagging a Chapter]] - added
#[[Textbook]] - replaces Textbook - 7/25/2010 14:55:00 by YourName
#[[TiddlyWiki Page Layout (Instructor)]] - added
#[[ToolbarCommands]] - replaces ToolbarCommands - 7/4/2010 21:02:00 by JohnRouillard
#[[Using This Tiddlywiki]] - replaces Using This Tiddlywiki - 7/11/2010 20:55:00 by YourName
#[[Using the Backstage Link]] - added
#[[Using the Content Links in the Main Menu]] - added
#[[Welcome to the presentation]] - replaces Welcome to the presentation - 7/18/2010 17:33:00 by JohnRouillard
#[[WelcomeSlide]] - replaces WelcomeSlide - 7/18/2010 17:30:00 by JohnRouillard
#[[Working with Tiddlers]] - added
#[[block-icon.png]] - added
#[[bookmark-icon.png]] - added
#[[bubble-icon.png]] - added
#[[clipboard-icon.png]] - added
#[[delete-icon.png]] - added
#[[editModeTiddler.png]] - added
#[[flag-icon.png]] - added
#[[goal.jpg]] - added
#[[info-icon.png]] - added
#[[label-icon.png]] - added
#[[pageLayout.png]] - added
#[[pencil-icon.png]] - added
#[[search-icon.png]] - added
#[[tick-icon.png]] - added
#[[viewModeTiddler.png]] - added
#[[warning-icon.png]] - added
<<<

----
On Saturday, July 31, 2010 3:29:26 AM, JohnRouillard imported 5 tiddlers from
[[C:\Documents and Settings\rouilj\My Documents\coursebook\CoursebookV2.html|C:\Documents and Settings\rouilj\My Documents\coursebook\CoursebookV2.html]]:
<<<
#[[Goals]] - replaces Goals - 7/31/2010 01:17:00 by JohnRouillard
#[[Notebook]] - replaces Notebook - 7/25/2010 15:00:00 by YourName
#[[Quizzes]] - replaces Quizzes - 7/25/2010 14:57:00 by YourName
#[[ReadMe]] - replaces ReadMe - 7/31/2010 01:32:00 by JohnRouillard
#[[SlideSubstyle]] - replaces SlideSubstyle - 7/31/2010 02:51:00 by JohnRouillard
<<<

----
On Saturday, July 31, 2010 2:57:23 AM, JohnRouillard imported 8 tiddlers from
[[C:\Documents and Settings\rouilj\My Documents\coursebook\CoursebookV2.html|C:\Documents and Settings\rouilj\My Documents\coursebook\CoursebookV2.html]]:
<<<
#[[Goals]] - replaces Goals - 7/29/2010 21:32:00 by JohnRouillard
#[[InstructorSidebarFunctions]] - added
#[[Presentations]] - replaces Presentations - 7/29/2010 20:46:00 by JohnRouillard
#[[ReadMe]] - replaces ReadMe - 7/26/2010 23:27:00 by YourName
#[[SideBarOptions]] - replaces SideBarOptions - 7/11/2010 21:16:00 by YourName
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 7/29/2010 21:31:00 by JohnRouillard
#[[SlideSubstyle]] - replaces SlideSubstyle - 7/29/2010 21:14:00 by JohnRouillard
#[[presentationViewTemplate]] - replaces presentationViewTemplate - 7/11/2010 21:12:00 by YourName
<<<

----
On Sunday, July 18, 2010 10:34:49 PM, JohnRouillard imported 1 tiddler from
[[http://www.minormania.com/tiddlylock/tiddlylock.html|http://www.minormania.com/tiddlylock/tiddlylock.html]]:
<<<
#[[TiddlyLockPlugin]] - replaces TiddlyLockPlugin - 7/18/2010 22:17:00 by YourName
<<<

----
On Sunday, July 11, 2010 20:33:58, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SaveToClipboard]] - added
<<<

----
On Monday, July 05, 2010 15:32:52, JohnRouillard imported 1 tiddler from
[[http://tw.lewcid.org/#ToggleSideBarMacro|http://tw.lewcid.org/#ToggleSideBarMacro]]:
<<<
#[[ToggleSideBarMacro]] - replaces ToggleSideBarMacro - 3/30/2009 17:03:00 by PauloSoares
<<<

----
On Monday, July 05, 2010 13:57:16, JohnRouillard imported 3 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 8/30/2009 14:32:00 by JohnRouillard
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 4/19/2009 14:44:00 by PauloSoares
#[[ToggleSideBarMacro]] - replaces ToggleSideBarMacro - 7/24/2006 06:18:00 by Saq
<<<

----
On Monday, July 05, 2010 13:45:59, JohnRouillard imported 7 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[ExportTiddlersPlugin]] - replaces ExportTiddlersPlugin - 9/12/2009 21:02:00 by ELSDesignStudios
#[[ExportTiddlersPluginInfo]] - replaces ExportTiddlersPluginInfo - 4/30/2009 18:14:00 by ELSDesignStudios
#[[FileDropPlugin]] - replaces FileDropPlugin - 10/10/2009 15:57:00 by ELSDesignStudios
#[[MatchTagsPlugin]] - replaces MatchTagsPlugin - 8/30/2009 19:56:00 by ELSDesignStudios
#[[MatchTagsPluginInfo]] - replaces MatchTagsPluginInfo - 8/30/2009 19:55:00 by ELSDesignStudios
#[[ShowImage]] - added
#[[SplitTiddler]] - replaces SplitTiddler - 8/16/2009 21:01:00 by JohnRouillard
<<<

----
On Sunday, July 04, 2010 9:43:42 PM, JohnRouillard imported 1 tiddler from
[[C:\Documents and Settings\rouilj\My Documents\sec_class\SEC_tw_inst.html|C:\Documents and Settings\rouilj\My Documents\sec_class\SEC_tw_inst.html]]:
<<<
#[[Credits]] - added
<<<

----
On Saturday, October 24, 2009 4:57:38 PM, JohnRouillard imported 4 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SaveAsPlugin]] - replaces SaveAsPlugin - 8/16/2009 15:43:00 by ELSDesignStudios
#[[SaveAsPluginInfo]] - replaces SaveAsPluginInfo - 8/16/2009 15:43:00 by ELSDesignStudios
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 8/29/2009 22:03:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 8/29/2009 22:03:00 by ELSDesignStudios
<<<

----
On Sunday, October 11, 2009 10:19:33 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[WikifyPlugin]] - added
#[[WikifyPluginInfo]] - added
<<<

----
On Sunday, October 11, 2009 8:17:50 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[SnapshotPlugin]] - added
#[[SnapshotPluginInfo]] - added
<<<

----
On Saturday, October 10, 2009 11:21:36 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/faq.html|http://www.tiddlytools.com/faq.html]]:
<<<
#[[FAQ_RescueStoreArea]] - replaces FAQ_RescueStoreArea - 3/31/2008 18:37:00 by ELSDesignStudios
<<<

----
On Saturday, October 10, 2009 9:59:52 PM, JohnRouillard imported 3 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[AttachFilePluginFormatters]] - replaces AttachFilePluginFormatters - 6/4/2009 14:33:00 by ELSDesignStudios
#[[FileDropPlugin]] - replaces FileDropPlugin - 10/8/2009 23:56:00 by ELSDesignStudios
#[[ToggleFullScreen]] - replaces ToggleFullScreen - 10/10/2009 11:50:00 by JohnRouillard
<<<

----
On Saturday, October 10, 2009 11:49:03 AM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[ToggleFullScreen]] - added
<<<

----
On Friday, October 09, 2009 10:37:27 PM, JohnRouillard imported 8 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[FileDropPlugin]] - replaces FileDropPlugin - 8/21/2009 00:36:00 by ELSDesignStudios
#[[ImportTiddlersPlugin]] - replaces ImportTiddlersPlugin - 9/12/2009 21:09:00 by ELSDesignStudios
#[[ImportTiddlersPluginInfo]] - replaces ImportTiddlersPluginInfo - 8/23/2009 18:55:00 by ELSDesignStudios
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 9/1/2009 19:19:00 by ELSDesignStudios
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 9/1/2009 19:18:00 by ELSDesignStudios
#[[RelatedTiddlersPlugin]] - replaces RelatedTiddlersPlugin - 11/11/2007 02:26:00 by ELSDesignStudios
#[[TiddlerTweakerPlugin]] - replaces TiddlerTweakerPlugin - 9/13/2009 13:33:00 by ELSDesignStudios
#[[ToggleFullScreen]] - replaces ToggleFullScreen - 9/6/2009 22:22:00 by JohnRouillard
<<<

----
On Tuesday, October 06, 2009 10:17:15 PM, JohnRouillard imported 2 tiddlers from
[[http://tiddlytagmindmap.tiddlyspot.com/|http://tiddlytagmindmap.tiddlyspot.com/]]:
<<<
#[[TiddlyTagMindMapPlugin]] - added
#[[VismoLibrary]] - added
<<<

----
On Sunday, September 13, 2009 2:01:22 PM, JohnRouillard imported 4 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[AliasPlugin]] - replaces AliasPlugin - 3/22/2007 01:36:00 by ELSDesignStudios
#[[ExportTiddlersPlugin]] - replaces ExportTiddlersPlugin - 7/6/2009 11:02:00 by ELSDesignStudios
#[[ImportTiddlersPlugin]] - replaces ImportTiddlersPlugin - 8/23/2009 18:55:00 by ELSDesignStudios
#[[ShowPopup]] - replaces ShowPopup - 8/13/2009 14:59:00 by ELSDesignStudios
<<<

----
On Sunday, September 13, 2009 1:48:21 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[TiddlerTweakerPlugin]] - replaces TiddlerTweakerPlugin - 6/26/2009 07:28:00 by ELSDesignStudios
<<<

----
On Saturday, September 12, 2009 7:24:14 PM, JohnRouillard imported 1 tiddler from
[[C:\Documents and Settings\rouilj\My Documents\sec_class\SEC_tw.html|C:\Documents and Settings\rouilj\My Documents\sec_class\SEC_tw.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 9/12/2009 16:50:00 by JohnRouillard
<<<

----
On Saturday, September 12, 2009 5:33:09 PM, JohnRouillard imported 1 tiddler from
[[http://sidebarpluginvault.tiddlyspot.com/|http://sidebarpluginvault.tiddlyspot.com/]]:
<<<
#[[BetterTimelineMacroMG]] - added
<<<

----
On Thursday, September 10, 2009 12:08:17 AM, JohnRouillard imported 1 tiddler from
[[http://devpad.tiddlyspot.com/|http://devpad.tiddlyspot.com/]]:
<<<
#[[TaggedBackupsPlugin]] - added
<<<

----
On Tuesday, September 08, 2009 4:55:58 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[AttachFilePluginFormatters]] - replaces AttachFilePluginFormatters - 6/4/2009 14:33:00 by ELSDesignStudios
<<<

----
On Monday, September 07, 2009 3:30:54 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/faq.html|http://www.tiddlytools.com/faq.html]]:
<<<
#[[FAQ_RescueStoreArea]] - added
<<<

----
On Monday, September 07, 2009 3:28:25 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[RescueStoreAreaCommand]] - added
<<<

----
On Sunday, September 06, 2009 3:32:09 PM, JohnRouillard imported 1 tiddler from
[[http://www.math.ist.utl.pt/~psoares/addons_2.4.html|http://www.math.ist.utl.pt/~psoares/addons_2.4.html]]:
<<<
#[[QuizzerPluginDoc]] - replaces QuizzerPluginDoc - 9/6/2009 15:30:40 by JohnRouillard
<<<

----
On Sunday, September 06, 2009 3:27:21 PM, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons_2.4.html|http://www.math.ist.utl.pt/~psoares/addons_2.4.html]]:
<<<
#[[QuizzerPlugin - fcs]] - renamed from QuizzerPlugin
#[[QuizzerPluginDoc - fcs]] - renamed from QuizzerPluginDoc
<<<

----
On Sunday, September 06, 2009 3:16:30 PM, JohnRouillard imported 1 tiddler from
[[http://www.orst.edu/~woodswa/tiddlywikiplugs.html|http://www.orst.edu/~woodswa/tiddlywikiplugs.html]]:
<<<
#[[DisplayOpenTiddlersPlugin]] - replaces DisplayOpenTiddlersPlugin - 9/6/2009 15:13:38 by JohnRouillard
<<<

----
On Friday, September 04, 2009 8:29:39 PM, JohnRouillard imported 1 tiddler from
[[http://www.linux-lovers.be/RevisionsPlugin/#RevisionsPlugin|http://www.linux-lovers.be/RevisionsPlugin/#RevisionsPlugin]]:
<<<
#[[RevisionsPlugin]] - replaces RevisionsPlugin - 9/4/2009 20:29:16 by JohnRouillard
<<<

----
On Friday, September 04, 2009 9:43:21 AM, JohnRouillard imported 1 tiddler from
[[http://tiddlywiki.abego-software.de/|http://tiddlywiki.abego-software.de/]]:
<<<
#[[YourSearchPlugin]] - replaces YourSearchPlugin - 4/16/2008 05:08:00 by UdoBorkowski
<<<

----
On Thursday, September 03, 2009 9:34:38 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[RelatedTiddlersPlugin]] - replaces RelatedTiddlersPlugin - 8/25/2009 00:15:00 by JohnRouillard
<<<

----
On Thursday, September 03, 2009 9:31:55 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[TiddlerTweakerPlugin]] - replaces TiddlerTweakerPlugin - 8/16/2009 21:02:00 by JohnRouillard
<<<

----
On Thursday, September 03, 2009 9:28:56 PM, JohnRouillard imported 4 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[InlineJavascriptPlugin]] - replaces InlineJavascriptPlugin - 4/12/2009 01:17:00 by ELSDesignStudios
#[[InlineJavascriptPluginInfo]] - replaces InlineJavascriptPluginInfo - 8/22/2009 17:56:00 by JohnRouillard
#[[TaggedTemplateTweak]] - replaces TaggedTemplateTweak - 7/31/2009 14:48:00 by ELSDesignStudios
#[[TaggedTemplateTweakInfo]] - replaces TaggedTemplateTweakInfo - 7/31/2009 14:45:00 by ELSDesignStudios
<<<

----
On Tuesday, September 01, 2009 7:56:09 PM, JohnRouillard imported 4 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[MatchTagsPlugin]] - replaces MatchTagsPlugin - 8/30/2009 19:56:00 by ELSDesignStudios
#[[MatchTagsPluginInfo]] - replaces MatchTagsPluginInfo - 8/30/2009 19:55:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 8/29/2009 22:03:00 by ELSDesignStudios
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 8/29/2009 22:03:00 by ELSDesignStudios
<<<

----
On Tuesday, September 01, 2009 7:42:42 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[LoadTiddlersPlugin]] - added
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 8/30/2009 23:01:00 by ELSDesignStudios
<<<

----
On Sunday, August 30, 2009 11:33:15 PM, JohnRouillard imported 4 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 8/29/2009 19:56:00 by ELSDesignStudios
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 8/29/2009 19:56:00 by ELSDesignStudios
#[[MatchTagsPlugin]] - replaces MatchTagsPlugin - 9/4/2008 12:45:00 by ELSDesignStudios
#[[MatchTagsPluginInfo]] - replaces MatchTagsPluginInfo - 9/4/2008 01:36:00 by ELSDesignStudios
<<<

----
On Sunday, August 30, 2009 4:01:44 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[CompareTiddlersPlugin]] - replaces CompareTiddlersPlugin - 8/30/2009 15:59:26 by JohnRouillard
<<<

----
On Sunday, August 30, 2009 1:03:13 PM, JohnRouillard imported 4 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 8/23/2009 23:27:00 by ELSDesignStudios
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 8/23/2009 23:27:00 by ELSDesignStudios
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 8/29/2009 19:56:00 by ELSDesignStudios
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 8/29/2009 19:56:00 by ELSDesignStudios
<<<

----
On Saturday, August 29, 2009 10:31:34 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 8/19/2009 16:53:00 by ELSDesignStudios
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 8/19/2009 16:53:00 by ELSDesignStudios
<<<

----
On Saturday, August 29, 2009 7:09:36 PM, JohnRouillard imported 1 tiddler from
[[http://tiddlywiki.abego-software.de|http://tiddlywiki.abego-software.de]]:
<<<
#[[YourSearchPlugin]] - replaces YourSearchPlugin - 8/29/2009 13:39:00 by YourName
<<<

----
On Saturday, August 29, 2009 5:38:27 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 8/29/2009 16:52:00 by JohnRouillard
<<<

----
On Friday, August 28, 2009 10:19:36 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StickyPopupPlugin]] - added
<<<

----
On Friday, August 28, 2009 8:09:32 PM, JohnRouillard imported 1 tiddler from
[[http://mptw.tiddlyspot.com/|http://mptw.tiddlyspot.com/]]:
<<<
#[[HideWhenPlugin]] - added
<<<

----
On Monday, August 24, 2009 8:46:36 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[AliasPlugin]] - added
<<<

----
On Monday, August 24, 2009 8:37:15 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[QuickEditPlugin]] - added
<<<

----
On Monday, August 24, 2009 8:15:48 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[QuickEdit_convert]] - added
<<<

----
On Monday, August 24, 2009 3:09:20 PM, JohnRouillard imported 4 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 8/21/2009 15:44:00 by ELSDesignStudios
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 8/21/2009 15:44:00 by ELSDesignStudios
#[[ImportTiddlersPluginInfo]] - replaces ImportTiddlersPluginInfo - 8/21/2009 03:49:00 by ELSDesignStudios
#[[ImportTiddlersPlugin]] - replaces ImportTiddlersPlugin - 8/21/2009 03:59:00 by ELSDesignStudios
<<<

----
On Saturday, August 22, 2009 11:51:20 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 8/22/2009 18:08:00 by ELSDesignStudios
<<<

----
On Saturday, August 22, 2009 8:50:19 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 8/14/2009 11:27:00 by ELSDesignStudios
<<<

----
On Friday, August 21, 2009 4:28:30 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 7/27/2009 22:27:00 by ELSDesignStudios
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 8/21/2009 14:57:00 by JohnRouillard
<<<

----
On Friday, August 21, 2009 1:47:22 PM, JohnRouillard imported 1 tiddler from
[[http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html|http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html]]:
<<<
#[[InlineJavascriptPluginInfo]] - added
<<<

----
On Friday, August 21, 2009 1:45:05 PM, JohnRouillard imported 3 tiddlers from
[[http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html|http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html]]:
<<<
#[[ImportTiddlersPlugin]] - replaces ImportTiddlersPlugin - 7/3/2009 18:32:00 by ELSDesignStudios
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 8/2/2009 05:18:00 by ELSDesignStudios
#[[InlineJavascriptPlugin]] - replaces InlineJavascriptPlugin - 2/26/2009 16:09:00 by ELSDesignStudios
<<<

----
On Friday, August 21, 2009 1:44:02 PM, JohnRouillard imported 4 tiddlers from
[[http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html|http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html]]:
<<<
#[[ImportTiddlersPlugin]] - skipped after asking
#[[ImportTiddlersPluginInfo]] - replaces ImportTiddlersPluginInfo - 5/4/2009 20:26:00 by ELSDesignStudios
#[[FileDropPlugin]] - replaces FileDropPlugin - 12/3/2007 15:22:00 by ELSDesignStudios
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 8/16/2009 18:24:00 by ELSDesignStudios
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 8/16/2009 18:24:00 by ELSDesignStudios
<<<

----
On Sunday, August 16, 2009 8:12:21 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 5/4/2009 20:08:00 by ELSDesignStudios
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 7/3/2009 18:32:00 by ELSDesignStudios
<<<

----
On Sunday, August 16, 2009 4:07:28 PM, JohnRouillard imported 3 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SaveAsPluginInfo]] - replaces SaveAsPluginInfo - 8/4/2009 16:00:00 by ELSDesignStudios
#[[SaveAsPlugin]] - replaces SaveAsPlugin - 8/4/2009 16:01:00 by ELSDesignStudios
#[[SplitTiddler]] - replaces SplitTiddler - 8/16/2009 00:19:00 by ELSDesignStudios
<<<

----
On Sunday, August 16, 2009 12:56:03 AM, JohnRouillard imported 1 tiddler from
[[http://www.orst.edu/~woodswa/tiddlywikiplugs.html|http://www.orst.edu/~woodswa/tiddlywikiplugs.html]]:
<<<
#[[DisplayOpenTiddlersPlugin]] - replaces DisplayOpenTiddlersPlugin - 8/4/2009 22:43:00 by JohnRouillard
<<<

----
On Sunday, August 16, 2009 12:23:28 AM, JohnRouillard loaded 1 tiddlers from
[[http://www.TiddlyTools.com/|http://www.TiddlyTools.com/]]:
<<<
#[[SplitTiddler]] - updated
<<<

----
On Sunday, August 16, 2009 12:14:29 AM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/15/2009 23:39:00 by ELSDesignStudios
<<<

----
On Saturday, August 15, 2009 11:50:16 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/14/2009 21:14:00 by JohnRouillard
<<<

----
On Saturday, August 15, 2009 8:17:20 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[ToggleFullScreen]] - added
<<<

----
On Friday, August 14, 2009 9:40:22 AM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/13/2009 21:07:00 by ELSDesignStudios
<<<

----
On Thursday, August 13, 2009 9:27:25 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/13/2009 21:15:34 by JohnRouillard
<<<

----
On Thursday, August 13, 2009 9:15:03 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/13/2009 21:13:38 by JohnRouillard
<<<

----
On Thursday, August 13, 2009 8:07:41 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/13/2009 20:06:46 by JohnRouillard
<<<

----
On Thursday, August 13, 2009 3:19:40 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/1/2009 22:59:00 by ELSDesignStudios
#[[ShowPopup]] - replaces ShowPopup - 8/12/2009 22:12:00 by YourName
<<<

----
On Tuesday, August 11, 2009 2:27:31 PM, JohnRouillard imported 1 tiddler from
[[http://tiddlywiki.com/beta/BetaUpgradePlugin.html|http://tiddlywiki.com/beta/BetaUpgradePlugin.html]]:
<<<
#[[BetaUpgradePlugin]] - added
<<<

----
On Saturday, August 08, 2009 4:26:38 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 8/8/2009 16:18:34 by JohnRouillard
<<<

----
On Saturday, August 08, 2009 4:24:08 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[ShowPopup]] - replaces ShowPopup - 8/1/2009 21:44:00 by JohnRouillard
<<<

----
On Friday, August 07, 2009 11:04:28 PM, YourName imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[RearrangeTiddlersPlugin]] - added
<<<

----
On Friday, August 07, 2009 10:15:04 PM, YourName imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[ImagePathPlugin]] - replaces ImagePathPlugin - 8/7/2009 22:13:00 by YourName
<<<

----
On Thursday, August 06, 2009 12:15:00 AM, YourName imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[RelatedTiddlersPlugin]] - added
<<<

----
On Tuesday, August 04, 2009 4:52:48 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SaveAsPlugin]] - replaces SaveAsPlugin - 8/3/2009 19:01:00 by ELSDesignStudios
#[[SaveAsPluginInfo]] - replaces SaveAsPluginInfo - 8/3/2009 18:45:00 by ELSDesignStudios
<<<

----
On Tuesday, August 04, 2009 4:48:44 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SaveAsPlugin]] - replaces SaveAsPlugin - 8/3/2009 23:01:00 by JohnRouillard
#[[SaveAsPluginInfo]] - replaces SaveAsPluginInfo - 8/3/2009 18:45:00 by ELSDesignStudios
<<<

----
On Tuesday, August 04, 2009 3:21:44 PM, JohnRouillard imported 1 tiddler from
[[http://oregonstate.edu/~woodswa/tiddlywikiplugs.html|http://oregonstate.edu/~woodswa/tiddlywikiplugs.html]]:
<<<
#[[DisplayOpenTiddlersPlugin]] - added
<<<

----
On Monday, August 03, 2009 10:39:36 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SaveAsPlugin]] - replaces SaveAsPlugin - 7/4/2009 01:19:00 by ELSDesignStudios
#[[SaveAsPluginInfo]] - replaces SaveAsPluginInfo - 4/30/2009 15:52:00 by ELSDesignStudios
<<<

----
On Sunday, August 02, 2009 3:28:32 PM, JohnRouillard imported 1 tiddler from
[[http://visualtw.ouvaton.org/VisualTW.html|http://visualtw.ouvaton.org/VisualTW.html]]:
<<<
#[[FieldsEditorPlugin]] - replaces FieldsEditorPlugin - 7/5/2009 00:24:00 by JohnRouillard
<<<

----
On Sunday, August 02, 2009 3:25:35 PM, JohnRouillard imported 1 tiddler from
[[http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html|http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html]]:
<<<
#[[CompareTiddlersPlugin]] - replaces CompareTiddlersPlugin - 7/28/2009 00:31:00 by YourName
<<<

----
On Sunday, August 02, 2009 1:00:23 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 8/1/2009 15:35:00 by ELSDesignStudios
<<<

----
On Sunday, August 02, 2009 12:55:52 AM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 7/6/2009 09:10:00 by ELSDesignStudios
#[[SplitTiddler]] - replaces SplitTiddler - 8/1/2009 20:26:00 by JohnRouillard
<<<

----
On Saturday, August 01, 2009 2:11:06 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 7/25/2009 15:19:00 by JohnRouillard
<<<

----
On Friday, July 31, 2009 9:35:58 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[TaggedTemplateTweak]] - replaces TaggedTemplateTweak - 5/3/2009 22:16:00 by ELSDesignStudios
#[[TaggedTemplateTweakInfo]] - replaces TaggedTemplateTweakInfo - 5/3/2009 22:15:00 by ELSDesignStudios
<<<

----
On Thursday, July 30, 2009 9:58:51 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[ExportTiddlersPlugin]] - replaces ExportTiddlersPlugin - 7/6/2009 11:02:00 by ELSDesignStudios
#[[ExportTiddlersPluginInfo]] - replaces ExportTiddlersPluginInfo - 4/30/2009 18:14:00 by ELSDesignStudios
<<<

----
On Monday, July 27, 2009 11:13:19 PM, JohnRouillard imported 1 tiddler from
[[http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html|http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html]]:
<<<
#[[CompareTiddlersPlugin]] - replaces CompareTiddlersPlugin - 7/27/2009 23:13:00 by ELSDesignStudios
<<<

----
On Monday, July 27, 2009 10:59:28 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 7/27/2009 19:07:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 7/27/2009 18:42:00 by ELSDesignStudios
<<<

----
On Monday, July 27, 2009 8:36:25 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 7/27/2009 19:07:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 7/27/2009 20:18:00 by JohnRouillard
<<<

----
On Monday, July 27, 2009 8:15:02 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 7/26/2009 17:41:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 7/26/2009 17:40:00 by ELSDesignStudios
<<<

----
On Sunday, July 26, 2009 11:13:48 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 7/6/2009 20:52:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 7/6/2009 20:51:00 by ELSDesignStudios
<<<

----
On Sunday, July 26, 2009 10:58:24 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#SaveFromWebConfig|http://www.tiddlytools.com/#SaveFromWebConfig]]:
<<<
#[[SaveFromWebConfig]] - replaces SaveFromWebConfig - 7/25/2009 13:21:00 by JohnRouillard
<<<

----
On Saturday, July 25, 2009 2:42:37 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[CompareTiddlersPlugin]] - replaces CompareTiddlersPlugin - 7/25/2009 14:37:00 by JohnRouillard
<<<

----
On Thursday, July 23, 2009 9:47:06 PM, JohnRouillard imported 1 tiddler from
[[http://tiddlywiki.bidix.info|http://tiddlywiki.bidix.info]]:
<<<
#[[RSSReaderPluginDescription]] - replaces RSSReaderPluginDescription - 7/4/2009 23:34:00 by JohnRouillard
<<<

----
On Thursday, July 23, 2009 9:22:13 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[SplitTiddler]] - replaces SplitTiddler - 7/5/2009 00:27:00 by JohnRouillard
<<<

----
On Thursday, July 23, 2009 9:07:18 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[ShowPopup]] - added
<<<

----
On Thursday, July 09, 2009 12:48:03 AM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#StorySaverPlugin|http://www.tiddlytools.com/#StorySaverPlugin]]:
<<<
#[[SaveAsPlugin]] - replaces SaveAsPlugin - 4/30/2009 15:55:00 by ELSDesignStudios
<<<

----
On Thursday, July 09, 2009 12:28:47 AM, JohnRouillard imported 8 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 4/24/2009 11:45:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 7/4/2009 23:30:00 by JohnRouillard
#[[ExportTiddlersPlugin]] - replaces ExportTiddlersPlugin - 4/30/2009 18:16:00 by ELSDesignStudios
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 7/6/2009 09:10:00 by ELSDesignStudios
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 5/4/2009 20:08:00 by ELSDesignStudios
#[[ImportTiddlersPlugin]] - replaces ImportTiddlersPlugin - 5/4/2009 20:27:00 by ELSDesignStudios
#[[TiddlerTweakerPlugin]] - replaces TiddlerTweakerPlugin - 6/26/2009 07:28:00 by ELSDesignStudios
#[[CopyTiddlerPlugin]] - replaces CopyTiddlerPlugin - 6/8/2009 04:34:00 by ELSDesignStudios
<<<

----
On Tuesday, July 07, 2009 8:50:38 PM, JohnRouillard imported 1 tiddler from
[[http://www.TiddlyTools.com|http://www.TiddlyTools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 7/4/2009 00:21:00 by ELSDesignStudios
<<<

----
On Saturday, July 04, 2009 10:52:42 PM, JohnRouillard imported 1 tiddler from
[[http://gwsyzygy.googlepages.com/creator.html|http://gwsyzygy.googlepages.com/creator.html]]:
<<<
#[[ScrollingTabsPlugin]] - added
<<<

----
On Saturday, July 04, 2009 1:26:07 AM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#SectionLinksPlugin|http://www.tiddlytools.com/#SectionLinksPlugin]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 6/3/2009 00:27:00 by ELSDesignStudios
<<<

----
On Saturday, July 04, 2009 1:16:15 AM, JohnRouillard imported 2 tiddlers from
[[http://www.TiddlyTools.com|http://www.TiddlyTools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 7/4/2009 00:08:58 by JohnRouillard
#[[SwitchThemePlugin]] - replaces SwitchThemePlugin - 4/23/2008 19:16:00 by ELSDesignStudios
<<<

----
On Friday, July 03, 2009 10:29:00 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[SplitTiddler]] - added
<<<

----
On Thursday, July 02, 2009 11:37:37 PM, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 4/13/2009 09:17:00 by PauloSoares
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 3/29/2009 19:49:00 by PauloSoares
<<<

----
On Thursday, July 02, 2009 11:21:27 PM, JohnRouillard imported 10 tiddlers from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[AttachFileMIMETypes]] - replaces AttachFileMIMETypes - 5/14/2006 21:21:00 by ELSDesignStudios
#[[CompareTiddlersPlugin]] - replaces CompareTiddlersPlugin - 6/9/2009 15:52:00 by JohnRouillard
#[[ImagePathPlugin]] - replaces ImagePathPlugin - 4/13/2007 15:48:00 by ELSDesignStudios
#[[ImageSizePlugin]] - replaces ImageSizePlugin - 2/26/2009 19:02:00 by ELSDesignStudios
#[[NestedSlidersPlugin]] - replaces NestedSlidersPlugin - 11/16/2008 01:23:00 by ELSDesignStudios
#[[NestedSlidersPluginInfo]] - replaces NestedSlidersPluginInfo - 11/16/2008 01:22:00 by ELSDesignStudios
#[[RefreshTiddler]] - added
#[[SwitchThemePlugin]] - replaces SwitchThemePlugin - 4/23/2008 19:16:00 by ELSDesignStudios
#[[SwitchThemePluginInfo]] - replaces SwitchThemePluginInfo - 4/23/2008 18:57:00 by ELSDesignStudios
#[[UnsavedChangesPlugin]] - replaces UnsavedChangesPlugin - 3/2/2009 14:33:00 by ELSDesignStudios
<<<

----
On Thursday, July 02, 2009 11:00:17 PM, JohnRouillard imported 3 tiddlers from
[[http://tiddlywiki.bidix.info|http://tiddlywiki.bidix.info]]:
<<<
#[[RSSReaderPlugin]] - replaces RSSReaderPlugin - 9/2/2008 16:25:00 by BidiX
#[[RSSReaderPluginDescription]] - added
#[[RSSReaderPluginDoc]] - replaces RSSReaderPluginDoc - 4/22/2007 04:57:00 by BidiX
<<<

----
On Thursday, July 02, 2009 10:57:08 PM, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com/|http://www.tiddlytools.com/]]:
<<<
#[[MatchTagsPlugin]] - replaces MatchTagsPlugin - 9/4/2008 12:45:00 by ELSDesignStudios
#[[MatchTagsPluginInfo]] - replaces MatchTagsPluginInfo - 9/4/2008 01:36:00 by ELSDesignStudios
<<<

----
On Thursday, July 02, 2009 10:52:37 PM, JohnRouillard imported 1 tiddler from
[[http://visualtw.ouvaton.org/VisualTW.html|http://visualtw.ouvaton.org/VisualTW.html]]:
<<<
#[[SyncFromSourcePlugin]] - replaces SyncFromSourcePlugin - 1/5/2008 04:31:00 by Pascal
<<<

----
On Thursday, July 02, 2009 10:41:51 PM, JohnRouillard imported 20 tiddlers from
[[http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html|http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html]]:
<<<
#[[TiddlerTweakerPlugin]] - replaces TiddlerTweakerPlugin - 1/22/2009 12:12:00 by ELSDesignStudios
#[[CopyTiddlerPlugin]] - replaces CopyTiddlerPlugin - 3/9/2009 20:48:00 by ELSDesignStudios
#[[AttachFilePlugin]] - replaces AttachFilePlugin - 7/21/2008 19:45:00 by ELSDesignStudios
#[[AttachFilePluginFormatters]] - replaces AttachFilePluginFormatters - 12/4/2007 15:56:00 by ELSDesignStudios
#[[AttachFilePluginInfo]] - replaces AttachFilePluginInfo - 7/21/2008 19:44:00 by ELSDesignStudios
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 6/3/2009 00:27:00 by ELSDesignStudios
#[[GotoPlugin]] - replaces GotoPlugin - 12/15/2008 19:42:00 by ELSDesignStudios
#[[GotoPluginInfo]] - replaces GotoPluginInfo - 12/15/2008 19:41:00 by ELSDesignStudios
#[[ImportTiddlersPlugin]] - replaces ImportTiddlersPlugin - 3/5/2009 11:45:00 by ELSDesignStudios
#[[ImportTiddlersPluginInfo]] - replaces ImportTiddlersPluginInfo - 3/4/2009 20:28:00 by ELSDesignStudios
#[[LoadTiddlersPluginInfo]] - replaces LoadTiddlersPluginInfo - 11/14/2008 10:51:00 by ELSDesignStudios
#[[LoadTiddlersPlugin]] - replaces LoadTiddlersPlugin - 11/14/2008 10:51:00 by ELSDesignStudios
#[[TaggedTemplateTweak]] - replaces TaggedTemplateTweak - 1/6/2009 05:19:00 by ELSDesignStudios
#[[TaggedTemplateTweakInfo]] - replaces TaggedTemplateTweakInfo - 3/29/2009 00:49:00 by JohnRouillard
#[[ExportTiddlersPlugin]] - replaces ExportTiddlersPlugin - 2/26/2009 15:21:00 by ELSDesignStudios
#[[ExportTiddlersPluginInfo]] - replaces ExportTiddlersPluginInfo - 2/26/2009 15:20:00 by ELSDesignStudios
#[[SaveAsPlugin]] - replaces SaveAsPlugin - 9/29/2008 11:12:00 by ELSDesignStudios
#[[SaveAsPluginInfo]] - replaces SaveAsPluginInfo - 9/29/2008 11:11:00 by ELSDesignStudios
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 4/24/2009 11:45:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 4/24/2009 11:24:00 by ELSDesignStudios
<<<

----
On Thursday, July 02, 2009 10:27:38 PM, JohnRouillard imported 1 tiddler from
[[http://visualtw.ouvaton.org/VisualTW.html|http://visualtw.ouvaton.org/VisualTW.html]]:
<<<
#[[SyncFromSourcePlugin]] - replaces SyncFromSourcePlugin - 3/22/2009 21:58:00 by JohnRouillard
<<<

----
On Thursday, July 02, 2009 10:21:26 PM, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#SectionLinksPlugin|http://www.tiddlytools.com/#SectionLinksPlugin]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 6/2/2009 18:02:00 by ELSDesignStudios
<<<

----
On Tuesday, June 09, 2009 12:26:52, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#CompareTiddlersPlugin|http://www.tiddlytools.com/#CompareTiddlersPlugin]]:
<<<
#[[CompareTiddlersPlugin]] - added
<<<

----
On Tuesday, June 09, 2009 12:21:29, JohnRouillard imported 1 tiddler from
[[http://www.linux-lovers.be/RevisionsPlugin/#RevisionsPlugin|http://www.linux-lovers.be/RevisionsPlugin/#RevisionsPlugin]]:
<<<
#[[RevisionsPlugin]] - added
<<<

----
On Tuesday, June 02, 2009 22:36:25, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#SectionLinksPlugin|http://www.tiddlytools.com/#SectionLinksPlugin]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 4/23/2009 23:14:00 by JohnRouillard
<<<

----
On Wednesday, May 27, 2009 21:18:01, JohnRouillard imported 2 tiddlers from
[[http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html|http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/SEC_ps.html]]:
<<<
#[[StorySaverPlugin]] - replaces StorySaverPlugin - 4/24/2009 11:45:00 by ELSDesignStudios
#[[StorySaverPluginInfo]] - replaces StorySaverPluginInfo - 4/24/2009 11:24:00 by ELSDesignStudios
<<<

----
On Wednesday, May 27, 2009 21:17:39, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com|http://www.tiddlytools.com]]:
<<<
#[[StorySaverPlugin]] - added
#[[StorySaverPluginInfo]] - added
<<<

----
On Friday, April 17, 2009 23:14:48, JohnRouillard imported 3 tiddlers from
[[http://www.TiddlyTools.com|http://www.TiddlyTools.com]]:
<<<
#[[ImagePathList]] - added
#[[ImagePathPlugin]] - added
#[[ImageSizePlugin]] - added
<<<

----
On Friday, April 17, 2009 22:34:10, JohnRouillard imported 1 tiddler from
[[http://www.TiddlyTools.com|http://www.TiddlyTools.com]]:
<<<
#[[SectionLinksPlugin]] - replaces SectionLinksPlugin - 1/18/2009 12:17:00 by ELSDesignStudios
<<<

----
On Thursday, April 16, 2009 00:16:38, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 3/30/2009 17:03:00 by PauloSoares
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 4/5/2009 14:02:00 by JohnRouillard
<<<

----
On Saturday, April 04, 2009 22:28:45, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - added
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 3/26/2009 14:58:00 by PauloSoares
<<<

----
On Monday, March 30, 2009 09:37:56, JohnRouillard imported 1 tiddler from
[[http://tiddlystyles.com/|http://tiddlystyles.com/]]:
<<<
#[[RedirectMacro]] - added
<<<

----
On Sunday, March 29, 2009 22:34:44, JohnRouillard imported 4 tiddlers from
[[C:\Documents and Settings\rouilj\Desktop\sec_class\SEC_tw.html|C:\Documents and Settings\rouilj\Desktop\sec_class\SEC_tw.html]]:
<<<
#[[StudentSlideShowViewTemplate]] - replaces StudentSlideShowViewTemplate - 3/29/2009 21:59:00 by JohnRouillard
#[[SlideShowViewTemplate]] - replaces SlideShowViewTemplate - 3/29/2009 21:59:00 by JohnRouillard
#[[contentViewTemplate]] - replaces contentViewTemplate - 3/29/2009 19:26:00 by JohnRouillard
#[[OtherToolbarCommands]] - added
<<<

----
On Sunday, March 29, 2009 19:32:26, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#TiddlerTweakerPlugin|http://www.tiddlytools.com/#TiddlerTweakerPlugin]]:
<<<
#[[TiddlerTweakerPlugin]] - added
<<<

----
On Sunday, March 29, 2009 12:18:38, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#UnsavedChangesPlugin|http://www.tiddlytools.com/#UnsavedChangesPlugin]]:
<<<
#[[UnsavedChangesPlugin]] - added
<<<

----
On Sunday, March 29, 2009 00:45:05, JohnRouillard imported 1 tiddler from
[[http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo]]:
<<<
#[[TaggedTemplateTweakInfo]] - added
<<<

----
On Sunday, March 29, 2009 00:26:42, JohnRouillard imported 1 tiddler from
[[http://www.tiddlywiki.com/coreplugins.html|http://www.tiddlywiki.com/coreplugins.html]]:
<<<
#[[SparklinePlugin]] - added
<<<

----
On Saturday, March 28, 2009 21:40:52, JohnRouillard imported 1 tiddler from
[[http://visualtw.ouvaton.org/VisualTW.html|http://visualtw.ouvaton.org/VisualTW.html]]:
<<<
#[[TiddlersBarPlugin]] - added
<<<

----
On Saturday, March 28, 2009 20:47:18, JohnRouillard imported 1 tiddler from
[[http://tw.lewcid.org/#TableSortingPlugin|http://tw.lewcid.org/#TableSortingPlugin]]:
<<<
#[[TableSortingPlugin]] - added
<<<

----
On Saturday, March 28, 2009 20:36:12, JohnRouillard imported 1 tiddler from
[[http://www.minormania.com/tiddlylock/tiddlylock.html|http://www.minormania.com/tiddlylock/tiddlylock.html]]:
<<<
#[[TiddlyLockPlugin]] - added 
<<<

----
On Saturday, March 28, 2009 20:19:40, JohnRouillard imported 1 tiddler from
[[http://mptw2.tiddlyspot.com/#Plugins|http://mptw2.tiddlyspot.com/#Plugins]]:
<<<
#[[RefreshCommand]] - added
<<<

----
On Saturday, March 28, 2009 20:11:12, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#RefreshTiddler|http://www.tiddlytools.com/#RefreshTiddler]]:
<<<
#[[RefreshTiddler]] - added
<<<

----
On Saturday, March 28, 2009 19:33:40, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#SectionLinksPlugin|http://www.tiddlytools.com/#SectionLinksPlugin]]:
<<<
#[[SectionLinksPlugin]] - added
<<<

----
On Thursday, March 26, 2009 23:02:31, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 3/26/2009 22:43:00 by JohnRouillard
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 3/25/2009 19:12:00 by PauloSoares
<<<

----
On Thursday, March 26, 2009 00:13:39, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 3/25/2009 15:38:00 by PauloSoares
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 3/25/2009 16:04:00 by PauloSoares
<<<

----
On Wednesday, March 25, 2009 19:06:36, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 3/25/2009 15:38:00 by PauloSoares
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 3/25/2009 16:04:00 by PauloSoares
<<<

----
On Wednesday, March 25, 2009 18:55:09, JohnRouillard imported 5 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[PrintingTheme]] - added
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 3/22/2009 22:22:00 by JohnRouillard
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 3/14/2009 12:02:00 by PauloSoares
#[[SlideShowTheme]] - added
#[[StudentTheme]] - added
<<<

----
On Sunday, March 22, 2009 22:20:27, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - replaces SlideShowPlugin - 3/21/2009 20:58:00 by JohnRouillard
#[[SlideShowPluginDoc]] - replaces SlideShowPluginDoc - 3/14/2009 12:02:00 by PauloSoares
<<<

----
On Sunday, March 22, 2009 17:33:31, JohnRouillard imported 1 tiddler from
[[http://www.tiddlytools.com/#InlineJavascriptPlugin|http://www.tiddlytools.com/#InlineJavascriptPlugin]]:
<<<
#[[InlineJavascriptPlugin]] - added
<<<

----
On Sunday, March 22, 2009 17:08:31, JohnRouillard imported 1 tiddler from
[[http://tw.lewcid.org/#ToggleSideBarMacro|http://tw.lewcid.org/#ToggleSideBarMacro]]:
<<<
#[[ToggleSideBarMacro]] - added
<<<

----
On Sunday, March 22, 2009 00:29:19, JohnRouillard imported 6 tiddlers from
[[http://tiddlytools.com/|http://tiddlytools.com/]]:
<<<
#[[AttachFileMIMETypes]] - added
#[[AttachFilePlugin]] - added
#[[AttachFilePluginFormatters]] - added
#[[AttachFilePluginInfo]] - added
#[[FileDropPlugin]] - added
#[[FileDropPluginConfig]] - added
<<<

----
On Saturday, March 21, 2009 19:31:04, JohnRouillard imported 1 tiddler from
[[http://tiddlytools.com/|http://tiddlytools.com/]]:
<<<
#[[CopyTiddlerPlugin]] - added
<<<

----
On Saturday, March 21, 2009 18:41:06, JohnRouillard imported 1 tiddler from
[[http://tw.lewcid.org/|http://tw.lewcid.org/]]:
<<<
#[[OpenTiddlersMacro]] - added
<<<

----
On Thursday, March 19, 2009 21:50:24, JohnRouillard imported 1 tiddler from
[[http://devpad.tiddlyspot.com/#DcTableOfContentsPlugin|http://devpad.tiddlyspot.com/#DcTableOfContentsPlugin]]:
<<<
#[[DcTableOfContentsPlugin]] - added
<<<

----
On Tuesday, March 17, 2009 01:19:43, JohnRouillard imported 1 tiddler from
[[http://tw.lewcid.org/#OpenTiddlersMacro|http://tw.lewcid.org/#OpenTiddlersMacro]]:
<<<
#[[OpenTiddlersMacro]] - added
<<<

----
On Tuesday, March 17, 2009 00:12:59, JohnRouillard imported 1 tiddler from
[[http://tw.lewcid.org/#BetterTimelineMacro|http://tw.lewcid.org/#BetterTimelineMacro]]:
<<<
#[[BetterTimelineMacro]] - added
<<<

----
On Monday, March 16, 2009 23:08:31, JohnRouillard imported 2 tiddlers from
[[http://www.TiddlyTools.com|http://www.TiddlyTools.com]]:
<<<
#[[NestedSlidersPlugin]] - added
#[[NestedSlidersPluginInfo]] - added
<<<

----
On Monday, March 16, 2009 23:01:22, JohnRouillard imported 1 tiddler from
[[http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin]]:
<<<
#[[PartTiddlerPlugin]] - added
<<<

----
On Monday, March 16, 2009 22:33:01, JohnRouillard imported 3 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons_2.4.html|http://www.math.ist.utl.pt/~psoares/addons_2.4.html]]:
<<<
#[[Quiz]] - added
#[[QuizzerPlugin]] - replaces QuizzerPlugin - 10/13/2007 17:17:00 by PauloSoares
#[[QuizzerPluginDoc]] - replaces QuizzerPluginDoc - 10/13/2007 17:16:00 by PauloSoares
<<<

----
On Monday, March 16, 2009 22:19:29, JohnRouillard imported 2 tiddlers from
[[http://vextor.net/|http://vextor.net/]]:
<<<
#[[QuizzerPlugin]] - added
#[[QuizzerPluginDoc]] - added
<<<

----
On Monday, March 16, 2009 00:19:02, JohnRouillard imported 2 tiddlers from
[[http://www.math.ist.utl.pt/~psoares/addons.html|http://www.math.ist.utl.pt/~psoares/addons.html]]:
<<<
#[[SlideShowPlugin]] - added
#[[SlideShowPluginDoc]] - added
<<<

----
On Sunday, March 15, 2009 18:30:46, JohnRouillard imported 2 tiddlers from
[[http://www.tiddlytools.com/#GotoPlugin|http://www.tiddlytools.com/#GotoPlugin]]:
<<<
#[[GotoPlugin]] - added
#[[GotoPluginInfo]] - added
<<<

----
On Sunday, March 15, 2009 18:01:56, JohnRouillard imported 2 tiddlers from
[[http://tiddlytools.com|http://tiddlytools.com]]:
<<<
#[[SwitchThemePlugin]] - added
#[[SwitchThemePluginInfo]] - added
<<<

----
On Sunday, March 15, 2009 17:08:36, JohnRouillard imported 1 tiddler from
[[http://visualtw.ouvaton.org/VisualTW.html|http://visualtw.ouvaton.org/VisualTW.html]]:
<<<
#[[FieldsEditorPlugin]] - added
<<<

----
On Sunday, March 15, 2009 15:55:36, JohnRouillard imported 4 tiddlers from
[[http://tw.lewcid.org/|http://tw.lewcid.org/]]:
<<<
#[[AnnotationsPlugin]] - added
#[[FontSizePlugin]] - added
#[[FootnotesPlugin]] - added
#[[TiddlerNotesPlugin]] - replaces TiddlerNotesPlugin - 10/26/2007 08:34:00 by Saq
<<<

----
On Sunday, March 15, 2009 15:08:51, JohnRouillard imported 8 tiddlers from
[[C:\Documents and Settings\rouilj\My Documents\downloads\coreaddons.export.html|C:\Documents and Settings\rouilj\My Documents\downloads\coreaddons.export.html]]:
<<<
#[[MatchTagsPlugin]] - added
#[[MatchTagsPluginInfo]] - added
#[[RSSReaderPlugin]] - added
#[[RSSReaderPluginDescription]] - added
#[[RSSReaderPluginDoc]] - added
#[[TaggedTemplateTweak]] - added
#[[TiddlerNotesPlugin]] - added
#[[YourSearchPlugin]] - added
<<<

----
On Sunday, March 15, 2009 15:03:06, JohnRouillard imported 2 tiddlers from
[[http://tiddlywiki.abego-software.de|http://tiddlywiki.abego-software.de]]:
<<<
#[[IntelliTaggerPlugin]] - added
#[[IntelliTagsEditCommandPlugin]] - added
<<<

----
On Sunday, March 15, 2009 14:59:54, JohnRouillard imported 1 tiddler from
[[http://no-sin.com/wiki/WorkTracker.html#AlternateBackupPlugin|http://no-sin.com/wiki/WorkTracker.html#AlternateBackupPlugin]]:
<<<
#[[AlternateBackupPlugin]] - added
<<<

----
On Sunday, March 15, 2009 14:51:54, JohnRouillard imported 1 tiddler from
[[http://visualtw.ouvaton.org/VisualTW.html|http://visualtw.ouvaton.org/VisualTW.html]]:
<<<
#[[SyncFromSourcePlugin]] - added
<<<
Instructions for emailing to people on how to download the coursebook and get it working.

Welcome to the SEC course. This course comes with a coursebook based
on ~TiddlyWiki. A ~TiddlyWiki is a single html file that uses
~JavaScript to make it into a wiki. The coursebook works best with
Firefox, but you can use it with some restrictions in Internet
Explorer (versions 7 and 8) as well as recent versions of Safari. Google
Chrome does not work as it is unable to import the content into the coursebook.

To set up your coursebook, browse to:

   <<tiddler "GettingStarted::courseHome" >>

Use the "Save Link as" functionality in your browser download the
~SEC_tw.html file. Do not load ~SEC_tw.html in your browser and then
try to save it using the File/Save mechanism, you must download the
link directly.

If you use a browser other than:
* Firefox (or a derivative)
* Internet Explorer
you must also download and save ~TiddlySaver.jar in the same directory
you saved ~SEC_tw.html.  This jar file allows you to save any notes
that you record in the coursebook.

If you use windows and a browser other than Firefox, one additional
step is needed. Use the file system explorer to find the ~SEC_tw.html
file. Right click on the file and pull up the properties menu. If you
see an unblock button (as in
http://tiddlywiki.org/wiki/How_To/Configure_your_browser_to_allow_saves_to_disk),
click on it and then dismiss the properties window. If you downloaded
the ~TiddlySaver.jar file you need to unblock it as well. Now you
should be able to open ~SEC_tw.html file and have it work correctly.

Depending on which browser you use, you may need to explicitly allow
the ~SEC_tw.hrml file to execute javascript. If you downloaded
~TiddlySaver.jar make sure that java is also enabled in your browser.
Once you have this you should see the GettingStarted page of the
coursebook.  Please follow the 4 step sequence to load content into
the coursebook and prepare it for use.


----

Also see: http://tiddlywiki.com/#ServicePack2Problems
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Insert Javascript executable code directly into your tiddler content.|
''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.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2009.04.11 [1.9.5] pass current tiddler object into wrapper code so it can be referenced from within 'onclick' scripts
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 5, date: new Date(2009,4,11)};

config.formatters.push( {
	name: "inlineJavascript",
	match: "\\<script",
	lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",

	handler: function(w) {
		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
		lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var src=lookaheadMatch[1];
			var label=lookaheadMatch[2];
			var tip=lookaheadMatch[3];
			var key=lookaheadMatch[4];
			var show=lookaheadMatch[5];
			var code=lookaheadMatch[6];
			if (src) { // external script library
				var script = document.createElement("script"); script.src = src;
				document.body.appendChild(script); document.body.removeChild(script);
			}
			if (code) { // inline code
				if (show) // display source in tiddler
					wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
				if (label) { // create 'onclick' command link
					var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
					var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
					link.code="function _out(place,tiddler){"+fixup+"\n};_out(this,this.tiddler);"
					link.tiddler=w.tiddler;
					link.onclick=function(){
						this.bufferedHTML="";
						try{ var r=eval(this.code);
							if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
								var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
							if(this.bufferedHTML.length)
								s.innerHTML=this.bufferedHTML;
							if((typeof(r)==="string")&&r.length) {
								wikify(r,s,null,this.tiddler);
								return false;
							} else return r!==undefined?r:false;
						} catch(e){alert(e.description||e.toString());return false;}
					};
					link.setAttribute("title",tip||"");
					var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
					URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
					URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
					link.setAttribute("href",URIcode);
					link.style.cursor="pointer";
					if (key) link.accessKey=key.substr(0,1); // single character only
				}
				else { // run script immediately
					var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
					var c="function _out(place,tiddler){"+fixup+"\n};_out(w.output,w.tiddler);";
					try	 { var out=eval(c); }
					catch(e) { out=e.description?e.description:e.toString(); }
					if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
				}
			}
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
		}
	}
} )
//}}}

// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
	if(limit > 0) text = text.substr(0,limit);
	var wikifier = new Wikifier(text,formatter,null,tiddler);
	return wikifier.wikifyPlain();
}
//}}}

// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
/***
|Name|InlineJavascriptPluginInfo|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for InlineJavascriptPlugin|
''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.
!!!!!Usage
<<<
This plugin adds wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be recognized as embedded javascript code.
<script show>
	/* javascript code goes here... */
</script>Every time the tiddler content is rendered, the javascript code is automatically evaluated, allowing you to invoke 'side-effect' processing and/or produce dynamically-generated content that is then inserted into the tiddler content, immediately following the script (see below).  By including the optional ''show'' keyword as the final parameter in a {{{<script>}}} marker, the plugin will also include the script source code in the output that it displays in the tiddler.  This is helpful when creating examples for documentation purposes (such as used in this tiddler!)

__''Deferred execution from an 'onClick' link''__
<script label="click here" title="mouseover tooltip text" key="X" show>
	/* javascript code goes here... */
	alert('you clicked on the link!');
</script>
By 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.  You may also include a {{{title="..."}}} parameter to specify the 'tooltip' text that will appear whenever the mouse is moved over the onClick link text, and a {{{key="X"}}} parameter to specify an //access key// (which must be a //single// letter or numeric digit only).

__''Loading scripts from external source files''__
<script src="URL" show>
	/* optional javascript code goes here... */
</script>You can also load javascript directly 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.

In addition to loading the javascript from the external file, you can also use this feature to invoke javascript code contained within the {{{<script>...</script>}}} markers.  This code is invoked //after// the external script file has been processed, and can make immediate use of the functions and/or global variables defined by the external script file.
>Note: To ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that is rendered as soon as your TiddlyWiki document is opened, such as MainMenu.  For example: put your {{{<script src="..."></script>}}} syntax into a separate 'library' tiddler (e.g., LoadScripts), and then add {{{<<tiddler LoadScripts>>}}} to MainMenu so that the library is loaded before any other tiddlers that rely upon the functions it defines. 
>
>Normally, loading external javascript in this way does not produce any direct output, and should not have any impact on the appearance of your MainMenu.  However, if your LoadScripts tiddler contains notes or other visible content, you can suppress this output by using 'inline CSS' in the MainMenu, like this: {{{@@display:none;<<tiddler LoadScripts>>@@}}}
<<<
!!!!!Creating dynamic tiddler content and accessing the ~TiddlyWiki DOM
<<<
An important difference between TiddlyWiki inline scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document: in a typical web document, you use the {{{document.write()}}} (or {{{document.writeln()}}}) function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.

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 instead will //completely replace the entire ~TiddlyWiki document in your browser window (which is clearly not a good thing!)//.  In order to allow scripts to use {{{document.write()}}}, the plugin automatically converts and buffers all HTML output so it can be safely inserted into your tiddler content, immediately following the script.

''Note that {{{document.write()}}} can only be used to output "pure HTML" syntax.  To produce //wiki-formatted// output, your script should instead return a text value containing the desired wiki-syntax content'', which will then be automatically rendered immediately following the script.  If returning a text value is not sufficient for your needs, the plugin also provides an automatically-defined variable, 'place', that gives the script code ''direct access to the //containing DOM element//'' into which the tiddler output is being rendered.  You can use this variable to ''perform direct DOM manipulations'' that can, for example:
* generate wiki-formatted output using {{{wikify("...content...",place)}}}
* vary the script's actions based upon the DOM element in which it is embedded
* access 'tiddler-relative' DOM information using {{{story.findContainingTiddler(place)}}}
Note:
''When using an 'onclick' script, the 'place' element actually refers to the onclick //link text// itself, instead of the containing DOM element.''  This permits you to directly reference or modify the link text to reflect any 'stateful' conditions that might set by the script.  To refer to the containing DOM element from within an 'onclick' script, you can use "place.parentNode" instead.
<<<
!!!!!Instant "bookmarklets"
<<<
You can also use an 'onclick' link to define a "bookmarklet": a small piece of javascript that can be ''invoked directly from the browser without having to be defined within the current document.''  This allows you to create 'stand-alone' commands that can be applied to virtually ANY TiddlyWiki document... even remotely-hosted documents that have been written by others!!  To create a bookmarklet, simply define an 'onclick' script and then grab the resulting link text and drag-and-drop it onto your browser's toolbar (or right-click and use the 'bookmark this link' command to add it to the browser's menu).

Notes:
*When writing scripts intended for use as bookmarklets, due to the ~URI-encoding required by the browser, ''you cannot not use ANY double-quotes (") within the bookmarklet script code.''
*All comments embedded in the bookmarklet script must ''use the fully-delimited {{{/* ... */}}} comment syntax,'' rather than the shorter {{{//}}} comment syntax.
*Most importantly, because bookmarklets are invoked directly from the browser interface and are not embedded within the TiddlyWiki document, there is NO containing 'place' DOM element surrounding the script.  As a result, ''you cannot use a bookmarklet to generate dynamic output in your document,''  and using {{{document.write()}}} or returning wiki-syntax text or making reference to the 'place' DOM element will halt the script and report a "Reference Error" when that bookmarklet is invoked.  
Please see [[InstantBookmarklets]] for many examples of 'onclick' scripts that can also be used as bookmarklets.
<<<
!!!!!Special reserved function name
<<<
The plugin 'wraps' all inline javascript code 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.
<<<
!!!!!$(...) 'shorthand' function
<<<
As described by Dustin Diaz [[here|http://www.dustindiaz.com/top-ten-javascript/]], the plugin defines a 'shorthand' function that allows you to write:
{{{
$(id)
}}}
in place of the normal standard javascript syntax:
{{{
document.getElementById(id)
}}}
This function is provided merely as a convenience for javascript coders that may be familiar with this abbreviation, in order to allow them to save a few bytes when writing their own inline script code.
<<<
!!!!!Examples
<<<
simple dynamic output:
><script show>
	document.write("The current date/time is: "+(new Date())+"<br>");
	return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
dynamic output using 'place' to get size information for current tiddler:
><script show>
	if (!window.story) window.story=window;
	var title=story.findContainingTiddler(place).getAttribute("tiddler");
	var size=store.getTiddlerText(title).length;
	return title+" is using "+size+" bytes";
</script>
dynamic output from an 'onclick' script, using {{{document.write()}}} and/or {{{return "..."}}}
><script label="click here" show>
	document.write("<br>The current date/time is: "+(new Date())+"<br>");
	return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
creating an 'onclick' button/link that accesses the link text AND the containing tiddler:
><script label="click here" title="clicking this link will show an 'alert' box" key="H" show>
	if (!window.story) window.story=window;
	var txt=place.firstChild.data;
	var tid=story.findContainingTiddler(place).getAttribute('tiddler');
	alert('Hello World!\nlinktext='+txt+'\ntiddler='+tid);
</script>
dynamically setting onclick link text based on stateful information:
>{{block{
{{{
<script label="click here">
	/* toggle "txtSomething" value */
	var on=(config.txtSomething=="ON");
	place.innerHTML=on?"enable":"disable";
	config.txtSomething=on?"OFF":"ON";
	return "\nThe current value is: "+config.txtSomething;
</script><script>
	/* initialize onclick link text based on current "txtSomething" value */
	var on=(config.txtSomething=="ON");
	place.lastChild.previousSibling.innerHTML=on?"disable":"enable";
</script>
}}}
<script label="click here">
	/* toggle "txtSomething" value */
	var on=(config.txtSomething=="ON");
	place.innerHTML=on?"enable":"disable";
	config.txtSomething=on?"OFF":"ON";
	return "\nThe current value is: "+config.txtSomething;
</script><script>
	/* initialize onclick link text based on current "txtSomething" value */
	var on=(config.txtSomething=="ON");
	place.lastChild.innerHTML=on?"enable":"disable";
</script>
}}}
loading a script from a source url:
>http://www.TiddlyTools.com/demo.js contains:
>>{{{function inlineJavascriptDemo() { alert('Hello from demo.js!!') } }}}
>>{{{displayMessage('InlineJavascriptPlugin: demo.js has been loaded');}}}
>note: When using this example on your local system, you will need to download the external script file from the above URL and install it into the same directory as your document.
>
><script src="demo.js" show>
	return "inlineJavascriptDemo() function has been defined"
</script>
><script label="click to invoke inlineJavascriptDemo()" key="D" show>
	inlineJavascriptDemo();
</script>
<<<
!!!!!Revisions
<<<
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
2008.06.11 [1.9.3] added $(...) function as 'shorthand' for document.getElementById()
2008.03.03 [1.9.2] corrected fallback declaration of wikifyPlainText() (fixes Safari "parse error")
2008.02.23 [1.9.1] in onclick function, use string instead of array for 'bufferedHTML' (fixes IE errors)
2008.02.21 [1.9.0] output from 'onclick' scripts (return value or document.write() calls) are now buffered and rendered into into a span following the script.  Also, added default 'return false' handling if no return value provided (prevents HREF from being triggered -- return TRUE to allow HREF to be processed).  Thanks to Xavier Verges for suggestion and preliminary code.
2008.02.14 [1.8.1] added backward-compatibility for use of wikifyPlainText() in TW2.1.3 and earlier
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 [1.8.0] added support for key="X" syntax to specify custom access key definitions
2007.12.15 [1.7.0] autogenerate URI encoded HREF on links for onclick scripts.  Drag links to browser toolbar to create bookmarklets.  IMPORTANT NOTE: place is NOT defined when scripts are used as bookmarklets.  In addition, double-quotes will cause syntax errors.  Thanks to PaulReiber for debugging and brainstorming.
2007.11.26 [1.6.2] when converting "document.write()" function calls in inline code, allow whitespace between "write" and "(" so that "document.write ( foobar )" is properly converted.
2007.11.16 [1.6.1] when rendering "onclick scripts", pass label text through wikifyPlainText() to parse any embedded wiki-syntax to enable use of HTML entities or even TW macros to generate dynamic label text.
2007.02.19 [1.6.0] added support for title="..." to specify mouseover tooltip when using an onclick (label="...") script
2006.10.16 [1.5.2] add newline before closing '}' in 'function out_' wrapper.  Fixes error caused when last line of script is a comment.
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
2006.04.19 [1.5.0] added 'show' parameter to force display of javascript source code in tiddler output
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.
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
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
2005.11.08 [1.2.0] handle loading of javascript from an external URL via src="..." syntax
2005.11.08 [1.1.0] pass 'place' param into scripts to provide direct DOM access 
2005.11.08 [1.0.0] initial release
<<<
* Student book without contents (framework)
** Meant to be portable for multiple classes.
* Student content to be imported
** Imported into framework to allow separation of framework updates from content updates
** Content updates are smaller than the whole TiddlyWiki
* rss feed of content changes
* Tool for mass editing of tiddlers, tags
* Tool for maintaining different versions of tiddlers
* Tools for embedding/attaching files inside TiddlyWiki document
* Tool for showing relations between tiddlers
* Tool for easier tag management
* Configuration that displays missing tiddlers rather then replacing with nothing
* Double click to edit a tiddler is enabled
* The instructor book has theme(s) meant for pretty display.
** It can include images, gradients and is all css controlled.
* The student book has a stripped down presentation mode and navigation/note taking interface
<<tiddler ChangeTitle##Script>>

<<tiddler SwitchContent with: 'Switch to alternate urls'  'GettingStarted - LISA'  'GettingStarted'>>
<<saveAs "label:save studentbook" "filename:CoursebookV2_student.html" "type:TiddlyWiki" not (content or structure or InstructorOnly or Notes or Revisions or nopublish or systemConfigDisable or temporary)>>
<<saveAs "label:save content" "filename:CoursebookV2_content_ps.html" "type:PureStore" not (nopublish or InstructorOnly or bblisaOnly) and (content or structure)>>
<<saveAs "label:save rss for content" "filename:CoursebookV2_rss.xml" "type:NewsFeed" "limit:30" not (nopublish or InstructorOnly or bblisaOnly) and (content or structure)>>
<<tiddler ToggleFullScreen with: "Toggle Fullscreen">>
--------
<<tiddler ShowPopup with: [[ReadMe/taglist]] "Defined Tags" "Show tags with predfined meaning in this tiddlywiki." >>
--------
[[Bugs And Feature Requests]]
[[Content Bugs]]
--------
Tiddlers tagged with this wiki word are not exported to the student tiddlywiki.
<<tiddler ChangeTitle##Script>>

<<tiddler SwitchContent with: 'Switch to alternate urls'  'GettingStarted - LISA'  'GettingStarted'>>
<<saveAs "label:save studentbook" "filename:CoursebookV2_student.html" "type:TiddlyWiki" not (content or structure or InstructorOnly or Notes or Revisions or nopublish or systemConfigDisable or temporary)>>
<<saveAs "label:save content" "filename:CoursebookV2_content_ps.html" "type:PureStore" not (nopublish or InstructorOnly or bblisaOnly) and (content or structure)>>
<<saveAs "label:save rss for content" "filename:CoursebookV2_rss.xml" "type:NewsFeed" "limit:30" not (nopublish or InstructorOnly or bblisaOnly) and (content or structure)>>
/%
!newTiddlers
<<newTiddler title:"New Chapter  1 -" tag:chapter tag:content tag:story label:"new chapter tiddler" prompt:"Create a new chapter tiddler.">><<newTiddler tag:content label:"new content tiddler" prompt:"Create a new content tiddler.">><<newTiddler title:"New Presentation  1 - " tag:presentation tag:content tag:story label:"new presentation tiddler" prompt:"Create a new presentation tiddler.">><<newTiddler title:"New Slide" tag:slide tag:content label:"new slide tiddler" prompt:"Create a new slide tiddler.">>
!end
%/
/% transclude these tiddlers for their side effects. defining aliases and defining ability to toggle fullscreen %/
/% shortcuts to bugs/features %/
<<redirectExact Bugs [[Bugs And Feature Requests]]>>
<<redirectExact Features [[Bugs And Feature Requests]]>>
/*{{{*/

body {
  background-image: url('[[LeftGradientImageBlue]]');
  background-repeat: repeat-y;
  color: #000;
}

/* Start Shadow style sheet */
.header, #mainMenu, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{
 display:none !important
}

#slideBlanker{
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 z-index: 90; 
 background-color: #000;
 opacity: 1.0;
 filter: alpha(opacity=100)
}

.nextOverlay{
 visibility: hidden
}

.previousOverlay,.currentOverlay{
 visibility: visible
}

#displayArea{
 font-size: 250%;
 margin: 0 !important;
 padding: 0
}

#controlBar{
 position: fixed;
 bottom: 2px;
 right: 2px;
 width: 100%;
 text-align: right
}

#controlBar .button{
 margin: 0 0.25em;
 padding: 0 0.25em
}

#slideHeader{
 font-size: 200%;
 font-weight: bold
}

#slideFooter{
 position: fixed;
 bottom: 2px
}

.slideFooterOff #navigator{
 visibility: hidden
}

#slideClock{
 margin: 0 5px 0 5px
}

#slideCounter{
 cursor: pointer;
 color: #aaa
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 bottom: 2em;
 right: 0;
 background: #fff;
 border: 1px solid #000;
 text-align: left
}

#jumpItem{
 padding-left:0.25em
}

#jumpInput{
 margin-left: 0.25em;
 width: 3em
}

.tocLevel1{
 font-size: .8em
}

.tocLevel2{
 margin-left: 1em;
 font-size: .75em
}

.tocLevel3{
 margin-left: 2em;
 font-size: .7em
}

.tocLevel4{
 margin-left: 3em;
 font-size: .65em
}

.tocLevel5{
 margin-left: 4em;
 font-size: .6em
}

.tocLevel6{
 margin-left: 5em;
 font-size: .55em
}

/* local changes for coursebook */

body {
cursor: crosshair;
}

/* set to 180% for 800x600 screen */
/*
#displayArea {
 font-size: 180%;
}
*/

/* change this to match the left border width to move the text out of the border */
.tiddler {
  margin-left: 100px !important;
}

#slideHeader {
 color: #0000BB;
 font-size: 50% !important;
 text-align: right;
}

#tiddlerDisplay {
margin-left: 0em;
margin-right: 0em;
padding: 0 !important;
}

/* background color matches the righthand gradient color. */
.title {
 color: #000000;
 border-bottom-style: outset;
 display: block !important;
 background-color: #B6B4FC;
 cursor:none;
}

.tiddler {
padding: 0px !important;
}

.viewer {
padding-left: 0.5em !important;
padding-right: 0.5em !important;
line-height: 1.2em;
}

/* tiddler content styles */
h1, h2, h3 {border-bottom: 0px}

.viewer ul, .viewer ol, .viewer dl{
margin: 0em !important;
}

.viewer code {
 font-weight: bold;
}

.viewer pre {
line-height: normal;
}

/* custom styles for 2 column layout */
.col2a {width:45%; float:left;}
.col2b {width:45%; float:left;}

/* custom syles for three column layout */
.col3a {width:32%; float:left;}
.col3b {width:32%; float:left;}
.col3c {width:32%; float:left;}

#slideFooter{
 font-size: 43%;
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 top: auto;
 bottom: 2em;
 right: 0em;
 background: #888;
 border: 1px solid #000;
 text-align: left;
}

/* navigator not always visible */
.slideFooterOff #navigator{
 visibility: hidden; 
}

/* do not display comments or notes */
#contentWrapper.slideShowMode .comment{
 display: none !important;
}

.notes{
 display: none !important;
}
/*}}}*/
/*{{{*/

body {
  background-image: url('[[LeftGradientImageBlue]]');
  background-repeat: repeat-y;
  color: #000;
}

/* Start Shadow style sheet */
.header, #mainMenu, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{
 display:none !important
}

#slideBlanker{
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 z-index: 90; 
 background-color: #000;
 opacity: 1.0;
 filter: alpha(opacity=100)
}

.nextOverlay{
 visibility: hidden
}

.previousOverlay,.currentOverlay{
 visibility: visible
}

#displayArea{
 font-size: 250%;
 margin: 0 !important;
 padding: 0
}

#controlBar{
 position: fixed;
 bottom: 2px;
 right: 2px;
 width: 100%;
 text-align: right
}

#controlBar .button{
 margin: 0 0.25em;
 padding: 0 0.25em
}

#slideHeader{
 font-size: 200%;
 font-weight: bold
}

#slideFooter{
 position: fixed;
 bottom: 2px
}

.slideFooterOff #navigator{
 visibility: hidden
}

#slideClock{
 margin: 0 5px 0 5px;
 visibility: visible;
}

#slideCounter{
 cursor: pointer;
 color: #aaa
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 bottom: 2em;
 right: 0;
 background: #fff;
 border: 1px solid #000;
 text-align: left
}

#jumpItem{
 padding-left:0.25em
}

#jumpInput{
 margin-left: 0.25em;
 width: 3em
}

.tocLevel1{
 font-size: .8em
}

.tocLevel2{
 margin-left: 1em;
 font-size: .75em
}

.tocLevel3{
 margin-left: 2em;
 font-size: .7em
}

.tocLevel4{
 margin-left: 3em;
 font-size: .65em
}

.tocLevel5{
 margin-left: 4em;
 font-size: .6em
}

.tocLevel6{
 margin-left: 5em;
 font-size: .55em
}

/* local changes for coursebook */

body {
cursor: crosshair;
}

/* set to 180% for 800x600 screen */
/*
#displayArea {
 font-size: 180%;
}
*/

/* change this to match the left border width to move the text out of the border */
.tiddler {
  margin-left: 100px !important;
}

#slideHeader {
 color: #FFFFFF;
 font-size: 50% !important;
 text-align: right;
 background-color: #3533BA;
}

#tiddlerDisplay {
margin-left: 0em;
margin-right: 0em;
padding: 0 !important;
}

/* background color matches the righthand gradient color. */
.title {
 color: #000000;
 border-bottom-style: outset;
 display: block !important;
 background-color: #B6B4FC;
 cursor:none;
 z-index: 20;
}

.tiddler {
padding: 0px !important;
}

.viewer {
padding-left: 0.5em !important;
padding-right: 0.5em !important;
line-height: 1.2em;
}

/* tiddler content styles */
h1, h2, h3 {border-bottom: 0px}

.viewer ul, .viewer ol, .viewer dl{
margin: 0em !important;
}

.viewer code {
 font-weight: bold;
}

.viewer pre {
line-height: normal;
}

/* custom styles for 2 column layout */
.col2a {width:45%; float:left;}
.col2b {width:45%; float:left;}

/* custom syles for three column layout */
.col3a {width:32%; float:left;}
.col3b {width:32%; float:left;}
.col3c {width:32%; float:left;}

#slideFooter{
 font-size: 43%;
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 top: auto;
 bottom: 2em;
 right: 0em;
 background: #888;
 border: 1px solid #000;
 text-align: left;
}

/* navigator not always visible */
.slideFooterOff #navigator{
 visibility: hidden; 
}

/* do not display comments or notes */
#contentWrapper.slideShowMode .comment{
 display: none !important;
}

.notes{
 display: none !important;
}
/*}}}*/
/*{{{*/

body {
  background-image: url('[[LeftGradientImageBlue]]');
  background-repeat: repeat-y;
  color: #000;
}

/* Start Shadow style sheet */
.header, #mainMenu, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{
 display:none !important
}

#slideBlanker{
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 z-index: 90; 
 background-color: #000;
 opacity: 1.0;
 filter: alpha(opacity=100)
}

.nextOverlay{
 visibility: hidden
}

.previousOverlay,.currentOverlay{
 visibility: visible
}

#displayArea{
 font-size: 250%;
 margin: 0 !important;
 padding: 0
}

#controlBar{
 position: fixed;
 bottom: 2px;
 right: 2px;
 width: 100%;
 text-align: right
}

#controlBar .button{
 margin: 0 0.25em;
 padding: 0 0.25em
}

#slideHeader{
 font-size: 200%;
 font-weight: bold
}

#slideFooter{
 position: fixed;
 bottom: 2px
}

.slideFooterOff #navigator{
 visibility: hidden
}

#slideClock{
 margin: 0 5px 0 5px;
 visibility: visible;
}

#slideCounter{
 cursor: pointer;
 color: #aaa
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 bottom: 2em;
 right: 0;
 background: #fff;
 border: 1px solid #000;
 text-align: left
}

#jumpItem{
 padding-left:0.25em
}

#jumpInput{
 margin-left: 0.25em;
 width: 3em
}

.tocLevel1{
 font-size: .8em
}

.tocLevel2{
 margin-left: 1em;
 font-size: .75em
}

.tocLevel3{
 margin-left: 2em;
 font-size: .7em
}

.tocLevel4{
 margin-left: 3em;
 font-size: .65em
}

.tocLevel5{
 margin-left: 4em;
 font-size: .6em
}

.tocLevel6{
 margin-left: 5em;
 font-size: .55em
}

/* local changes for coursebook */

body {
cursor: crosshair;
}

/* set to 180% for 800x600 screen */
/*
#displayArea {
 font-size: 180%;
}
*/

/* change this to match the left border width to move the text out of the border */
.tiddler {
  margin-left: 100px !important;
}

#slideHeader {
 color: #FFFFFF;
 font-size: 50% !important;
 text-align: right;
 background-color: #3533BA;
}

#tiddlerDisplay {
margin-left: 0em;
margin-right: 0em;
padding: 0 !important;
}

/* background color matches the righthand gradient color. */
.title {
 color: #000000;
 border-bottom-style: outset;
 display: block !important;
 background-color: #B6B4FC;
 cursor:none;
 z-index: 20;
display: none !important
}

.tiddler {
padding: 0px !important;
}

.viewer {
padding-left: 0.5em !important;
padding-right: 0.5em !important;
line-height: 1.2em;
}

/* tiddler content styles */
h1, h2, h3 {border-bottom: 0px}

.viewer ul, .viewer ol, .viewer dl{
margin: 0em !important;
}

.viewer code {
 font-weight: bold;
}

.viewer pre {
line-height: normal;
}

/* custom styles for 2 column layout */
.col2a {width:45%; float:left;}
.col2b {width:45%; float:left;}

/* custom syles for three column layout */
.col3a {width:32%; float:left;}
.col3b {width:32%; float:left;}
.col3c {width:32%; float:left;}

#slideFooter{
 font-size: 43%;
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 top: auto;
 bottom: 2em;
 right: 0em;
 background: #888;
 border: 1px solid #000;
 text-align: left;
}

/* navigator not always visible */
.slideFooterOff #navigator{
 visibility: hidden; 
}

/* do not display comments or notes */
#contentWrapper.slideShowMode .comment{
 display: none !important;
}

.notes{
 display: none !important;
}
/*}}}*/
/*{{{*/
/* Make bad links very obvious */
.tiddlyLinkNonExistingSection {font-size: 200%; background-color: orange; }
.tiddlyLinkNonExisting {font-size: 200%; background-color: green; }
.tiddlyLinkNonExisting.shadow {font-size: 100%; background-color: transparent; }

/* Make it easier to see comment in slides when shown in story column */
.comment{
 border: 1pt dashed;
 padding: 0.5em;
}
/*}}}*/
/***
|''Name:''|IntelliTaggerPlugin|
|''Version:''|1.0.2 (2007-07-25)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IntelliTaggerPlugin Documentation]]|
|''~SourceCode:''|[[IntelliTaggerPlugin SourceCode]]|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Version History
* 1.0.2 (2007-07-25): 
** Feature: "Return" key may be used to accept first tag suggestion (beside "Alt-1")
** Bugfix: Keyboard shortcuts (Alt+3 etc.) shifted
* 1.0.1 (2007-05-18): Improvement: Speedup when using TiddlyWikis with many tags
* 1.0.0 (2006-04-26): Initial release

***/
// /%
if(!version.extensions.IntelliTaggerPlugin){if(!window.abego){window.abego={};}if(!abego.internal){abego.internal={};}abego.alertAndThrow=function(s){alert(s);throw s;};if(version.major<2){abego.alertAndThrow("Use TiddlyWiki 2.0.8 or better to run the IntelliTagger Plugin.");}version.extensions.IntelliTaggerPlugin={major:1,minor:0,revision:2,date:new Date(2007,6,25),type:"plugin",source:"http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin",documentation:"[[IntelliTaggerPlugin Documentation]]",sourcecode:"[[IntelliTaggerPlugin SourceCode]]",author:"Udo Borkowski (ub [at] abego-software [dot] de)",licence:"[[BSD open source license (abego Software)]]",tiddlywiki:"Version 2.0.8 or better",browser:"Firefox 1.5.0.2 or better"};abego.createEllipsis=function(_2){var e=createTiddlyElement(_2,"span");e.innerHTML="&hellip;";};abego.isPopupOpen=function(_4){return _4&&_4.parentNode==document.body;};abego.openAsPopup=function(_5){if(_5.parentNode!=document.body){document.body.appendChild(_5);}};abego.closePopup=function(_6){if(abego.isPopupOpen(_6)){document.body.removeChild(_6);}};abego.getWindowRect=function(){return {left:findScrollX(),top:findScrollY(),height:findWindowHeight(),width:findWindowWidth()};};abego.moveElement=function(_7,_8,_9){_7.style.left=_8+"px";_7.style.top=_9+"px";};abego.centerOnWindow=function(_a){if(_a.style.position!="absolute"){throw "abego.centerOnWindow: element must have absolute position";}var _b=abego.getWindowRect();abego.moveElement(_a,_b.left+(_b.width-_a.offsetWidth)/2,_b.top+(_b.height-_a.offsetHeight)/2);};abego.isDescendantOrSelf=function(_c,e){while(e){if(_c==e){return true;}e=e.parentNode;}return false;};abego.toSet=function(_e){var _f={};for(var i=0;i<_e.length;i++){_f[_e[i]]=true;}return _f;};abego.filterStrings=function(_11,_12,_13){var _14=[];for(var i=0;i<_11.length&&(_13===undefined||_14.length<_13);i++){var s=_11[i];if(s.match(_12)){_14.push(s);}}return _14;};abego.arraysAreEqual=function(a,b){if(!a){return !b;}if(!b){return false;}var n=a.length;if(n!=b.length){return false;}for(var i=0;i<n;i++){if(a[i]!=b[i]){return false;}}return true;};abego.moveBelowAndClip=function(_1b,_1c){if(!_1c){return;}var _1d=findPosX(_1c);var _1e=findPosY(_1c);var _1f=_1c.offsetHeight;var _20=_1d;var _21=_1e+_1f;var _22=findWindowWidth();if(_22<_1b.offsetWidth){_1b.style.width=(_22-100)+"px";}var _23=_1b.offsetWidth;if(_20+_23>_22){_20=_22-_23-30;}if(_20<0){_20=0;}_1b.style.left=_20+"px";_1b.style.top=_21+"px";_1b.style.display="block";};abego.compareStrings=function(a,b){return (a==b)?0:(a<b)?-1:1;};abego.sortIgnoreCase=function(arr){var _27=[];var n=arr.length;for(var i=0;i<n;i++){var s=arr[i];_27.push([s.toString().toLowerCase(),s]);}_27.sort(function(a,b){return (a[0]==b[0])?0:(a[0]<b[0])?-1:1;});for(i=0;i<n;i++){arr[i]=_27[i][1];}};abego.getTiddlerField=function(_2d,_2e,_2f){var _30=document.getElementById(_2d.idPrefix+_2e);var e=null;if(_30!=null){var _32=_30.getElementsByTagName("*");for(var t=0;t<_32.length;t++){var c=_32[t];if(c.tagName.toLowerCase()=="input"||c.tagName.toLowerCase()=="textarea"){if(!e){e=c;}if(c.getAttribute("edit")==_2f){e=c;}}}}return e;};abego.setRange=function(_35,_36,end){if(_35.setSelectionRange){_35.setSelectionRange(_36,end);var max=0+_35.scrollHeight;var len=_35.textLength;var top=max*_36/len,bot=max*end/len;_35.scrollTop=Math.min(top,(bot+top-_35.clientHeight)/2);}else{if(_35.createTextRange!=undefined){var _3b=_35.createTextRange();_3b.collapse();_3b.moveEnd("character",end);_3b.moveStart("character",_36);_3b.select();}else{_35.select();}}};abego.internal.TagManager=function(){var _3c=null;var _3d=function(){if(_3c){return;}_3c={};store.forEachTiddler(function(_3e,_3f){for(var i=0;i<_3f.tags.length;i++){var tag=_3f.tags[i];var _42=_3c[tag];if(!_42){_42=_3c[tag]={count:0,tiddlers:{}};}_42.tiddlers[_3f.title]=true;_42.count+=1;}});};var _43=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_44,_45,_46,_47,_48,_49){var _4a=this.fetchTiddler(_44);var _4b=_4a?_4a.tags:[];var _4c=(typeof _49=="string")?_49.readBracketedList():_49;_43.apply(this,arguments);if(!abego.arraysAreEqual(_4b,_4c)){abego.internal.getTagManager().reset();}};var _4d=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_4e){var _4f=this.fetchTiddler(_4e);var _50=_4f&&_4f.tags.length>0;_4d.apply(this,arguments);if(_50){abego.internal.getTagManager().reset();}};this.reset=function(){_3c=null;};this.getTiddlersWithTag=function(tag){_3d();var _52=_3c[tag];return _52?_52.tiddlers:null;};this.getAllTags=function(_53){_3d();var _54=[];for(var i in _3c){_54.push(i);}for(i=0;_53&&i<_53.length;i++){_54.pushUnique(_53[i],true);}abego.sortIgnoreCase(_54);return _54;};this.getTagInfos=function(){_3d();var _56=[];for(var _57 in _3c){_56.push([_57,_3c[_57]]);}return _56;};var _58=function(a,b){var a1=a[1];var b1=b[1];var d=b[1].count-a[1].count;return d!=0?d:abego.compareStrings(a[0].toLowerCase(),b[0].toLowerCase());};this.getSortedTagInfos=function(){_3d();var _5e=this.getTagInfos();_5e.sort(_58);return _5e;};this.getPartnerRankedTags=function(_5f){var _60={};for(var i=0;i<_5f.length;i++){var _62=this.getTiddlersWithTag(_5f[i]);for(var _63 in _62){var _64=store.getTiddler(_63);if(!(_64 instanceof Tiddler)){continue;}for(var j=0;j<_64.tags.length;j++){var tag=_64.tags[j];var c=_60[tag];_60[tag]=c?c+1:1;}}}var _68=abego.toSet(_5f);var _69=[];for(var n in _60){if(!_68[n]){_69.push(n);}}_69.sort(function(a,b){var d=_60[b]-_60[a];return d!=0?d:abego.compareStrings(a.toLowerCase(),b.toLowerCase());});return _69;};};abego.internal.getTagManager=function(){if(!abego.internal.gTagManager){abego.internal.gTagManager=new abego.internal.TagManager();}return abego.internal.gTagManager;};(function(){var _6e=2;var _6f=1;var _70=30;var _71;var _72;var _73;var _74;var _75;var _76;if(!abego.IntelliTagger){abego.IntelliTagger={};}var _77=function(){return _72;};var _78=function(tag){return _75[tag];};var _7a=function(s){var i=s.lastIndexOf(" ");return (i>=0)?s.substr(0,i):"";};var _7d=function(_7e){var s=_7e.value;var len=s.length;return (len>0&&s[len-1]!=" ");};var _81=function(_82){var s=_82.value;var len=s.length;if(len>0&&s[len-1]!=" "){_82.value+=" ";}};var _85=function(tag,_87,_88){if(_7d(_87)){_87.value=_7a(_87.value);}story.setTiddlerTag(_88.title,tag,0);_81(_87);abego.IntelliTagger.assistTagging(_87,_88);};var _89=function(n){if(_76&&_76.length>n){return _76[n];}return (_74&&_74.length>n)?_74[n]:null;};var _8b=function(n,_8d,_8e){var _8f=_89(n);if(_8f){_85(_8f,_8d,_8e);}};var _90=function(_91){var pos=_91.value.lastIndexOf(" ");var _93=(pos>=0)?_91.value.substr(++pos,_91.value.length):_91.value;return new RegExp(_93.escapeRegExp(),"i");};var _94=function(_95,_96){var _97=0;for(var i=0;i<_95.length;i++){if(_96[_95[i]]){_97++;}}return _97;};var _99=function(_9a,_9b,_9c){var _9d=1;var c=_9a[_9b];for(var i=_9b+1;i<_9a.length;i++){if(_9a[i][1].count==c){if(_9a[i][0].match(_9c)){_9d++;}}else{break;}}return _9d;};var _a0=function(_a1,_a2){var _a3=abego.internal.getTagManager().getSortedTagInfos();var _a4=[];var _a5=0;for(var i=0;i<_a3.length;i++){var c=_a3[i][1].count;if(c!=_a5){if(_a2&&(_a4.length+_99(_a3,i,_a1)>_a2)){break;}_a5=c;}if(c==1){break;}var s=_a3[i][0];if(s.match(_a1)){_a4.push(s);}}return _a4;};var _a9=function(_aa,_ab){return abego.filterStrings(abego.internal.getTagManager().getAllTags(_ab),_aa);};var _ac=function(){if(!_71){return;}var _ad=store.getTiddlerText("IntelliTaggerMainTemplate");if(!_ad){_ad="<b>Tiddler IntelliTaggerMainTemplate not found</b>";}_71.innerHTML=_ad;applyHtmlMacros(_71,null);refreshElements(_71,null);};var _ae=function(e){if(!e){var e=window.event;}var tag=this.getAttribute("tag");if(_73){_73.call(this,tag,e);}return false;};var _b2=function(_b3){createTiddlyElement(_b3,"span",null,"tagSeparator"," | ");};var _b4=function(_b5,_b6,_b7,_b8,_b9){if(!_b6){return;}var _ba=_b8?abego.toSet(_b8):{};var n=_b6.length;var c=0;for(var i=0;i<n;i++){var tag=_b6[i];if(_ba[tag]){continue;}if(c>0){_b2(_b5);}if(_b9&&c>=_b9){abego.createEllipsis(_b5);break;}c++;var _bf="";var _c0=_b5;if(_b7<10){_c0=createTiddlyElement(_b5,"span",null,"numberedSuggestion");_b7++;var key=_b7<10?""+(_b7):"0";createTiddlyElement(_c0,"span",null,"suggestionNumber",key+") ");var _c2=_b7==1?"Return or ":"";_bf=" (Shortcut: %1Alt-%0)".format([key,_c2]);}var _c3=config.views.wikified.tag.tooltip.format([tag]);var _c4=(_78(tag)?"Remove tag '%0'%1":"Add tag '%0'%1").format([tag,_bf]);var _c5="%0; Shift-Click: %1".format([_c4,_c3]);var btn=createTiddlyButton(_c0,tag,_c5,_ae,_78(tag)?"currentTag":null);btn.setAttribute("tag",tag);}};var _c7=function(){if(_71){window.scrollTo(0,ensureVisible(_71));}if(_77()){window.scrollTo(0,ensureVisible(_77()));}};var _c8=function(e){if(!e){var e=window.event;}if(!_71){return;}var _cb=resolveTarget(e);if(_cb==_77()){return;}if(abego.isDescendantOrSelf(_71,_cb)){return;}abego.IntelliTagger.close();};addEvent(document,"click",_c8);var _cc=Story.prototype.gatherSaveFields;Story.prototype.gatherSaveFields=function(e,_ce){_cc.apply(this,arguments);var _cf=_ce.tags;if(_cf){_ce.tags=_cf.trim();}};var _d0=function(_d1){story.focusTiddler(_d1,"tags");var _d2=abego.getTiddlerField(story,_d1,"tags");if(_d2){var len=_d2.value.length;abego.setRange(_d2,len,len);window.scrollTo(0,ensureVisible(_d2));}};var _d4=config.macros.edit.handler;config.macros.edit.handler=function(_d5,_d6,_d7,_d8,_d9,_da){_d4.apply(this,arguments);var _db=_d7[0];if((_da instanceof Tiddler)&&_db=="tags"){var _dc=_d5.lastChild;_dc.onfocus=function(e){abego.IntelliTagger.assistTagging(_dc,_da);setTimeout(function(){_d0(_da.title);},100);};_dc.onkeyup=function(e){if(!e){var e=window.event;}if(e.altKey&&!e.ctrlKey&&!e.metaKey&&(e.keyCode>=48&&e.keyCode<=57)){_8b(e.keyCode==48?9:e.keyCode-49,_dc,_da);}else{if(e.ctrlKey&&e.keyCode==32){_8b(0,_dc,_da);}}if(!e.ctrlKey&&(e.keyCode==13||e.keyCode==10)){_8b(0,_dc,_da);}setTimeout(function(){abego.IntelliTagger.assistTagging(_dc,_da);},100);return false;};_81(_dc);}};var _e0=function(e){if(!e){var e=window.event;}var _e3=resolveTarget(e);var _e4=_e3.getAttribute("tiddler");if(_e4){story.displayTiddler(_e3,_e4,"IntelliTaggerEditTagsTemplate",false);_d0(_e4);}return false;};var _e5=config.macros.tags.handler;config.macros.tags.handler=function(_e6,_e7,_e8,_e9,_ea,_eb){_e5.apply(this,arguments);abego.IntelliTagger.createEditTagsButton(_eb,createTiddlyElement(_e6.lastChild,"li"));};var _ec=function(){if(_71&&_72&&!abego.isDescendantOrSelf(document,_72)){abego.IntelliTagger.close();}};setInterval(_ec,100);abego.IntelliTagger.displayTagSuggestions=function(_ed,_ee,_ef,_f0,_f1){_74=_ed;_75=abego.toSet(_ee);_76=_ef;_72=_f0;_73=_f1;if(!_71){_71=createTiddlyElement(document.body,"div",null,"intelliTaggerSuggestions");_71.style.position="absolute";}_ac();abego.openAsPopup(_71);if(_77()){var w=_77().offsetWidth;if(_71.offsetWidth<w){_71.style.width=(w-2*(_6e+_6f))+"px";}abego.moveBelowAndClip(_71,_77());}else{abego.centerOnWindow(_71);}_c7();};abego.IntelliTagger.assistTagging=function(_f3,_f4){var _f5=_90(_f3);var s=_f3.value;if(_7d(_f3)){s=_7a(s);}var _f7=s.readBracketedList();var _f8=_f7.length>0?abego.filterStrings(abego.internal.getTagManager().getPartnerRankedTags(_f7),_f5,_70):_a0(_f5,_70);abego.IntelliTagger.displayTagSuggestions(_a9(_f5,_f7),_f7,_f8,_f3,function(tag,e){if(e.shiftKey){onClickTag.call(this,e);}else{_85(tag,_f3,_f4);}});};abego.IntelliTagger.close=function(){abego.closePopup(_71);_71=null;return false;};abego.IntelliTagger.createEditTagsButton=function(_fb,_fc,_fd,_fe,_ff,id,_101){if(!_fd){_fd="[edit]";}if(!_fe){_fe="Edit the tags";}if(!_ff){_ff="editTags";}var _102=createTiddlyButton(_fc,_fd,_fe,_e0,_ff,id,_101);_102.setAttribute("tiddler",(_fb instanceof Tiddler)?_fb.title:String(_fb));return _102;};abego.IntelliTagger.getSuggestionTagsMaxCount=function(){return 100;};config.macros.intelliTagger={label:"intelliTagger",handler:function(_103,_104,_105,_106,_107,_108){var _109=_107.parseParams("list",null,true);var _10a=_109[0]["action"];for(var i=0;_10a&&i<_10a.length;i++){var _10c=_10a[i];var _10d=config.macros.intelliTagger.subhandlers[_10c];if(!_10d){abego.alertAndThrow("Unsupported action '%0'".format([_10c]));}_10d(_103,_104,_105,_106,_107,_108);}},subhandlers:{showTags:function(_10e,_10f,_110,_111,_112,_113){_b4(_10e,_74,_76?_76.length:0,_76,abego.IntelliTagger.getSuggestionTagsMaxCount());},showFavorites:function(_114,_115,_116,_117,_118,_119){_b4(_114,_76,0);},closeButton:function(_11a,_11b,_11c,_11d,_11e,_11f){var _120=createTiddlyButton(_11a,"close","Close the suggestions",abego.IntelliTagger.close);},version:function(_121){var t="IntelliTagger %0.%1.%2".format([version.extensions.IntelliTaggerPlugin.major,version.extensions.IntelliTaggerPlugin.minor,version.extensions.IntelliTaggerPlugin.revision]);var e=createTiddlyElement(_121,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_124){var e=createTiddlyElement(_124,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2006-2007 <b><font color=\"red\">abego</font></b> Software<font>";}}};})();config.shadowTiddlers["IntelliTaggerStyleSheet"]="/***\n"+"!~IntelliTagger Stylesheet\n"+"***/\n"+"/*{{{*/\n"+".intelliTaggerSuggestions {\n"+"\tposition: absolute;\n"+"\twidth: 600px;\n"+"\n"+"\tpadding: 2px;\n"+"\tlist-style: none;\n"+"\tmargin: 0;\n"+"\n"+"\tbackground: #eeeeee;\n"+"\tborder: 1px solid DarkGray;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .currentTag   {\n"+"\tfont-weight: bold;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .suggestionNumber {\n"+"\tcolor: #808080;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .numberedSuggestion{\n"+"\twhite-space: nowrap;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter {\n"+"\tmargin-top: 4px;\n"+"\tborder-top-width: thin;\n"+"\tborder-top-style: solid;\n"+"\tborder-top-color: #999999;\n"+"}\n"+".intelliTaggerSuggestions .favorites {\n"+"\tborder-bottom-width: thin;\n"+"\tborder-bottom-style: solid;\n"+"\tborder-bottom-color: #999999;\n"+"\tpadding-bottom: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .normalTags {\n"+"\tpadding-top: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter .button {\n"+"\tfont-size: 10px;\n"+"\n"+"\tpadding-left: 0.3em;\n"+"\tpadding-right: 0.3em;\n"+"}\n"+"\n"+"/*}}}*/\n";config.shadowTiddlers["IntelliTaggerMainTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class=\"favorites\" macro=\"intelliTagger action: showFavorites\"></div>\n"+"<div class=\"normalTags\" macro=\"intelliTagger action: showTags\"></div>\n"+"<!-- The Footer (with the Navigation) ============================================ -->\n"+"<table class=\"intelliTaggerFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n"+"  <tr>\n"+"\t<td align=\"left\">\n"+"\t\t<span macro=\"intelliTagger action: closeButton\"></span>\n"+"\t</td>\n"+"\t<td align=\"right\">\n"+"\t\t<span macro=\"intelliTagger action: version\"></span>, <span macro=\"intelliTagger action: copyright \"></span>\n"+"\t</td>\n"+"  </tr>\n"+"</tbody></table>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["IntelliTaggerEditTagsTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='title' macro='view title'></div>\n"+"<div class='tagged' macro='tags'></div>\n"+"<div class='viewer' macro='view text wikified'></div>\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["BSD open source license (abego Software)"]="See [[Licence|http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D]].";config.shadowTiddlers["IntelliTaggerPlugin Documentation"]="[[Documentation on abego Software website|http://tiddlywiki.abego-software.de/doc/IntelliTagger.pdf]].";config.shadowTiddlers["IntelliTaggerPlugin SourceCode"]="[[Plugin source code on abego Software website|http://tiddlywiki.abego-software.de/archive/IntelliTaggerPlugin/Plugin-IntelliTagger-src.1.0.2.js]]\n";(function(){var _126=restart;restart=function(){setStylesheet(store.getTiddlerText("IntelliTaggerStyleSheet"),"IntelliTaggerStyleSheet");_126.apply(this,arguments);};})();}
// %/
/***
|''Name:''|IntelliTagsEditCommandPlugin|
|''Version:''|1.0.0 (2007-10-03)|
|''Type:''|plugin|
|''Description:''|A command for your tiddler's toolbar to directly edit the tiddler's tags using the IntelliTaggerPlugin, without switching to "edit mode".|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTagsEditCommandPlugin|
|''Requires:''|IntelliTaggerPlugin http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Using the "IntelliTagsEditCommandPlugin"
Add the command {{{intelliTagsEdit}}} into the 'macro' attribute of the 'toolbar' {{{<div...>}}} in your ViewTemplate.

''Example:''
{{{
<div class='toolbar' 
        macro='toolbar -closeTiddler closeOthers +editTiddler intelliTagsEdit permalink references jump'>
</div>
}}}

This adds a "tags" button to the toolbar of the tiddlers (next to the ''edit'' button). Pressing the "tags" button will open the input field for the tiddler's tags and let you edit the tags with all the [[IntelliTaggerPlugin|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin]] features.
***/
/***
!Source Code
***/
//{{{
(function(){

if (!version.extensions.IntelliTaggerPlugin)
    throw Error("IntelliTagsEditCommandPlugin requires the IntelliTaggerPlugin (http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin)");

if (config.commands.intelliTagsEdit) 
    return;

config.commands.intelliTagsEdit = {
	text: "tags",
	tooltip: "edit the tags"
};

config.commands.intelliTagsEdit.handler = function(event,src,title) {
	var button = abego.IntelliTagger.createEditTagsButton(title, null, "tags", "edit the tags");
	button.onclick(event);
	return false;
};

})();
//}}}
John Rouillard has been working in system administration since the early 90's. His involvement with SEC started at version 1 in the early 2000's. His comments and needs drove a number of the features in the modern SEC. He presented a paper on using SEC at the LISA 2004 conference that has been referenced by people developing commercial correlation software. He continues to use SEC as a supplemental correlation engine for Nagios and is an active member of the SEC mailing list.

His homepage can be found at http://www.cs.umb.edu/~rouilj.

Email for <<tiddler "Credits::Author">>.
!usage
{{{[img[LeftGradientImageBlue]]}}}
[img[LeftGradientImageBlue]]
!notes
Blue left hand gradient for instructor mode slides.
!type
image/png
!file
./images_inst/left_gradient_blue.png
!url
http://www.cs.umb.edu/~rouilj/classes/SEC_intermediate/images/left_gradient_blue.png
!data
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAABCAIAAACnuZzqAAAAMklEQVQYlWPk513GxMTIyMjIxMTIxMQAYzAiMRgwRBiZmBgwREhVjM8uqppJjgOwagcA1sECY552w9cAAAAASUVORK5CYII=
{{col2a{[img(100%,)[rss-icon.png]]}}}
{{col2b{
<br /><br /><br /><br />
{{overlay1{Errata}}}
{{overlay2{Editing time}}}
{{overlay3{RSS feed}}}
{{overlay4{Embedded rss viewer}}}
{{overlay5{One click update}}}
}}}

{{nocol comment{
* update content tiddlers to fix errata
* editing was falling behind so I knew there would be changes between submission time and class
* rss feed on changes to see what's new. Embedded feed reader for student to use.
* one click updating of content
}}}
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

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

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 }
 return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.8.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|macro for automated updates or one-click installations of tiddlers from remote sources|
!!!!!Documentation
>see [[LoadTiddlersPluginInfo]]
!!!!!Configuration
<<<
<<option chkLoadTiddlersShowReport>>after loading tiddlers, automatically display [[ImportedTiddlers]] (if created)
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2009.10.08 3.8.1 removed switchTheme() from doImport()... causes an INFINITE cycle of imports!
|please see [[LoadTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.LoadTiddlersPlugin= {major: 3, minor: 8, revision: 1, date: new Date(2009,10,8)};

if (config.options.chkLoadTiddlersShowReport===undefined)
	config.options.chkLoadTiddlersShowReport=true;

config.macros.loadTiddlers = {
	label: '',
	tip: "add/update tiddlers from '%0'",
	lockedTag: 'noReload',	// if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
	askMsg: 'Please enter a local path/filename or a remote URL',
	openMsg: 'Opening %0',
	openErrMsg: 'Could not open %0 - error=%1',
	readMsg: 'Read %0 bytes from %1',
	foundMsg: 'Found %0 tiddlers in %1',
	nochangeMsg: "'%0' is up-to-date... skipped.",
	lockedMsg: "'%0' is tagged '%1'... skipped.",
	skippedMsg: 'skipped (cancelled by user)',
	loadedMsg: 'Loaded %0 of %1 tiddlers from %2',
	reportTitle: 'ImportedTiddlers',
	warning: "Warning!!  Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	handler: function(place,macroName,params) {
		var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
		var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
		var filter='updates';
		if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
			|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
			filter=params.shift();
		var src=params.shift(); if (!src || !src.length) return; // filename is required
		var quiet=(params[0]=='quiet'); if (quiet) params.shift();
		var ask=(params[0]=='confirm'); if (ask) params.shift();
		var force=(params[0]=='force'); if (force) params.shift();
		var init=(params[0]=='init'); if (init) params.shift();
		var nodirty=(params[0]=='nodirty'); if (nodirty) params.shift();
		var norefresh=(params[0]=='norefresh'); if (norefresh) params.shift();
		var noreport=(params[0]=='noreport'); if (noreport) params.shift();
		this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as 'autotags'
		if (label.trim().length) {
			// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
			createTiddlyButton(place,label.format([src.replace(/%20/g,' ')]),tip.format([src.replace(/%20/g,' ')]), function() {
				if (src=='ask') src=prompt(this.askMsg);
				config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
				return false;
			})
		}
		else {
			// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
			if (src=='ask') src=prompt(this.askMsg);
			config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,nodirty:nodirty,norefresh:norefresh,noreport:noreport});
		}
	},
	loadFile: function(src,callback,params) {
		var quiet=params.quiet;
		if (src==undefined || !src.length) return null; // filename is required
		if (!quiet) clearMessage();
		if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g,' ')]));
		// if working locally and src is not a URL, read from local filesystem
		if (document.location.protocol=='file:' && src.substr(0,5)!='http:' && src.substr(0,5)!='file:') {
			var txt=loadFile(src);
			if (!txt) { // file didn't load, might be relative path.. try fixup
				var pathPrefix=document.location.href;  // get current document path and trim off filename
				var slashpos=pathPrefix.lastIndexOf('/'); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf('\\'); 
				if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
				src=pathPrefix+src;
				if (pathPrefix.substr(0,5)!='http:') src=getLocalPath(src);
				var txt=loadFile(src);
			}
			if (!txt) { // file still didn't load, report error
				if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g,' '),'(unknown)']));
			} else {
				if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g,' ')]));
				if (version.major+version.minor*.1+version.revision*.01!=2.52)
					txt=convertUTF8ToUnicode(txt);
				if (callback) callback(true,params,txt,src,null);
			}
		} else { // use XMLHttpRequest
			doHttp('GET',src,null,null,config.options.txtRemoteUsername,config.options.txtRemotePassword,callback,params,null);
		}
	},
	readTiddlersFromHTML: function(html) {
		// for TW2.2+
		if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
			var remoteStore=new TiddlyWiki();
			remoteStore.importTiddlyWiki(html);
			return remoteStore.getTiddlers('title');	
		}
	},
	readTiddlersFromCSV: function(CSV) {
		var remoteStore=new TiddlyWiki();
		// GET NAMES
		var lines=CSV.replace(/\r/g,'').split('\n');
		var names=lines.shift().replace(/"/g,'').split(',');
		CSV=lines.join('\n');
		// ENCODE commas and newlines within quoted values
		var comma='!~comma~!'; var commaRE=new RegExp(comma,'g');
		var newline='!~newline~!'; var newlineRE=new RegExp(newline,'g');
		CSV=CSV.replace(/"([^"]*?)"/g,
			function(x){ return x.replace(/\,/g,comma).replace(/\n/g,newline); });
		// PARSE lines
		var lines=CSV.split('\n');
		for (var i=0; i<lines.length; i++) { if (!lines[i].length) continue;
			var values=lines[i].split(',');
			// DECODE commas, newlines, and doubled-quotes, and remove enclosing quotes (if any)
			for (var v=0; v<values.length; v++)
				values[v]=values[v].replace(commaRE,',').replace(newlineRE,'\n')
					.replace(/^"|"$/g,'').replace(/""/g,'"');
			// EXTRACT tiddler values
			var title=''; var text=''; var tags=[]; var fields={};
			var created=null; var when=new Date(); var who=config.options.txtUserName;
			for (var v=0; v<values.length; v++) { var val=values[v];
				if (names[v]) switch(names[v].toLowerCase()) {
					case 'title':	title=val.replace(/\[\]\|/g,'_'); break;
					case 'created': created=new Date(val); break;
					case 'modified':when=new Date(val); break;
					case 'modifier':who=val; break;
					case 'text':	text=val; break;
					case 'tags':	tags=val.readBracketedList(); break;
					default:	fields[names[v].toLowerCase()]=val; break;
				}
			}
			// CREATE tiddler in temporary store
			if (title.length)
				remoteStore.saveTiddler(title,title,text,who,when,tags,fields,true,created||when);
		}
		return remoteStore.getTiddlers('title');	
	},
	createTiddlerFromFile: function(src,txt) {
		var t=new Tiddler();
		var pos=src.lastIndexOf("/"); if (pos==-1) pos=src.lastIndexOf("\\");
		t.title=pos==-1?src:src.substr(pos+1);
		t.text=txt; 
		t.created=t.modified=new Date();
		t.modifier=config.options.txtUserName;
		if (src.substr(src.length-3,3)=='.js') t.tags=['systemConfig'];
		return [t];
	},
	doImport: function(status,params,html,src,xhr) {
		var cml=config.macros.loadTiddlers; // abbrev
		src=src.split('?')[0]; // strip off "?nocache=..."
		if (!status) {
			displayMessage(cml.openErrMsg.format([src.replace(/%20/g,' '),xhr.status]));
			return false;
		}
		var quiet=params.quiet;
		var ask=params.ask;
		var filter=params.filter;
		var force=params.force;
		var init=params.init;
		var nodirty=params.nodirty;
		var norefresh=params.norefresh;
		var noreport=params.noreport;
		var tiddlers = cml.readTiddlersFromHTML(html);
		if (!tiddlers||!tiddlers.length) tiddlers=cml.readTiddlersFromCSV(html);
		if (!tiddlers||!tiddlers.length) tiddlers=cml.createTiddlerFromFile(src,html);
		var count=tiddlers?tiddlers.length:0;
		if (!quiet) displayMessage(cml.foundMsg.format([count,src.replace(/%20/g,' ')]));
		var wasDirty=store.isDirty();
		store.suspendNotifications();
		var count=0;
		if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
			var inbound = tiddlers[t];
			var theExisting = store.getTiddler(inbound.title);
			if (inbound.title==cml.reportTitle)
				continue; // skip 'ImportedTiddlers' history from the other document...
			if (theExisting && theExisting.tags.contains(cml.lockedTag)) {
				if (!quiet) displayMessage(cml.lockedMsg.format([theExisting.title,cml.lockedTag]));
				continue; // skip existing tiddler if tagged with 'noReload'
			}
			// apply the all/new/changes/updates filter (if any)
			if (filter && filter!='all') {
				if ((filter=='new') && theExisting) // skip existing tiddlers
					continue;
				if ((filter=='changes') && !theExisting) // skip new tiddlers
					continue;
				if ((filter.substr(0,4)=='tag:') && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
					continue;
				if ((filter.substr(0,8)=='tiddler:') && inbound.title!=filter.substr(8)) // must match specific tiddler name
					continue;
				if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0)) {
					var msg=cml.nochangeMsg;
					if (!quiet&&msg.length) displayMessage(msg.format([inbound.title]));
					continue;
				}
			}
			// get confirmation if required
			var msg=(theExisting?'Update':'Add')+" tiddler '"+inbound.title+"'\n"
				+'from '+src.replace(/%20/g,' ')+'\n\nOK to proceed?';
			if (ask && !confirm(msg))
				{ tiddlers[t].status=cml.skippedMsg; continue; }
			// DO IT!
			var tags=new Array().concat(inbound.tags,cml.newTags);
	                store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier,
				inbound.modified, tags, inbound.fields, true, inbound.created);
			// force creation date to imported value - needed for TW2.1.3 or earlier
	                store.fetchTiddler(inbound.title).created = inbound.created;
			tiddlers[t].status=theExisting?'updated':'added'
			if (init && tags.contains('systemConfig') && !tags.contains('systemConfigDisable')) {
				var ok=true;
				if (ask||!quiet) ok=confirm(cml.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound.text); tiddlers[t].status+=' (plugin initialized)'; }
					catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
				}
			}
			count++;
		}
		store.resumeNotifications();
		if (count) {
			// set/clear 'unsaved changes' flag, refresh page display, and generate a report
			store.setDirty(wasDirty||!nodirty);
			if (!norefresh) {
				story.forEachTiddler(function(t,e){
					if(!story.isDirty(t))story.refreshTiddler(t,null,true)
				});
				store.notifyAll();
			}
			if (!noreport) cml.report(src,tiddlers,count,quiet);
		}
		// show message whenver tiddlers are actually loaded
		if (!quiet||count)
			displayMessage(cml.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g,' ')]));
	},
	showReport: true,
	report: function(src,tiddlers,count,quiet) {
		var cml=config.macros.loadTiddlers; // abbrev
		// format the new report content
		var newText = 'On '+(new Date()).toLocaleString()+', ';
		newText += config.options.txtUserName+' loaded '+count+' tiddlers ';
		newText += 'from\n[['+src+'|'+src+']]:\n';
		newText += '<<<\n';
		for (var t=0; t<tiddlers.length; t++)
			if (tiddlers[t].status)
				newText += '#[['+tiddlers[t].title+']] - '+tiddlers[t].status+'\n';
		newText += '<<<\n';
		var title=cml.reportTitle;
		var currText='';
		var t=store.getTiddler(title);
		if (t) currText=(t.text.length?'\n----\n':'')+t.text;
		store.saveTiddler(title, title, newText+currText,
			config.options.txtUserName, new Date(),	t?t.tags:null, t?t.fields:null);
		if (!quiet) {
			if (config.options.chkLoadTiddlersShowReport)
				story.displayTiddler(null,title);
			story.refreshTiddler(title,null,true);
		}
	}
}
//}}}
/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.7.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|macro for automated updates or one-click installations of tiddlers from remote sources|
!!!!!Documentation
>see [[LoadTiddlersPluginInfo]]
!!!!!Configuration
<<<
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2009.08.30 [3.7.5] in doImport(), check status and report error, if any
|please see [[LoadTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.LoadTiddlersPlugin= {major: 3, minor: 7, revision: 5, date: new Date(2009,8,30)};

config.macros.loadTiddlers = {
	label: '',
	tip: "add/update tiddlers from '%0'",
	lockedTag: 'noReload',	// if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
	askMsg: 'Please enter a local path/filename or a remote URL',
	openMsg: 'Opening %0',
	openErrMsg: 'Could not open %0 - error=%1',
	readMsg: 'Read %0 bytes from %1',
	foundMsg: 'Found %0 tiddlers in %1',
	nochangeMsg: "'%0' is up-to-date... skipped.",
	lockedMsg: "'%0' is tagged '%1'... skipped.",
	skippedMsg: 'skipped (cancelled by user)',
	loadedMsg: 'Loaded %0 of %1 tiddlers from %2',
	reportTitle: 'ImportedTiddlers',
	warning: "Warning!!  Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	handler: function(place,macroName,params) {
		var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
		var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
		var filter='updates';
		if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
			|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
			filter=params.shift();
		var src=params.shift(); if (!src || !src.length) return; // filename is required
		var quiet=(params[0]=='quiet'); if (quiet) params.shift();
		var ask=(params[0]=='confirm'); if (ask) params.shift();
		var force=(params[0]=='force'); if (force) params.shift();
		var init=(params[0]=='init'); if (init) params.shift();
		var nodirty=(params[0]=='nodirty'); if (nodirty) params.shift();
		var norefresh=(params[0]=='norefresh'); if (norefresh) params.shift();
		var noreport=(params[0]=='noreport'); if (noreport) params.shift();
		var noreportshow=(params[0]=='noreportshow'); if (noreportshow) params.shift();

		this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as 'autotags'
		if (label.trim().length) {
			// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
			createTiddlyButton(place,label.format([src.replace(/%20/g,' ')]),tip.format([src.replace(/%20/g,' ')]), function() {
				if (src=='ask') src=prompt(this.askMsg);
				config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport,noreportshow:noreportshow});
				return false;
			})
		}
		else {
			// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
			if (src=='ask') src=prompt(this.askMsg);
			config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,nodirty:nodirty,norefresh:norefresh,noreport:noreport,noreportshow:noreportshow});
		}
	},
	loadFile: function(src,callback,params) {
		var quiet=params.quiet;
		if (src==undefined || !src.length) return null; // filename is required
		if (!quiet) clearMessage();
		if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g,' ')]));
		// if working locally and src is not a URL, read from local filesystem
		if (document.location.protocol=='file:' && src.substr(0,5)!='http:' && src.substr(0,5)!='file:') {
			var txt=loadFile(src);
			if (!txt) { // file didn't load, might be relative path.. try fixup
				var pathPrefix=document.location.href;  // get current document path and trim off filename
				var slashpos=pathPrefix.lastIndexOf('/'); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf('\\'); 
				if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
				src=pathPrefix+src;
				if (pathPrefix.substr(0,5)!='http:') src=getLocalPath(src);
				var txt=loadFile(src);
			}
			if (!txt) { // file still didn't load, report error
				if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g,' '),'(unknown)']));
			} else {
				if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g,' ')]));
				if (version.major+version.minor*.1+version.revision*.01!=2.52)
					txt=convertUTF8ToUnicode(txt);
				if (callback) callback(true,params,txt,src,null);
			}
		} else { // use XMLHttpRequest
			doHttp('GET',src,null,null,config.options.txtRemoteUsername,config.options.txtRemotePassword,callback,params,null);
		}
	},
	readTiddlersFromHTML: function(html) {
		// for TW2.2+
		if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
			var remoteStore=new TiddlyWiki();
			remoteStore.importTiddlyWiki(html);
			return remoteStore.getTiddlers('title');	
		}
	},
	readTiddlersFromCSV: function(CSV) {
		var remoteStore=new TiddlyWiki();
		var lines=CSV.split('\n'); var names=lines[0].split(','); CSV=lines.join('\n')
		// ENCODE commas and newlines within quoted values
		var comma='!~comma~!'; var commaRE=new RegExp(comma,'g');
		var newline='!~newline~!'; var newlineRE=new RegExp(newline,'g');
		CSV=CSV.replace(/\x22((?:[^\x22]|\x22\x22)*?)\x22/g,
			function(x){ return x.substr(1,x.length-2).replace(/\,/g,comma).replace(/\n/g,newline); });
		// PARSE lines
		var lines=CSV.split('\n');
		for (var i=1; i<lines.length; i++) { if (!lines[i].length) continue;
			var values=lines[i].split(',');
			// DECODE commas, newlines and doubled-quotes within quoted values
			for (var v=0; v<values.length; v++)
				values[v]=values[v].replace(commaRE,',').replace(newlineRE,'\n').replace(/\x22\x22/g,'\x22');
			// EXTRACT tiddler values
			var title=''; var text=''; var tags=[]; var fields={};
			var created=null; var when=new Date(); var who=config.options.txtUserName;
			for (var v=0; v<values.length; v++) { var val=values[v];
				if (names[v]) switch(names[v].toLowerCase()) {
					case 'title':	title=val.replace(/\[\]\|/g,'_'); break;
					case 'created': created=new Date(val); break;
					case 'modified':when=new Date(val); break;
					case 'modifier':who=val; break;
					case 'text':	text=val; break;
					case 'tags':	tags=val.readBracketedList(); break;
					default:	fields[names[v].toLowerCase()]=val; break;
				}
			}
			// CREATE tiddler in temporary store
			if (title.length) remoteStore.saveTiddler(title,title,text,who,when,tags,fields,true,created||when);
		}
		return remoteStore.getTiddlers('title');	
	},
	doImport: function(status,params,html,src,xhr) {
		var cml=config.macros.loadTiddlers; // abbrev
		src=src.split('?')[0]; // strip off "?nocache=..."
		if (!status) {
			displayMessage(cml.openErrMsg.format([src.replace(/%20/g,' '),xhr.status]));
			return false;
		}
		var quiet=params.quiet;
		var ask=params.ask;
		var filter=params.filter;
		var force=params.force;
		var init=params.init;
		var nodirty=params.nodirty;
		var norefresh=params.norefresh;
		var noreport=params.noreport;
		var noreportshow=params.noreportshow;
		var tiddlers = cml.readTiddlersFromHTML(html);
		if (!tiddlers||!tiddlers.length) tiddlers=cml.readTiddlersFromCSV(html);
		var count=tiddlers?tiddlers.length:0;
		if (!quiet) displayMessage(cml.foundMsg.format([count,src.replace(/%20/g,' ')]));
		var wasDirty=store.isDirty();
		store.suspendNotifications();
		var count=0;
		if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
			var inbound = tiddlers[t];
			var theExisting = store.getTiddler(inbound.title);
			if (inbound.title==cml.reportTitle)
				continue; // skip 'ImportedTiddlers' history from the other document...
			if (theExisting && theExisting.tags.contains(cml.lockedTag)) {
				if (!quiet) displayMessage(cml.lockedMsg.format([theExisting.title,cml.lockedTag]));
				continue; // skip existing tiddler if tagged with 'noReload'
			}
			// apply the all/new/changes/updates filter (if any)
			if (filter && filter!='all') {
				if ((filter=='new') && theExisting) // skip existing tiddlers
					continue;
				if ((filter=='changes') && !theExisting) // skip new tiddlers
					continue;
				if ((filter.substr(0,4)=='tag:') && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
					continue;
				if ((filter.substr(0,8)=='tiddler:') && inbound.title!=filter.substr(8)) // must match specific tiddler name
					continue;
				if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0)) {
					var msg=cml.nochangeMsg;
					if (!quiet&&msg.length) displayMessage(msg.format([inbound.title]));
					continue;
				}
			}
			// get confirmation if required
			if (ask && !confirm((theExisting?'Update':'Add')+" tiddler '"+inbound.title+"'\nfrom "+src.replace(/%20/g,' ')+'\n\nOK to proceed?'))
				{ tiddlers[t].status=cml.skippedMsg; continue; }
			// DO IT!
			var tags=new Array().concat(inbound.tags,cml.newTags);
	                store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, tags, inbound.fields, true, inbound.created);
	                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value - needed for TW2.1.3 or earlier
			tiddlers[t].status=theExisting?'updated':'added'
			if (init && tags.contains('systemConfig') && !tags.contains('systemConfigDisable')) {
				var ok=true;
				if (ask||!quiet) ok=confirm(cml.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound.text); tiddlers[t].status+=' (plugin initialized)'; }
					catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
				}
			}
			count++;
		}
		store.resumeNotifications();
		if (count) {
			// optionally: set/clear 'unsaved changes' flag, refresh page display, and generate a report
			store.setDirty(wasDirty||!nodirty);
			if (!norefresh) {
				story.forEachTiddler(function(t,e){if(!story.isDirty(t))story.refreshTiddler(t,null,true)});
				store.notifyAll();
			}
			if (!noreport) cml.report(src,tiddlers,count,quiet,noreportshow);
		}
		// always show final message when tiddlers were actually loaded
		if (!quiet||count) displayMessage(cml.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g,' ')]));
	},
	report: function(src,tiddlers,count,quiet,noreportshow) {
		// format the new report content
		var newText = 'On '+(new Date()).toLocaleString()+', ';
		newText += config.options.txtUserName+' loaded '+count+' tiddlers ';
		newText += 'from\n[['+src+'|'+src+']]:\n';
		newText += '<<<\n';
		for (var t=0; t<tiddlers.length; t++)
			if (tiddlers[t].status)
				newText += '#[['+tiddlers[t].title+']] - '+tiddlers[t].status+'\n';
		newText += '<<<\n';
		// get current report (if any)
		var title=config.macros.loadTiddlers.reportTitle;
		var currText='';
		var theReport = store.getTiddler(title);
		if (theReport) currText=((theReport.text!='')?'\n----\n':'')+theReport.text;
		// update the ImportedTiddlers content and show the tiddler
		store.saveTiddler(title, title, newText+currText, config.options.txtUserName, new Date(), theReport?theReport.tags:null, theReport?theReport.fields:null);
		if (!(quiet || noreportshow) ) { story.displayTiddler(null,title,1,null,null,false); story.refreshTiddler(title,1,true); }
	}
}
//}}}
/***
|Name|LoadTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.8.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for LoadTiddlersPlugin|
!!!!!Usage
<<<
Syntax:
{{{<<loadTiddlers label:text prompt:text filter source quiet confirm force init noreport tag tag tag...>>}}}

Example:
{{{<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>}}}
<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>

Where:
''"""label:text"""'' and ''"""prompt:text"""''
>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.
''filter'' (optional) determines which tiddlers will be automatically selected for importing.  Use one of the following keywords:
>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler
>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)
>''""""tiddler:TiddlerName""""'' retrieves only the specific tiddler named in the parameter.
>''""""tag:text""""'' retrieves only the tiddlers tagged with the indicated text.
>> 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.
''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://")
>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked
''"quiet"'' (optional)
>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.
''"confirm"'' (optional)
>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.
''"init"'' (optional)
>invoke tiddlers tagged with <<tag systemConfig>> as plugins as soon as they are imported, without requiring a save-and-reload action first.  For safety, a browser message box (OK/Cancel) is displayed for each imported plugin, so that you can manually bypass any plugins that you do not want to invoke.  Note, however, that those tiddlers are still //imported// into your document and therefore will still take effect the next time you save-and-reload the document.
''"force"'' (optional)
>import all matching tiddlers, even if unchanged
''"noreport"'' (optional)
>suppress generation of [[ImportedTiddlers]] report
''"tag tag tag..."'' (optional)
>any remaining parameters are used as tag values to be added to each imported tiddler (i.e., "tag-on-import")
<<<
!!!!!Configuration
<<<
<<option chkLoadTiddlersShowReport>>after loading tiddlers, automatically display [[ImportedTiddlers]] (if created)
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2009.10.08 3.8.1 removed switchTheme() from doImport()... causes an INFINITE cycle of imports!
2009.10.06 3.8.0 added createTiddlerFromFile (import text files)
2009.10.04 3.7.8 in doImport(), call switchTheme() after loading tiddlers
2009.09.27 3.7.7 in readTiddlersFromCSV(), strip \r from input and fixed handling for quoted values
2009.09.01 3.7.6 added config.options.chkLoadTiddlersShowReport (default=true)
2009.09.01 3.7.6 added config.options.chkLoadTiddlersShowReport (default=true)
2009.08.30 3.7.5 in doImport(), check status and report error, if any
2009.08.29 3.7.4 in handler(), added 'return false' in button function (fixes IE page transition)
2009.08.19 3.7.3 in doImport(), fixed 'init' handling
2009.08.16 3.7.2 in doImport(), corrected check for tiddlers returned by readTiddlersFromHTML();
2009.07.03 3.7.1 fixups for TW252: doHttp() doesn't return XHR and convertUTF8ToUnicode() not needed for local I/O
2009.05.04 3.7.0 read CSV file format
2008.11.14 3.6.4 in loadFile(), force use of XMLHttpRequest if not viewing a local document (supports use of relative file references when online)
2008.10.27 3.6.3 in doImport(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
2008.08.05 3.6.2 rewrote loadFile() to eliminate use of platform-specific fileExists() test
2008.08.03 3.6.1 in handler(), changed variable 'prompt' to 'tip' to avoid conflict with prompt() function
2008.01.07 3.6.0 added 'init' option to automatically invoke plugin tiddlers as soon as they are loaded (without needing save/reload)
2008.01.03 3.5.0 in loadFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.12.04 *.*.* update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.27 3.4.8 added missing 'fields' params to saveTiddler() call. Fixes problem where importing tiddlers would lose the custom fields.
2007.06.25 3.4.7 add calls to store.suspendNotifications() and store.resumeNotifications() to eliminate redisplay overhead DURING import activities.
2007.05.27 3.4.6 in handler(), loadRemoteFile() and doImport(), added 'noreport' flag to suppress generation of ImportedTiddlers
2007.05.27 3.4.5 in handler(), initialize 'newTags' to [] (empty array) instead of null... fixes fatal error when loading tiddler without autotagging.
2007.04.22 3.4.4 in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content.  Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.04.05 3.4.3 in doImport(), changed this.readTiddlersFromHTML(html) to config.macros.loadTiddlers.readTiddlersFromHTML(html).
2007.03.26 3.4.2 renamed import() to doImport() to fix IE load-time error ("identifier expected").  "import" is a reserved word in some browsers...
2007.03.22 3.4.1 code cleanup: moved all functions inside object def'n, re-wrote report function
2007.03.21 3.4.0 split ImportTiddlersPlugin and LoadTiddlersPlugin into separate plugins
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
[[Welcome]]
[[ContentChanges]]
--------
<<tiddler ShowPopup with: [[BookmarkList]] "Bookmarks" "User's list of bookmarked tiddlers." >> @@font-size: smaller;[[(open)|BookmarkList]]@@
--------
<<toggleSideBar "Toggle Right Bar" '' show>>
--------
<<tiddler InstructorMainMenu>>
!Presentations
<<openStory list "story and presentation" >>
<<tiddler PresentationList>>
!Chapters
<<openStory list "story and chapter" >>
<<tiddler ChapterList>>
!Quizzes
<<tiddler QuizList>>
/***
|Name|MatchTagsPlugin|
|Source|http://www.TiddlyTools.com/#MatchTagsPlugin|
|Documentation|http://www.TiddlyTools.com/#MatchTagsPluginInfo|
|Version|2.0.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|'tag matching' with full boolean expressions (AND, OR, NOT, and nested parentheses)|
!!!!!Documentation
> see [[MatchTagsPluginInfo]]
!!!!!Revisions
<<<
2010.03.02 2.0.3 added %6 format (tags)
| please see [[MatchTagsPluginInfo]] for additional revision details |
2008.02.28 1.0.0 initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.MatchTagsPlugin= {major: 2, minor: 0, revision: 3, date: new Date(2010,3,2)};

// store.getMatchingTiddlers() processes boolean expressions for tag matching
//    sortfield (optional) sets sort order for tiddlers - default=title
//    tiddlers (optional) use alternative set of tiddlers (instead of current store)
TiddlyWiki.prototype.getMatchingTiddlers = function(tagexpr,sortfield,tiddlers) {

	var debug=config.options.chkDebug; // abbreviation
	var cmm=config.macros.matchTags; // abbreviation
	var r=[]; // results are an array of tiddlers
	var tids=tiddlers||store.getTiddlers(sortfield||"title");
	if (tiddlers && sortfield) store.sortTiddlers(tids,sortfield);
	if (debug) displayMessage(cmm.msg1.format([tids.length]));

	// try simple lookup to quickly find single tags or tags that
	// contain boolean operators as literals, e.g. "foo and bar"
	for (var t=0; t<tids.length; t++)
		if (tids[t].isTagged(tagexpr)) r.pushUnique(tids[t]);
	if (r.length) {
		if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
		return r;
	}
	
	// convert expression into javascript code with regexp tests,
	// so that "tag1 AND ( tag2 OR NOT tag3 )" becomes
	// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag3\~/.test(...) )"

	// normalize whitespace, tokenize operators, delimit with "~"
	var c=tagexpr.trim(); // remove leading/trailing spaces
	c = c.replace(/\s+/ig," "); // reduce multiple spaces to single spaces
	c = c.replace(/\(\s?/ig,"~(~"); // open parens
	c = c.replace(/\s?\)/ig,"~)~"); // close parens
	c = c.replace(/(\s|~)?&&(\s|~)?/ig,"~&&~"); // &&
	c = c.replace(/(\s|~)AND(\s|~)/ig,"~&&~"); // AND
	c = c.replace(/(\s|~)?\|\|(\s|~)?/ig,"~||~"); // ||
	c = c.replace(/(\s|~)OR(\s|~)/ig,"~||~"); // OR
	c = c.replace(/(\s|~)?!(\s|~)?/ig,"~!~"); // !
	c = c.replace(/(^|~|\s)NOT(\s|~)/ig,"~!~"); // NOT
	c = c.replace(/(^|~|\s)NOT~\(/ig,"~!~("); // NOT(
	// change tag terms to regexp tests
	var terms=c.split("~"); for (var i=0; i<terms.length; i++) { var t=terms[i];
		if (/(&&)|(\|\|)|[!\(\)]/.test(t) || t=="") continue; // skip operators/parens/spaces
		if (t==config.macros.matchTags.untaggedKeyword)
			terms[i]="tiddlertags=='~~'"; // 'untagged' tiddlers
		else
			terms[i]="/\\~"+t+"\\~/.test(tiddlertags)";
	}
	c=terms.join(" ");
	if (debug) { displayMessage(cmm.msg2.format([tagexpr])); displayMessage(cmm.msg3.format([c])); }

	// scan tiddlers for matches
	for (var t=0; t<tids.length; t++) {
	 	// assemble tags from tiddler into string "~tag1~tag2~tag3~"
		var tiddlertags = "~"+tids[t].tags.join("~")+"~";
		try { if(eval(c)) r.push(tids[t]); } // test tags
		catch(e) { // error in test
			displayMessage(cmm.msg2.format([tagexpr]));
			displayMessage(cmm.msg3.format([c]));
			displayMessage(e.toString());
			break; // skip remaining tiddlers
		}
	}
	if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
	return r;
}
//}}}
//{{{
config.macros.matchTags = {
	msg1: "scanning %0 input tiddlers",
	msg2: "looking for '%0'",
	msg3: "using expression: '%0'",
	msg4: "found %0 tiddlers matching '%1'",
	noMatch: "no matching tiddlers",
	untaggedKeyword: "-",
	untaggedLabel: "no tags",
	untaggedPrompt: "show tiddlers with no tags",
	defTiddler: "MatchingTiddlers",
	defTags: "",
	defFormat: "[[%0]]",
	defSeparator: "\n",
	reportHeading: "Found %0 tiddlers tagged with: '{{{%1}}}'\n----\n",
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var mode=params[0]?params[0].toLowerCase():'';
		if (mode=="inline")
			params.shift();
		if (mode=="report" || mode=="panel") {
			params.shift();
			var target=params.shift()||this.defTiddler;
		}
		if (mode=="popup") {
			params.shift();
			if (params[0]&&params[0].substr(0,6)=="label:") var label=params.shift().substr(6);
			if (params[0]&&params[0].substr(0,7)=="prompt:") var prompt=params.shift().substr(7);
		} else {
			var fmt=(params.shift()||this.defFormat).unescapeLineBreaks();
			var sep=(params.shift()||this.defSeparator).unescapeLineBreaks();
		}
		var sortBy="+title";
		if (params[0]&&params[0].substr(0,5)=="sort:") sortBy=params.shift().substr(5);
		var expr = params.join(" ");
		if (mode!="panel" && (!expr||!expr.trim().length)) return;
		if (expr==this.untaggedKeyword)
			{ var label=this.untaggedLabel; var prompt=this.untaggedPrompt };
		switch (mode) {
			case "popup": this.createPopup(place,label,expr,prompt,sortBy); break;
			case "panel": this.createPanel(place,expr,fmt,sep,sortBy,target); break;
			case "report": this.createReport(target,this.defTags,expr,fmt,sep,sortBy); break;
			case "inline": default: this.createInline(place,expr,fmt,sep,sortBy); break;
		}
	},
	formatList: function(tids,fmt,sep) {
		var out=[];
		for (var i=0; i<tids.length; i++) { var t=tids[i];
			var title=t.title;
			var who=t.modifier;
			var when=t.modified.toLocaleString();
			var text=t.text;
			var first=t.text.split("\n")[0];
			var desc=store.getTiddlerSlice(t.title,"description");
			desc=desc||store.getTiddlerSlice(t.title,"Description");
			desc=desc||store.getTiddlerText(t.title+"##description");
			desc=desc||store.getTiddlerText(t.title+"##Description");
			var tags=t.tags.length?'[['+t.tags.join(']] [[')+']]':'';
			out.push(fmt.format([title,who,when,text,first,desc,tags]));
		}
		return out.join(sep);
	},
	createInline: function(place,expr,fmt,sep,sortBy) {
		wikify(this.formatList(store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy),fmt,sep),place);
	},
	createPopup: function(place,label,expr,prompt,sortBy) {
		var btn=createTiddlyButton(place,
			(label||expr).format([expr]),
			(prompt||config.views.wikified.tag.tooltip).format([expr]),
			function(ev){ return config.macros.matchTags.showPopup(this,ev||window.event); });
		btn.setAttribute("sortBy",sortBy);
		btn.setAttribute("expr",expr);
	},
	showPopup: function(here,ev) {
		var p=Popup.create(here); if (!p) return false;
		var tids=store.getMatchingTiddlers(here.getAttribute("expr"));
		store.sortTiddlers(tids,here.getAttribute("sortBy"));
		var list=[]; for (var t=0; t<tids.length; t++) list.push(tids[t].title);
		if (!list.length) createTiddlyText(p,this.noMatch);
		else {
			var b=createTiddlyButton(createTiddlyElement(p,"li"),
				config.views.wikified.tag.openAllText,
				config.views.wikified.tag.openAllTooltip,
				function() {
					var list=this.getAttribute("list").readBracketedList();
					story.displayTiddlers(null,tids);
				});
			b.setAttribute("list","[["+list.join("]] [[")+"]]");
			createTiddlyElement(p,"hr");
		}
		var out=this.formatList(tids," &nbsp;[[%0]]&nbsp; ","\n"); wikify(out,p);
		Popup.show();
		ev.cancelBubble=true;
		if(ev.stopPropagation) ev.stopPropagation();
		return false;
	},
	createReport: function(target,tags,expr,fmt,sep,sortBy) {
		var tids=store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy);
		if (!tids.length) { displayMessage('no matches for: '+expr); return false; }
		var msg=config.messages.overwriteWarning.format([target]);
		if (store.tiddlerExists(target) && !confirm(msg)) return false;
		var out=this.reportHeading.format([tids.length,expr])
		out+=this.formatList(tids,fmt,sep);
		store.saveTiddler(target,target,out,config.options.txtUserName,new Date(),tags,{});
		story.closeTiddler(target); story.displayTiddler(null,target);
	},
	createPanel: function(place,expr,fmt,sep,sortBy,tid) {
		var s=createTiddlyElement(place,"span"); s.innerHTML=store.getTiddlerText("MatchTagsPlugin##html");
		var f=s.getElementsByTagName("form")[0];
		f.expr.value=expr; f.fmt.value=fmt; f.sep.value=sep.escapeLineBreaks();
		f.tid.value=tid; f.tags.value=this.defTags;
	}
};
//}}}
/***
//{{{
!html
<form style='display:inline;white-space:nowrap'>
<input type='text'    name='expr' style='width:50%' title='tag expression'><!--
--><input type='text'    name='fmt'  style='width:10%' title='list item format'><!--
--><input type='text'    name='sep'  style='width:5%'  title='list item separator'><!--
--><input type='text'    name='tid'  style='width:12%' title='target tiddler title'><!--
--><input type='text'    name='tags' style='width:10%' title='target tiddler tags'><!--
--><input type='button'  name='go'   style='width:8%'  value='go' onclick="
	var expr=this.form.expr.value;
	if (!expr.length) { alert('Enter a boolean tag expression'); return false; }
	var fmt=this.form.fmt.value;
	if (!fmt.length) { alert('Enter the list item output format'); return false; }
	var sep=this.form.sep.value.unescapeLineBreaks();
	var tid=this.form.tid.value;
	if (!tid.length) { alert('Enter a target tiddler title'); return false; }
	var tags=this.form.tags.value;
	config.macros.matchTags.createReport(tid,tags,expr,fmt,sep,'title');
	return false;">
</form>
!end
//}}}
***/
//{{{
// SHADOW TIDDLER for displaying default panel input form
config.shadowTiddlers.MatchTags="<<matchTags panel>>";
//}}}
//{{{
// TWEAK core filterTiddlers() for enhanced boolean matching in [tag[...]] syntax:
// use getMatchingTiddlers instead getTaggedTiddlers
var fn=TiddlyWiki.prototype.filterTiddlers;
fn=fn.toString().replace(/getTaggedTiddlers/g,"getMatchingTiddlers");
eval("TiddlyWiki.prototype.filterTiddlers="+fn);
//}}}
//{{{
// REDEFINE core handler for enhanced boolean matching in tag:"..." paramifier
// use filterTiddlers() instead of getTaggedTiddlers() to get list of tiddlers.
config.paramifiers.tag = {
	onstart: function(v) {
		var tagged = store.filterTiddlers("[tag["+v+"]]");
		story.displayTiddlers(null,tagged,null,false,null);
	}
};
//}}}
/***
|Name|MatchTagsPluginInfo|
|Source|http://www.TiddlyTools.com/#MatchTagsPlugin|
|Documentation|http://www.TiddlyTools.com/#MatchTagsPluginInfo|
|Version|2.0.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for MatchTagsPlugin|
!!!!!Usage
<<<
This plugin extends the {{{[tag[tagname]]}}} macro parameter syntax used by the TiddlyWiki core {{{<<list>>}}} macro so that, instead of a simple tagname value, you can specify a complex combination of tagname values using a //boolean expression// containing AND, OR, and NOT operators, enclosed in nested parentheses if needed.
{{{
<<list filter "[tag[expression]]">>
}}}
In addition, the plugin defines a new macro, {{{<<matchTags ...>>}}} that can be used instead of the core {{{<<list>>}}} macro to output a list of matching tiddlers //using a custom 'item format' and 'separator'//.  You can also use this macro to create a command link that displays the matching tiddlers within a popup list, similar to the standard {{{<<tag tagName>>}}} macro, but matching a combination of tag values rather than a single tag value.
{{{
<<matchTags inline "format" "separator" sort:fieldname tag expression>>
<<matchTags popup "label:..." "prompt:..." sort:fieldname tag expression>>
<<matchTags report TiddlerName "format" "separator" sort:fieldname tag expression>>
<<matchTags panel  Tiddlername "format" "separator" sort:fieldname tag expression>>
}}}
where:
* ''inline'', ''report'', ''panel'', and ''popup''<br>are keywords that indicate the type of output that the macro should produce:
** ''inline'' //(default)// - displays a list of matching tiddlers embedded directly in tiddler content
** ''popup'' - embeds a command button that, when clicked, lists matching tiddlers in a ~TiddlyWiki popup display
** ''report'' - generates a list of matching tiddler in a separate [[MatchingTiddlers]] report tiddler
** ''panel'' - displays an interactive form for generating a [[MatchingTiddlers]] report
* ''format''<br>defines the wiki-syntax for rendering list items.  The following //substitution markers// can be used to insert tiddler-specific information for each matched tiddler:
** {{{%0}}} - title
** {{{%1}}} - modifier (author)
** {{{%2}}} - modified (date of last change)
** {{{%3}}} - text (all tiddler content)
** {{{%4}}} - firstline (tiddler content up to the first newline)
** {{{%5}}} - description (tiddler slice or section content named "description" or "Description")
** {{{%6}}} - tags (space-separated, bracketed list)
* ''separator''<br>defines the wiki-syntax to use //between// each matching title (e.g., ", " creates a comma-separated list, while "\n" displays one tiddler per line).
* ''sort:fieldname'' (optional)<br>specifies the sort order for the resulting list of tiddlers.  You can specify any tiddler field name (standard or custom-defined).  Standard tiddler fieldnames include: //title, created, modified, modifier//.  If not specified, tiddlers are sorted by title.  You can prefix the fieldname with "+" or "-" to indicate ascending or descending order, respectively.
* ''tag expression''<br>the remaining parameter(s) are joined together to define the boolean expression to be matched.
When using the ''popup'' option, there are two additional (and optional) parameters you can specify:
* ''"label:..."''(optional)<br> indicates the text for the popup command link.  The default is to display the specified tag expression itself.
* ''"prompt:..."'' (optional)<br>indicates the mouseover 'tooltip' for the popup command link.
When using the ''report'' or ''panel'' option, an additional parameter may be provided:
* ''~TiddlerName''<br>specifies the target tiddler into which the output will be generated (default: [[MatchingTiddlers]])
Notes:
*A tag expression can use any combination of text operators: ''AND'', ''OR'', ''NOT'' (or their equivalent javascript operators: ''&&'', ''||'', ''!''), contained in nested parentheses as needed.
*Operators should be delimited by spaces or parentheses.
*Before matching, leading/trailing spaces are automatically trimmed and multiple spaces are reduced to single spaces.
*Tag values containing embedded spaces do //not// have to be enclosed in {{{[[...]]}}}.
*Tag values that contain boolean operators as ''literal text'' (e.g., {{{"foo and bar"}}} or {{{"foo && bar"}}} cannot be used within a compound boolean expression, but //can// be matched if specified by themselves, without any other tag values or operators.
*To match tiddlers that are untagged, use "-" as a special tag value within the expression.
*You can match "wildcard" tags  by using //regular expression// (i.e., "text pattern") syntax within a tag value, e.g. {{{[Tt]agvalue.*}}}
<<<
!!!!!Examples:
<<<
display a popup list:
{{{
<<matchTags popup sample OR (settings AND systemConfig)>>
}}}
><<matchTags popup sample OR (settings AND systemConfig)>>
display a popup list with custom label:
{{{
<<matchTags popup "label:samples and settings" sample OR (settings AND systemConfig)>>
}}}
><<matchTags popup "label:samples and settings" sample OR (settings AND systemConfig)>>
display a popup list of untagged tiddlers:
{{{
<<matchTags popup ->>
}}}
><<matchTags popup ->>
generate a report using interactive form control panel
{{{
<<matchTags panel "MatchingTiddlers" "[[%0]]" "\n" sample OR (settings AND systemConfig)>>
}}}
>{{smallform{<<matchTags panel "MatchingTiddlers" "[[%0]]" "\n" sample OR (settings AND systemConfig)>>}}}
comma-separated list:
{{{
<<matchTags "[[%0]]" ", " sample OR (settings AND systemConfig)>>
}}}
><<matchTags "[[%0]]" ", " sample OR (settings AND systemConfig)>>
numbered list (sorted by modification date, most recent first):
{{{
<<matchTags "#[[%0]] (%2)<br>^^%5^^" "\n" sort:-modified sample OR (settings AND systemConfig)>>
}}}
><<matchTags "#[[%0]] (%2)<br>^^%5^^" "\n" sort:-modified sample OR (settings AND systemConfig)>>
bullet-item list (using the TiddlyWiki core {{{<<list filter ...>>}}} macro):
//(Note: when using the core {{{<<list>>}}} macro, you should always enclose the entire tag filter parameter within quotes)//
{{{
<<list filter "[tag[sample OR (settings AND systemConfig)]]">>
}}}
><<list filter "[tag[sample OR (settings AND systemConfig)]]">>
<<<
!!!!!Revisions
<<<
2010.03.02 2.0.3 added %6 format (tags)
2010.03.01 2.0.2 in formatList(), don't automatically put '[[' and ']]' around title (%0) in formatted output
2009.08.29 2.0.1 added support for {{{config.macros.matchTags.defTags}}} to auto-tag [[MatchingTiddlers]] output
2008.09.04 2.0.0 added "report" and "panel" options to generate formatted results and store in a tiddler.  Also, added config.macros.matchTags.formatList(place,fmt,sep) API to return formatted output for use with other plugins/scripts
2008.09.01 1.9.2 fixed return value from popup button handler so IE doesn't attempt to leave the page
2008.08.31 1.9.1 improved expression conversion handling to permit use of regular expressions for "wildcard" matching within tag values
2008.06.12 1.9.0 added support for formatted output of: title, who, when, text, firstline, description (slice or section)
2008.06.05 1.8.0 in getMatchingTiddlers(), added optional sortfield and tiddlers params to support use of alternative set of tiddlers instead of using current store content (provides filtering support for ImportTiddlersPlugin)
2008.06.04 1.7.1 in getMatchingTiddlers(), reworked conversion of expression for more robust parsing of whitespace, parentheses and javascript operators and allow use of "-" (untagged) //within// expressions
2008.05.19 1.7.0 in getMatchingTiddlers(), use reverseLookup() instead of forEachTiddler() to permit access to tiddlers included via [[IncludePlugin|http://tiddlywiki.abego-software.de/#IncludePlugin]]
2008.05.17 1.6.0 in getMatchingTiddlers(), rewrote expression conversion to handle tags with spaces tag values that are substrings of other tag values.
2008.05.16 1.5.0 added special case using "-" to find UNTAGGED tiddlers
2008.05.15 1.4.0 added "popup" output option
2008.05.14 1.3.4 instead of hijacking getTaggedTiddlers(), added tweak of filterTiddlers() prototype to replace getTaggedTiddlers() with getMatchingTiddler() so that core use of getTaggedTiddlers() does not perform boolean processing of tiddler titles such as [[To Be or not To Be]].  Also, improved "filter error" messages in getMatchingTiddlers() to report tag expression in addition to actual eval error.
2008.04.25 1.3.3 in getTaggedTiddlers(), fixed handling for "not" embedded within a tag
2008.04.21 1.3.2 in getTaggedTiddlers(), fixed handling for initial "NOT" and "NOT(expr)" syntax
2008.04.20 1.3.1 in getTaggedTiddlers(), corrected check for boolean expression to avoid excess processing of tags containing spaces.  Also, improved handling for non-existing tags that contain text of existing tags
2008.04.19 1.3.0 in filterTiddlers(), use getTaggedTiddlers() instead of matchTags(), and then hijack getTaggedTiddlers() to add matchTags() handling
2008.04.19 [*.*.*] plugin size reduction: moved documentation to [[MatchTagsPluginInfo]]
2008.03.25 1.2.0 added optional "sort:fieldname" parameter
2008.03.20 1.1.2 in handler(), replace 'encodeTiddlyLink' with explicit [[...]] brackets to ensure that one-word tiddler titles are properly rendered as TiddlyLinks
2008.02.29 1.1.1 in matchTags(), added handling to skip remaining tiddlers if expression has an error
2008.02.29 1.1.0 refactored to define store.matchTags() and extend store.filterTiddlers()
2008.02.28 1.0.0 initial release
<<<
/***
! Make MatchingTiddlers tiddler temporary

Don't want to save the report of the MatchTags tiddler.
***/

//{{{
config.macros.matchTags.defTags="temporary";
//}}}
/***
|Name|NestedSlidersPlugin|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.4.9|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
!!!!!Documentation
>see [[NestedSlidersPluginInfo]]
!!!!!Configuration
<<<
<<option chkFloatingSlidersAnimate>> allow floating sliders to animate when opening/closing
>Note: This setting can cause 'clipping' problems in some versions of InternetExplorer.
>In addition, for floating slider animation to occur you must also allow animation in general (see [[AdvancedOptions]]).
<<<
!!!!!Revisions
<<<
2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class).  In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
|please see [[NestedSlidersPluginInfo]] for additional revision details|
2005.11.03 - 1.0.0 initial public release.  Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
<<<
!!!!!Code
***/
//{{{
version.extensions.NestedSlidersPlugin= {major: 2, minor: 4, revision: 9, date: new Date(2008,11,15)};

// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkFloatingSlidersAnimate===undefined)
	config.options.chkFloatingSlidersAnimate=false; // avoid clipping problems in IE

// default styles for 'floating' class
setStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
	background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");

// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
	window.removeCookie=function(name) {
		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;'; 
	}
}

config.formatters.push( {
	name: "nestedSliders",
	match: "\\n?\\+{3}",
	terminator: "\\s*\\={3}\\n?",
	lookahead: "\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\@\\[\\>]*\\^)?)?(\\*)?(\\@)?(?:\\{\\{([\\w]+[\\s\\w]*)\\{)?(\\[[^\\]]*\\])?(\\[[^\\]]*\\])?(?:\\}{3})?(\\#[^:]*\\:)?(\\>)?(\\.\\.\\.)?\\s*",
	handler: function(w)
		{
			lookaheadRegExp = new RegExp(this.lookahead,"mg");
			lookaheadRegExp.lastIndex = w.matchStart;
			var lookaheadMatch = lookaheadRegExp.exec(w.source)
			if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
			{
				var defopen=lookaheadMatch[1];
				var cookiename=lookaheadMatch[2];
				var header=lookaheadMatch[3];
				var panelwidth=lookaheadMatch[4];
				var transient=lookaheadMatch[5];
				var hover=lookaheadMatch[6];
				var buttonClass=lookaheadMatch[7];
				var label=lookaheadMatch[8];
				var openlabel=lookaheadMatch[9];
				var panelID=lookaheadMatch[10];
				var blockquote=lookaheadMatch[11];
				var deferred=lookaheadMatch[12];

				// location for rendering button and panel
				var place=w.output;

				// default to closed, no cookie, no accesskey, no alternate text/tip
				var show="none"; var cookie=""; var key="";
				var closedtext=">"; var closedtip="";
				var openedtext="<"; var openedtip="";

				// extra "+", default to open
				if (defopen) show="block";

				// cookie, use saved open/closed state
				if (cookiename) {
					cookie=cookiename.trim().slice(1,-1);
					cookie="chkSlider"+cookie;
					if (config.options[cookie]==undefined)
						{ config.options[cookie] = (show=="block") }
					show=config.options[cookie]?"block":"none";
				}

				// parse label/tooltip/accesskey: [label=X|tooltip]
				if (label) {
					var parts=label.trim().slice(1,-1).split("|");
					closedtext=parts.shift();
					if (closedtext.substr(closedtext.length-2,1)=="=")	
						{ key=closedtext.substr(closedtext.length-1,1); closedtext=closedtext.slice(0,-2); }
					openedtext=closedtext;
					if (parts.length) closedtip=openedtip=parts.join("|");
					else { closedtip="show "+closedtext; openedtip="hide "+closedtext; }
				}

				// parse alternate label/tooltip: [label|tooltip]
				if (openlabel) {
					var parts=openlabel.trim().slice(1,-1).split("|");
					openedtext=parts.shift();
					if (parts.length) openedtip=parts.join("|");
					else openedtip="hide "+openedtext;
				}

				var title=show=='block'?openedtext:closedtext;
				var tooltip=show=='block'?openedtip:closedtip;

				// create the button
				if (header) { // use "Hn" header format instead of button/link
					var lvl=(header.length>5)?5:header.length;
					var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,buttonClass,title);
					btn.onclick=onClickNestedSlider;
					btn.setAttribute("href","javascript:;");
					btn.setAttribute("title",tooltip);
				}
				else
					var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,buttonClass);
				btn.innerHTML=title; // enables use of HTML entities in label

				// set extra button attributes
				btn.setAttribute("closedtext",closedtext);
				btn.setAttribute("closedtip",closedtip);
				btn.setAttribute("openedtext",openedtext);
				btn.setAttribute("openedtip",openedtip);
				btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
				btn.defOpen=defopen!=null; // save default open/closed state (boolean)
				btn.keyparam=key; // save the access key letter ("" if none)
				if (key.length) {
					btn.setAttribute("accessKey",key); // init access key
					btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus
				}
				btn.setAttribute("hover",hover?"true":"false");
				btn.onmouseover=function(ev) {
					// optional 'open on hover' handling
					if (this.getAttribute("hover")=="true" && this.sliderPanel.style.display=='none') {
						document.onclick.call(document,ev); // close transients
						onClickNestedSlider(ev); // open this slider
					}
					// mouseover on button aligns floater position with button
					if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this,this.sliderPanel);
				}

				// create slider panel
				var panelClass=panelwidth?"floatingPanel":"sliderPanel";
				if (panelID) panelID=panelID.slice(1,-1); // trim off delimiters
				var panel=createTiddlyElement(place,"div",panelID,panelClass,null);
				panel.button = btn; // so the slider panel know which button it belongs to
				btn.sliderPanel=panel; // so the button knows which slider panel it belongs to
				panel.defaultPanelWidth=(panelwidth && panelwidth.length>2)?panelwidth.slice(1,-1):"";
				panel.setAttribute("transient",transient=="*"?"true":"false");
				panel.style.display = show;
				panel.style.width=panel.defaultPanelWidth;
				panel.onmouseover=function(event) // mouseover on panel aligns floater position with button
					{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this.button,this); }

				// render slider (or defer until shown) 
				w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
				if ((show=="block")||!deferred) {
					// render now if panel is supposed to be shown or NOT deferred rendering
					w.subWikify(blockquote?createTiddlyElement(panel,"blockquote"):panel,this.terminator);
					// align floater position with button
					if (window.adjustSliderPos) window.adjustSliderPos(place,btn,panel);
				}
				else {
					var src = w.source.substr(w.nextMatch);
					var endpos=findMatchingDelimiter(src,"+++","===");
					panel.setAttribute("raw",src.substr(0,endpos));
					panel.setAttribute("blockquote",blockquote?"true":"false");
					panel.setAttribute("rendered","false");
					w.nextMatch += endpos+3;
					if (w.source.substr(w.nextMatch,1)=="\n") w.nextMatch++;
				}
			}
		}
	}
)

function findMatchingDelimiter(src,starttext,endtext) {
	var startpos = 0;
	var endpos = src.indexOf(endtext);
	// check for nested delimiters
	while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
		// count number of nested 'starts'
		var startcount=0;
		var temp = src.substring(startpos,endpos-1);
		var pos=temp.indexOf(starttext);
		while (pos!=-1)  { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
		// set up to check for additional 'starts' after adjusting endpos
		startpos=endpos+endtext.length;
		// find endpos for corresponding number of matching 'ends'
		while (startcount && endpos!=-1) {
			endpos = src.indexOf(endtext,endpos+endtext.length);
			startcount--;
		}
	}
	return (endpos==-1)?src.length:endpos;
}
//}}}
//{{{
window.onClickNestedSlider=function(e)
{
	if (!e) var e = window.event;
	var theTarget = resolveTarget(e);
	while (theTarget && theTarget.sliderPanel==undefined) theTarget=theTarget.parentNode;
	if (!theTarget) return false;
	var theSlider = theTarget.sliderPanel;
	var isOpen = theSlider.style.display!="none";

	// if SHIFT-CLICK, dock panel first (see [[MoveablePanelPlugin]])
	if (e.shiftKey && config.macros.moveablePanel) config.macros.moveablePanel.dock(theSlider,e);

	// toggle label
	theTarget.innerHTML=isOpen?theTarget.getAttribute("closedText"):theTarget.getAttribute("openedText");
	// toggle tooltip
	theTarget.setAttribute("title",isOpen?theTarget.getAttribute("closedTip"):theTarget.getAttribute("openedTip"));

	// deferred rendering (if needed)
	if (theSlider.getAttribute("rendered")=="false") {
		var place=theSlider;
		if (theSlider.getAttribute("blockquote")=="true")
			place=createTiddlyElement(place,"blockquote");
		wikify(theSlider.getAttribute("raw"),place);
		theSlider.setAttribute("rendered","true");
	}

	// show/hide the slider
	if(config.options.chkAnimate && (!hasClass(theSlider,'floatingPanel') || config.options.chkFloatingSlidersAnimate))
		anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		theSlider.style.display = isOpen ? "none" : "block";

	// reset to default width (might have been changed via plugin code)
	theSlider.style.width=theSlider.defaultPanelWidth;

	// align floater panel position with target button
	if (!isOpen && window.adjustSliderPos) window.adjustSliderPos(theSlider.parentNode,theTarget,theSlider);

	// if showing panel, set focus to first 'focus-able' element in panel
	if (theSlider.style.display!="none") {
		var ctrls=theSlider.getElementsByTagName("*");
		for (var c=0; c<ctrls.length; c++) {
			var t=ctrls[c].tagName.toLowerCase();
			if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")
				{ try{ ctrls[c].focus(); } catch(err){;} break; }
		}
	}
	var cookie=theTarget.sliderCookie;
	if (cookie && cookie.length) {
		config.options[cookie]=!isOpen;
		if (config.options[cookie]!=theTarget.defOpen) window.saveOptionCookie(cookie);
		else window.removeCookie(cookie); // remove cookie if slider is in default display state
	}

	// prevent SHIFT-CLICK from being processed by browser (opens blank window... yuck!)
	// prevent clicks *within* a slider button from being processed by browser
	// but allow plain click to bubble up to page background (to close transients, if any)
	if (e.shiftKey || theTarget!=resolveTarget(e))
		{ e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); }
	Popup.remove(); // close open popup (if any)
	return false;
}
//}}}
//{{{
// click in document background closes transient panels 
document.nestedSliders_savedOnClick=document.onclick;
document.onclick=function(ev) { if (!ev) var ev=window.event; var target=resolveTarget(ev);

	if (document.nestedSliders_savedOnClick)
		var retval=document.nestedSliders_savedOnClick.apply(this,arguments);
	// if click was inside a popup... leave transient panels alone
	var p=target; while (p) if (hasClass(p,"popup")) break; else p=p.parentNode;
	if (p) return retval;
	// if click was inside transient panel (or something contained by a transient panel), leave it alone
	var p=target; while (p) {
		if ((hasClass(p,"floatingPanel")||hasClass(p,"sliderPanel"))&&p.getAttribute("transient")=="true") break;
		p=p.parentNode;
	}
	if (p) return retval;
	// otherwise, find and close all transient panels...
	var all=document.all?document.all:document.getElementsByTagName("DIV");
	for (var i=0; i<all.length; i++) {
		 // if it is not a transient panel, or the click was on the button that opened this panel, don't close it.
		if (all[i].getAttribute("transient")!="true" || all[i].button==target) continue;
		// otherwise, if the panel is currently visible, close it by clicking it's button
		if (all[i].style.display!="none") window.onClickNestedSlider({target:all[i].button})
		if (!hasClass(all[i],"floatingPanel")&&!hasClass(all[i],"sliderPanel")) all[i].style.display="none";
	}
	return retval;
};
//}}}
//{{{
// adjust floating panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel) {
	if (hasClass(panel,"floatingPanel") && !hasClass(panel,"undocked")) {
		// see [[MoveablePanelPlugin]] for use of 'undocked'
		var rightEdge=document.body.offsetWidth-1;
		var panelWidth=panel.offsetWidth;
		var left=0;
		var top=btn.offsetHeight; 
		if (place.style.position=="relative" && findPosX(btn)+panelWidth>rightEdge) {
			left-=findPosX(btn)+panelWidth-rightEdge; // shift panel relative to button
			if (findPosX(btn)+left<0) left=-findPosX(btn); // stay within left edge
		}
		if (place.style.position!="relative") {
			var left=findPosX(btn);
			var top=findPosY(btn)+btn.offsetHeight;
			var p=place; while (p && !hasClass(p,'floatingPanel')) p=p.parentNode;
			if (p) { left-=findPosX(p); top-=findPosY(p); }
			if (left+panelWidth>rightEdge) left=rightEdge-panelWidth;
			if (left<0) left=0;
		}
		panel.style.left=left+"px"; panel.style.top=top+"px";
	}
}
//}}}
//{{{
// TW2.1 and earlier:
// hijack Slider stop handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function()
	{ this.coreStop.apply(this,arguments); this.element.style.overflow = "visible"; }

// TW2.2+
// hijack Morpher stop handler so sliderPanel/floatingPanel overflow is visible after animation has completed
if (version.major+.1*version.minor+.01*version.revision>=2.2) {
	Morpher.prototype.coreStop = Morpher.prototype.stop;
	Morpher.prototype.stop = function() {
		this.coreStop.apply(this,arguments);
		var e=this.element;
		if (hasClass(e,"sliderPanel")||hasClass(e,"floatingPanel")) {
			// adjust panel overflow and position after animation
			e.style.overflow = "visible";
			if (window.adjustSliderPos) window.adjustSliderPos(e.parentNode,e.button,e);
		}
	};
}
//}}}
/***
|Name|NestedSlidersPluginInfo|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.4.9|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|documentation for NestedSlidersPlugin|
This plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content.
!!!!!Usage
<<<
Use {{{+++}}} and {{{===}}} to delimit the slider content.  You can also 'nest' these sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created.  This is most useful when converting existing in-line text content to create in-line annotations, footnotes, context-sensitive help, or other subordinate information displays.

Additional optional syntax elements let you specify
*default to open
*cookiename
*heading level
*floater (with optional CSS width value)
*transient display (clicking elsewhere closes panel)
*open on hover (without needing to click)
*custom class/label/tooltip/accesskey
*alternate label/tooltip (displayed when panel is open)
*panelID (for later use with {{{<<DOM>>}}} macro.  See [[DOMTweaksPlugin]])
*automatic blockquote style on panel
*deferred rendering of panel content
The complete syntax, using all options, is:
//{{{
++++(cookiename)!!!!!^width^*@{{class{[label=key|tooltip][altlabel|alttooltip]}}}#panelID:>...
content goes here
===
//}}}
where:
* ''"""+++""" (or """++++""") and """==="""''<br>marks the start and end of the slider definition, respectively.  When the extra {{{+}}} is used, the slider will be open when initially displayed.
* ''"""(cookiename)"""''<br>saves the slider opened/closed state, and restores this state whenever the slider is re-rendered.
* ''"""! through !!!!!"""''<br>displays the slider label using a formatted headline (Hn) style instead of a button/link style
* ''"""^width^ (or just ^)"""''<br>makes the slider 'float' on top of other content rather than shifting that content downward.  'width' must be a valid CSS value (e.g., "30em", "180px", "50%", etc.).  If omitted, the default width is "auto" (i.e., fit to content)
* ''"""*"""''<br>denotes "transient display": when a click occurs elsewhere in the document, the slider/floating panel will be automatically closed.  This is useful for creating 'pulldown menus' that automatically go away after they are used.  //Note: using SHIFT-click on a slider label will open/close that slider without triggering the automatic closing of any transient slider panels that are currently displayed, permitting ''temporary'' display of several transient panels at once.//
* ''"""@"""''<br>denotes "open on hover": the slider/floating panel will be automatically opened as soon as the mouse moves over the slider label, without requiring a click.
* ''"""{{class{[label=key|tooltip][altlabel|alttooltip]}}}"""''<br>uses label/tooltip/accesskey.  """{{class{...}}}""", """=key""", """|tooltip""" and """[altlabel|alttooltip]""" are optional.  'class' is any valid CSS class name, used to style the slider label text.  'key' must be a ''single letter only''.  altlabel/alttooltip specify alternative label/tooltip for use when slider/floating panel is displayed.  //Note: you can use HTML syntax within the label text to include HTML entities (e.g., {{{&raquo;}}} (&raquo;) or {{{&#x25ba;}}} (&#x25ba;), or even embedded images (e.g., {{{<img src="images/eric3.gif">}}}).//
* ''"""#panelID:"""''<br>defines a unique DOM element ID that is assigned to the panel element used to display the slider content.  This ID can then be used later to reposition the panel using the {{{<<DOM move id>>}}} macro (see [[DOMTweaksPlugin]]), or to access/modify the panel element through use of {{{document.getElementById(...)}}}) javascript code in a plugin or inline script.
* ''""">"""''<br>automatically adds blockquote formatting to slider content
* ''"""..."""''<br>defers rendering of closed sliders until the first time they are opened.  //Note: deferred rendering may produce unexpected results in some cases.  Use with care.//

//Note: to make slider definitions easier to read and recognize when editing a tiddler, newlines immediately following the {{{+++}}} 'start slider' or preceding the {{{===}}} 'end slider' sequence are automatically supressed so that excess whitespace is eliminated from the output.//
<<<
!!!!!Examples
<<<
simple in-line slider: 
{{{
+++
   content
===
}}}
+++
   content
===
----
use a custom label and tooltip: 
{{{
+++[label|tooltip]
   content
===
}}}
+++[label|tooltip]
   content
===
----
content automatically blockquoted: 
{{{
+++>
   content
===
}}}
+++>
   content
===
----
all options (except cookie) //(default open, heading, sized floater, transient, open on hover, class, label/tooltip/key, blockquoted, deferred)//
{{{
++++!!!^30em^*@{{big{[label=Z|click or press Alt-Z to open]}}}>...
   content
===
}}}
++++!!!^30em^*@{{big{[label=Z|click or press Alt-Z to open]}}}>...
   content
===
----
complex nesting example:
{{{
+++[get info...=I|click for information or press Alt-I]
	put some general information here,
	plus a floating panel with more specific info:
	+++^10em^[view details...|click for details]
		put some detail here, which could in turn contain a transient panel,
		perhaps with a +++^25em^*[glossary definition]explaining technical terms===
	===
===
}}}
+++[get info...=I|click for information or press Alt-I]
	put some general information here,
	plus a floating panel with more specific info:
	+++^10em^[view details...|click for details]
		put some detail here, which could in turn contain a transient panel,
		perhaps with a +++^25em^*[glossary definition]explaining technical terms===
	===
===
----
embedded image as slider button
{{{
+++[<img src=images/eric3.gif>|click me!]>
	{{big{OUCH!}}}
===
}}}
+++[<img src=images/eric3.gif>|click me!]>
	{{big{OUCH!}}}
===
<<<
!!!!!Revisions
<<<
2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class).  In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
2008.11.13 - 2.4.8 in document.onclick(), if transient panel is not a sliderPanel or floatingPanel, hide it via CSS
2008.10.05 - 2.4.7 in onClickNestedSlider(), added try/catch around focus() call to prevent IE error if input field being focused on is currently not visible.
2008.09.07 - 2.4.6 added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.06.07 - 2.4.5 in 'onmouseover' handler for 'open on hover' slider buttons, use call() method when invoking document.onclick function (avoids error in IE)
2008.06.07 - 2.4.4 changed default for chkFloatingSlidersAnimate to FALSE to avoid clipping problem on some browsers (IE).  Updated Morpher hijack (again) to adjust regular sliderPanel styles as well as floatingPanel styles.
2008.05.07 - 2.4.3 updated Morpher hijack to adjust floatingPanel styles after animation without affecting other animated elements (i.e. popups).  Also, updated adjustSliderPos() to account for scrollwidth and use core findWindowWidth().
2008.04.02 - 2.4.2 in onClickNestedSlider, handle clicks on elements contained //within// slider buttons (e.g., when using HTML to display an image as a slider button).
2008.04.01 - 2.4.1 open on hover also triggers document.onclick to close other transient sliders
2008.04.01 - 2.4.0 re-introduced 'open on hover' feature using "@" symbol
2008.03.26 - 2.3.5 in document.onclick(), if click is in popup, don't dismiss transient panel (if any)
2008.01.08 - [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 - 2.3.4 added hijack for Animator.prototype.startAnimating().  Previously, the plugin code simply set the overflow to "visible" after animation.  This code tweak corrects handling of elements that were styled with overflow=hidden/auto/scroll before animation by saving the overflow style and then restoring it after animation has completed.
2007.12.17 - 2.3.3 use hasClass() instead of direct comparison to test for "floatingPanel" class.  Allows floating panels to have additional classes assigned to them (i.e., by AnimationEffectsPlugin).
2007.11.14 - 2.3.2 in onClickNestedSlider(), prevent SHIFT-click events from opening a new, empty browser window by setting "cancelBubble=true" and calling "stopPropagation()".  Note: SHIFT-click is still processed as a normal click (i.e., it toggles the slider panel display).  Also, using SHIFT-click will prevent 'transient' sliders from being automatically closed when another slider is opened, allowing you to *temporarily* display several transient sliders at once.
2007.07.26 - 2.3.1 in document.onclick(), propagate return value from hijacked core click handler to consume OR bubble up click as needed.  Fixes "IE click disease", whereby nearly every mouse click causes a page transition.
2007.07.20 - 2.3.0 added syntax for setting panel ID (#panelID:).  This allows individual slider panels to be repositioned within tiddler content simply by giving them a unique ID and then moving them to the desired location using the {{{<<DOM move id>>}}} macro.
2007.07.19 - 2.2.0 added syntax for alttext and alttip (button label and tooltip to be displayed when panel is open)
2007.07.14 - 2.1.2 corrected use of 'transient' attribute in IE to prevent (non-recursive) infinite loop
2007.07.12 - 2.1.0 replaced use of "*" for 'open/close on rollover' (which didn't work too well).  "*" now indicates 'transient' panels that are automatically closed if a click occurs somewhere else in the document.  This permits use of nested sliders to create nested "pulldown menus" that automatically disappear after interaction with them has been completed.  Also, in onClickNestedSlider(), use "theTarget.sliderCookie", instead of "this.sliderCookie" to correct cookie state tracking when automatically dismissing transient panels.
2007.06.10 - 2.0.5 add check to ensure that window.adjustSliderPanel() is defined before calling it (prevents error on shutdown when mouse event handlers are still defined)
2007.05.31 - 2.0.4 add handling to invoke adjustSliderPanel() for onmouseover events on slider button and panel.  This allows the panel position to be re-synced when the button position shifts due to changes in unrelated content above it on the page.  (thanks to Harsha for bug report)
2007.03.30 - 2.0.3 added chkFloatingSlidersAnimate (default to FALSE), so that slider animation can be disabled independent of the overall document animation setting (avoids strange rendering and focus problems in floating panels)
2007.03.01 - 2.0.2 for TW2.2+, hijack Morpher.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends
2007.03.01 - 2.0.1 in hijack for Slider.prototype.stop, use apply() to pass params to core function
2006.07.28 - 2.0.0 added custom class syntax around label/tip/key syntax: {{{{{classname{[label=key|tip]}}}}}}
2006.07.25 - 1.9.3 when parsing slider, save default open/closed state in button element, then in onClickNestedSlider(), if slider state matches saved default, instead of saving cookie, delete it.  Significantly reduces the 'cookie overhead' when default slider states are used.
2006.06.29 - 1.9.2 in onClickNestedSlider(), when setting focus to first control, skip over type="hidden"
2006.06.22 - 1.9.1 added panel.defaultPanelWidth to save requested panel width, even after resizing has changed the style value
2006.05.11 - 1.9.0 added optional '^width^' syntax for floating sliders and '=key' syntax for setting an access key on a slider label
2006.05.09 - 1.8.0 in onClickNestedSlider(), when showing panel, set focus to first child input/textarea/select element
2006.04.24 - 1.7.8 in adjustSliderPos(), if floating panel is contained inside another floating panel, subtract offset of containing panel to find correct position
2006.02.16 - 1.7.7 corrected deferred rendering to account for use-case where show/hide state is tracked in a cookie
2006.02.15 - 1.7.6 in adjustSliderPos(), ensure that floating panel is positioned completely within the browser window (i.e., does not go beyond the right edge of the browser window)
2006.02.04 - 1.7.5 add 'var' to unintended global variable declarations to avoid FireFox 1.5.0.1 crash bug when assigning to globals
2006.01.18 - 1.7.4 only define adjustSliderPos() function if it has not already been provided by another plugin.  This lets other plugins 'hijack' the function even when they are loaded first.
2006.01.16 - 1.7.3 added adjustSliderPos(place,btn,panel,panelClass) function to permit specialized logic for placement of floating panels.  While it provides improved placement for many uses of floating panels, it exhibits a relative offset positioning error when used within *nested* floating panels.  Short-term workaround is to only adjust the position for 'top-level' floaters.
2006.01.16 - 1.7.2 added button property to slider panel elements so that slider panel can tell which button it belongs to.  Also, re-activated and corrected animation handling so that nested sliders aren't clipped by hijacking Slider.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends
2006.01.14 - 1.7.1 added optional "^" syntax for floating panels.  Defines new CSS class, ".floatingPanel", as an alternative for standard in-line ".sliderPanel" styles.
2006.01.14 - 1.7.0 added optional "*" syntax for rollover handling to show/hide slider without requiring a click (Based on a suggestion by tw4efl)
2006.01.03 - 1.6.2 When using optional "!" heading style, instead of creating a clickable "Hn" element, create an "A" element inside the "Hn" element.  (allows click-through in SlideShowPlugin, which captures nearly all click events, except for hyperlinks)
2005.12.15 - 1.6.1 added optional "..." syntax to invoke deferred ('lazy') rendering for initially hidden sliders
removed checkbox option for 'global' application of lazy sliders
2005.11.25 - 1.6.0 added optional handling for 'lazy sliders' (deferred rendering for initially hidden sliders)
2005.11.21 - 1.5.1 revised regular expressions: if present, a single newline //preceding// and/or //following// a slider definition will be suppressed so start/end syntax can be place on separate lines in the tiddler 'source' for improved readability.  Similarly, any whitespace (newlines, tabs, spaces, etc.) trailing the 'start slider' syntax or preceding the 'end slider' syntax is also suppressed.
2005.11.20 - 1.5.0 added (cookiename) syntax for optional tracking and restoring of slider open/close state
2005.11.11 - 1.4.0 added !!!!! syntax to render slider label as a header (Hn) style instead of a button/link style
2005.11.07 - 1.3.0 removed alternative syntax {{{(((}}} and {{{)))}}} (so they can be used by other formatting extensions) and simplified/improved regular expressions to trim multiple excess newlines
2005.11.05 - 1.2.1 changed name to NestedSlidersPlugin
2005.11.04 - 1.2.0 added alternative character-mode syntax {{{(((}}} and {{{)))}}}
tweaked "eat newlines" logic for line-mode {{{+++}}} and {{{===}}} syntax
2005.11.03 - 1.1.1 fixed toggling of default tooltips ("more..." and "less...") when a non-default button label is used.  code cleanup, added documentation
2005.11.03 - 1.1.0 changed delimiter syntax from {{{(((}}} and {{{)))}}} to {{{+++}}} and {{{===}}}.  changed name to EasySlidersPlugin
2005.11.03 - 1.0.0 initial public release
<<<
<<tiddler SlideSubstyle##levelTwo>>
{{comment{
picture notebook/pen possible student

* Allow students to annotate content tiddlers (slides, chapter elements)
** during presentation
** while using textbook (c.f. margin notes)
* Students should have singe click access to modify all notes on a tiddler
* Notes should not be lost when upgrading the Coursebook.
}}}
* references
* chapters
* presentations and notes
* per student bookmarks
* search
* related tiddlers

{{comment{
There are multiple plugins for related tiddlers from touchgraph to tag based lists.
Choosing the right mechanism is still an open issue.
}}}
*  references
**            separate chapters/index for quick access
*        chapters
**            full treatment of topic.
**            1:1 more or less with presentations maybe not a good idea but
*        presentations and notes
**            if student took notes during talk, they can review instructor notes on slides link to chapters/reference material
*        per student bookmarks
*  link at top of tiddler append to bookmark list in main menu. Edit link for bookmarks allows student to reorder/format for access
* search
** search works like google searh, terms in quotes, +/- to add subtract matched terms plus can search in titles, text or tags
* related tiddlers
** a few ways to visualize. Still in progress what mechanism to use. Allows students to investigate other topics of interest, find info outside of a chapter tiddler. Make better associations between concepts.

Follow along with presentations
* student view includes instructor notes and notebook area
* students follow along and with slide show and annotate slides as needed
* students can also read instructor notes with background material or important points from slide reenforcing the goal of the slide.
/% {{ "$1" != "$" + "1" ? "$1"  : "Open links in %0"}} 
    computed param when called as: <<tiddler OpenStoryButton with: "button label" "tooltip" > >
    $1  is set to "button label" and $2 is set to "tooltip" if no params are specified, $1 and $2 are
    not substituted. So the computed param checks to see if $1 was replaced (by concatenating
    $ and 1 so I don't have the obviously false "$1" != "$1") and if it was uses it. If it wasn't use
    the alternate string with %1 being the name of the parent tiddler.

   No return after the % and / so no newline is rendered when included.
%/{{openStoryButton{
<<openStory {{tiddler.title}} {{ "$1" != "$" + "1" ? "$1"  : "Open links in %0"}} {{ "$2" != "$" + "2" ? "$2"  : "Open all of the links in %0 according to the check boxes"}}>>
''The first/topmost checked box determines how tidders are opened''
<<option chkStoryClose>> close other tiddlers when opening
<<option chkStoryBottom>> open tiddlers at bottom of story column
<<option chkStoryTop>> open tiddlers at top of story column
}}}
Once you have created content, you want to be able to view it. There are three ways to open a chapter:
# use the title link in the Chapter section of the MainMenu
# use the dropdown select box in the Chapter section of the MainMenu to have more control over how the chapter opens, and use it to open multiple chapters
# use the chapter control tiddler (accessed with the open link next to the chapter title links) to change viewing options and open the entire chapter or select a specific tiddler in the chapter to open).

!! Using the Title Link

Simply click on the title link for the chapter and the story column will be replaced (except for tiddlers being edited) by the content of the chapter.
Depending on the [[configuration settings|StorySaverPluginInfo##Configuration]] for stories you can prevent the chapter from taking over
the story column, but it may be easier to use the pulldown select box if you want to open multiple chapters, or keep your current tiddlers displayed.

!! Using the Selection Pulldown

The selection pulldown is directly below the Chapter heading in the MainMenu. At the end of the selection menu are the viewing options that can be selected to:
* Close tiddlers currently in the story column (except those being edited) and open the chapter's tiddlers
* Open the chapters tiddlers at the top of the story column (keeping currently displayed tiddlers)
* Open the chapters tiddlers at the end of the story column  (keeping currently displayed tiddlers)

Selecting "close other tiddlers" hides the other two options. Both open at top and open at bottom can be selected, open at top has priority.

Once you have chosen your viewing options, you can select chapters from the dropdown box and they will open as you have specified

!! Opening a Chapter Using .the Control Tiddler

A third way of opening a chapter is to use the chapter's control tiddler. To access the control tiddler, use the {{{(open)}}} link net to the title link in the Chapter section of the MainMenu. Once you open the control tiddler, you can see all the tiddlers that are part of that chapter and you can select an individual tiddler for editing or disply by clicking on the link. If you want to open the entire chapter, you can select the viewing options and click on the button to open the chapter.

To display a presentation (slides)  for editing/printing
* Choose the presentation from the pulldown list under the presentation header (for multi-tiddler presentations)
This will display all the tiddlers in the multi-tiddler presentation. Then you can edit them normally, or use your browsers print function to print the list of tiddlers, slide notes and notebooks. 

* Choose the {{{(open)}}} link next to the presentation title (for single tiddler presentations)
This will display the control tiddler for the presentation that also contains the slide elements.

Using the {{{(open)}}} link for multi-tiddler presentations will display the control tiddler for the presentation. In this control tiddler you can
* edit the tiddler to add/remove slides
To open to coursebook you can use: ~FireFox, Internet Explorer, Safari (Safari users, see the instructor first)
# Find the coursebook on the usb stick at:  ''\training\S2\coursebook\coursebook.html''
# Open the coursebook on the usb stick  or copy the material to your hard drive and open the coursebook from there
# Allow javascript execution for the coursebook

You should see something like:
@@display: block;text-align: center;[img(50%,)[Frontscreen.png]]@@
If you don't please see the instructor.
{{overlay1{}}}{{overlay2{}}}{{overlay3{}}}{{overlay4{}}}{{overlay5{}}}{{overlay6{}}}
! Toolbar command for tiddlers tagged with content.

|~ContentViewToolbar|AddTiddlerToBookmarks closeTiddler closeOthers editTiddler refresh jump >  fields permalink references < |
http://www.pdfforge.org/
<!--{{{-->
<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>
<span style='display:none' macro='tiddler SiteStartup'></span>
<!--}}}-->
/***
|<html><a name="Top"/></html>''Name:''|PartTiddlerPlugin|
|''Version:''|1.0.9 (2007-07-14)|
|''Source:''|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Table of Content<html><a name="TOC"/></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Description',null, event)">Description, Syntax</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Applications',null, event)">Applications</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('LongTiddler',null, event)">Refering to Paragraphs of a Longer Tiddler</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Citation',null, event)">Citation Index</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('TableCells',null, event)">Creating "multi-line" Table Cells</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Tabs',null, event)">Creating Tabs</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Sliders',null, event)">Using Sliders</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Revisions',null, event)">Revision History</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Code',null, event)">Code</a></html>
!Description<html><a name="Description"/></html>
With the {{{<part aPartName> ... </part>}}} feature you can structure your tiddler text into separate (named) parts. 
Each part can be referenced as a "normal" tiddler, using the "//tiddlerName//''/''//partName//" syntax (e.g. "About/Features").  E.g. you may create links to the parts (e.g. {{{[[Quotes/BAX95]]}}} or {{{[[Hobbies|AboutMe/Hobbies]]}}}), use it in {{{<<tiddler...>>}}} or {{{<<tabs...>>}}} macros etc.


''Syntax:'' 
|>|''<part'' //partName// [''hidden''] ''>'' //any tiddler content// ''</part>''|
|//partName//|The name of the part. You may reference a part tiddler with the combined tiddler name "//nameOfContainerTidder//''/''//partName//. <br />If you use a partName containing spaces you need to quote it (e.g. {{{"Major Overview"}}} or {{{[[Shortcut List]]}}}).|
|''hidden''|When defined the content of the part is not displayed in the container tiddler. But when the part is explicitly referenced (e.g. in a {{{<<tiddler...>>}}} macro or in a link) the part's content is displayed.|
|<html><i>any&nbsp;tiddler&nbsp;content</i></html>|<html>The content of the part.<br>A part can have any content that a "normal" tiddler may have, e.g. you may use all the formattings and macros defined.</html>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Applications<html><a name="Applications"/></html>
!!Refering to Paragraphs of a Longer Tiddler<html><a name="LongTiddler"/></html>
Assume you have written a long description in a tiddler and now you want to refer to the content of a certain paragraph in that tiddler (e.g. some definition.) Just wrap the text with a ''part'' block, give it a nice name, create a "pretty link" (like {{{[[Discussion Groups|Introduction/DiscussionGroups]]}}}) and you are done.

Notice this complements the approach to first writing a lot of small tiddlers and combine these tiddlers to one larger tiddler in a second step (e.g. using the {{{<<tiddler...>>}}} macro). Using the ''part'' feature you can first write a "classic" (longer) text that can be read "from top to bottom" and later "reuse" parts of this text for some more "non-linear" reading.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Citation Index<html><a name="Citation"/></html>
Create a tiddler "Citations" that contains your "citations". 
Wrap every citation with a part and a proper name. 

''Example''
{{{
<part BAX98>Baxter, Ira D. et al: //Clone Detection Using Abstract Syntax Trees.// 
in //Proc. ICSM//, 1998.</part>

<part BEL02>Bellon, Stefan: //Vergleich von Techniken zur Erkennung duplizierten Quellcodes.// 
Thesis, Uni Stuttgart, 2002.</part>

<part DUC99>Ducasse, Stéfane et al: //A Language Independent Approach for Detecting Duplicated Code.// 
in //Proc. ICSM//, 1999.</part>
}}}

You may now "cite" them just by using a pretty link like {{{[[Citations/BAX98]]}}} or even more pretty, like this {{{[[BAX98|Citations/BAX98]]}}}.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating "multi-line" Table Cells<html><a name="TableCells"/></html>
You may have noticed that it is hard to create table cells with "multi-line" content. E.g. if you want to create a bullet list inside a table cell you cannot just write the bullet list
{{{
* Item 1
* Item 2
* Item 3
}}}
into a table cell (i.e. between the | ... | bars) because every bullet item must start in a new line but all cells of a table row must be in one line.

Using the ''part'' feature this problem can be solved. Just create a hidden part that contains the cells content and use a {{{<<tiddler >>}}} macro to include its content in the table's cell.

''Example''
{{{
|!Subject|!Items|
|subject1|<<tiddler ./Cell1>>|
|subject2|<<tiddler ./Cell2>>|

<part Cell1 hidden>
* Item 1
* Item 2
* Item 3
</part>
...
}}}

Notice that inside the {{{<<tiddler ...>>}}} macro you may refer to the "current tiddler" using the ".".

BTW: The same approach can be used to create bullet lists with items that contain more than one line.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating Tabs<html><a name="Tabs"/></html>
The build-in {{{<<tabs ...>>}}} macro requires that you defined an additional tiddler for every tab it displays. When you want to have "nested" tabs you need to define a tiddler for the "main tab" and one for every tab it contains. I.e. the definition of a set of tabs that is visually displayed at one place is distributed across multiple tiddlers.

With the ''part'' feature you can put the complete definition in one tiddler, making it easier to keep an overview and maintain the tab sets.

''Example''
The standard tabs at the sidebar are defined by the following eight tiddlers:
* SideBarTabs
* TabAll
* TabMore
* TabMoreMissing
* TabMoreOrphans
* TabMoreShadowed
* TabTags
* TabTimeline

Instead of these eight tiddlers one could define the following SideBarTabs tiddler that uses the ''part'' feature:
{{{
<<tabs txtMainTab 
    Timeline Timeline SideBarTabs/Timeline 
    All 'All tiddlers' SideBarTabs/All 
    Tags 'All tags' SideBarTabs/Tags 
    More 'More lists' SideBarTabs/More>>
<part Timeline hidden><<timeline>></part>
<part All hidden><<list all>></part>
<part Tags hidden><<allTags>></part>
<part More hidden><<tabs txtMoreTab 
    Missing 'Missing tiddlers' SideBarTabs/Missing 
    Orphans 'Orphaned tiddlers' SideBarTabs/Orphans 
    Shadowed 'Shadowed tiddlers' SideBarTabs/Shadowed>></part>
<part Missing hidden><<list missing>></part>
<part Orphans hidden><<list orphans>></part>
<part Shadowed hidden><<list shadowed>></part>
}}}

Notice that you can easily "overwrite" individual parts in separate tiddlers that have the full name of the part.

E.g. if you don't like the classic timeline tab but only want to see the 100 most recent tiddlers you could create a tiddler "~SideBarTabs/Timeline" with the following content:
{{{
<<forEachTiddler 
		sortBy 'tiddler.modified' descending 
		write '(index < 100) ? "* [["+tiddler.title+"]]\n":""'>>
}}}
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Using Sliders<html><a name="Sliders"/></html>
Very similar to the build-in {{{<<tabs ...>>}}} macro (see above) the {{{<<slider ...>>}}} macro requires that you defined an additional tiddler that holds the content "to be slid". You can avoid creating this extra tiddler by using the ''part'' feature

''Example''
In a tiddler "About" we may use the slider to show some details that are documented in the tiddler's "Details" part.
{{{
...
<<slider chkAboutDetails About/Details details "Click here to see more details">>
<part Details hidden>
To give you a better overview ...
</part>
...
}}}

Notice that putting the content of the slider into the slider's tiddler also has an extra benefit: When you decide you need to edit the content of the slider you can just doubleclick the content, the tiddler opens for editing and you can directly start editing the content (in the part section). In the "old" approach you would doubleclick the tiddler, see that the slider is using tiddler X, have to look for the tiddler X and can finally open it for editing. So using the ''part'' approach results in a much short workflow.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Revision history<html><a name="Revisions"/></html>
* v1.0.9 (2007-07-14)
** Bugfix: Error when using the SideBarTabs example and switching between "More" and "Shadow". Thanks to cmari for reporting the issue.
* v1.0.8 (2007-06-16)
** Speeding up display of tiddlers containing multiple pard definitions. Thanks to Paco Rivière for reporting the issue.
** Support "./partName" syntax inside <<tabs ...>> macro
* v1.0.7 (2007-03-07)
** Bugfix: <<tiddler "./partName">> does not always render correctly after a refresh (e.g. like it happens when using the "Include" plugin). Thanks to Morris Gray for reporting the bug.
* v1.0.6 (2006-11-07)
** Bugfix: cannot edit tiddler when UploadPlugin by Bidix is installed. Thanks to José Luis González Castro for reporting the bug.
* v1.0.5 (2006-03-02)
** Bugfix: Example with multi-line table cells does not work in IE6. Thanks to Paulo Soares for reporting the bug.
* v1.0.4 (2006-02-28)
** Bugfix: Shadow tiddlers cannot be edited (in TW 2.0.6). Thanks to Torsten Vanek for reporting the bug.
* v1.0.3 (2006-02-26)
** Adapt code to newly introduced Tiddler.prototype.isReadOnly() function (in TW 2.0.6). Thanks to Paulo Soares for reporting the problem.
* v1.0.2 (2006-02-05)
** Also allow other macros than the "tiddler" macro use the "." in the part reference (to refer to "this" tiddler)
* v1.0.1 (2006-01-27)
** Added Table of Content for plugin documentation. Thanks to RichCarrillo for suggesting.
** Bugfix: newReminder plugin does not work when PartTiddler is installed. Thanks to PauloSoares for reporting.
* v1.0.0 (2006-01-25)
** initial version
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Code<html><a name="Code"/></html>
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
***/
//{{{
//============================================================================
//                           PartTiddlerPlugin

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



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

if (!window.abego) window.abego = {};
if (version.major < 2) alertAndThrow("PartTiddlerPlugin requires TiddlyWiki 2.0 or newer.");

//============================================================================
// Common Helpers

// Looks for the next newline, starting at the index-th char of text. 
//
// If there are only whitespaces between index and the newline 
// the index behind the newline is returned, 
// otherwise (or when no newline is found) index is returned.
//
var skipEmptyEndOfLine = function(text, index) {
	var re = /(\n|[^\s])/g;
	re.lastIndex = index;
	var result = re.exec(text);
	return (result && text.charAt(result.index) == '\n') 
			? result.index+1
			: index;
}


//============================================================================
// Constants

var partEndOrStartTagRE = /(<\/part>)|(<part(?:\s+)((?:[^>])+)>)/mg;
var partEndTagREString = "<\\/part>";
var partEndTagString = "</part>";

//============================================================================
// Plugin Specific Helpers

// Parse the parameters inside a <part ...> tag and return the result.
//
// @return [may be null] {partName: ..., isHidden: ...}
//
var parseStartTagParams = function(paramText) {
	var params = paramText.readMacroParams();
	if (params.length == 0 || params[0].length == 0) return null;
	
	var name = params[0];
	var paramsIndex = 1;
	var hidden = false;
	if (paramsIndex < params.length) {
		hidden = params[paramsIndex] == "hidden";
		paramsIndex++;
	}
	
	return {
		partName: name, 
		isHidden: hidden
	};
}

// Returns the match to the next (end or start) part tag in the text, 
// starting the search at startIndex.
// 
// When no such tag is found null is returned, otherwise a "Match" is returned:
// [0]: full match
// [1]: matched "end" tag (or null when no end tag match)
// [2]: matched "start" tag (or null when no start tag match)
// [3]: content of start tag (or null if no start tag match)
//
var findNextPartEndOrStartTagMatch = function(text, startIndex) {
	var re = new RegExp(partEndOrStartTagRE);
	re.lastIndex = startIndex;
	var match = re.exec(text);
	return match;
}

//============================================================================
// Formatter

// Process the <part ...> ... </part> starting at (w.source, w.matchStart) for formatting.
//
// @return true if a complete part section (including the end tag) could be processed, false otherwise.
//
var handlePartSection = function(w) {
	var tagMatch = findNextPartEndOrStartTagMatch(w.source, w.matchStart);
	if (!tagMatch) return false;
	if (tagMatch.index != w.matchStart || !tagMatch[2]) return false;

	// Parse the start tag parameters
	var arguments = parseStartTagParams(tagMatch[3]);
	if (!arguments) return false;
	
	// Continue processing
	var startTagEndIndex = skipEmptyEndOfLine(w.source, tagMatch.index + tagMatch[0].length);
	var endMatch = findNextPartEndOrStartTagMatch(w.source, startTagEndIndex);
	if (endMatch && endMatch[1]) {
		if (!arguments.isHidden) {
			w.nextMatch = startTagEndIndex;
			w.subWikify(w.output,partEndTagREString);
		}
		w.nextMatch = skipEmptyEndOfLine(w.source, endMatch.index + endMatch[0].length);
		
		return true;
	}
	return false;
}

config.formatters.push( {
    name: "part",
    match: "<part\\s+[^>]+>",
	
	handler: function(w) {
		if (!handlePartSection(w)) {
			w.outputText(w.output,w.matchStart,w.matchStart+w.matchLength);
		}
	}
} )

//============================================================================
// Extend "fetchTiddler" functionality to also recognize "part"s of tiddlers 
// as tiddlers.

var currentParent = null; // used for the "." parent (e.g. in the "tiddler" macro)

// Return the match to the first <part ...> tag of the text that has the
// requrest partName.
//
// @return [may be null]
//
var findPartStartTagByName = function(text, partName) {
	var i = 0;
	
	while (true) {
		var tagMatch = findNextPartEndOrStartTagMatch(text, i);
		if (!tagMatch) return null;

		if (tagMatch[2]) {
			// Is start tag
	
			// Check the name
			var arguments = parseStartTagParams(tagMatch[3]);
			if (arguments && arguments.partName == partName) {
				return tagMatch;
			}
		}
		i = tagMatch.index+tagMatch[0].length;
	}
}

// Return the part "partName" of the given parentTiddler as a "readOnly" Tiddler 
// object, using fullName as the Tiddler's title. 
//
// All remaining properties of the new Tiddler (tags etc.) are inherited from 
// the parentTiddler.
// 
// @return [may be null]
//
var getPart = function(parentTiddler, partName, fullName) {
	var text = parentTiddler.text;
	var startTag = findPartStartTagByName(text, partName);
	if (!startTag) return null;
	
	var endIndexOfStartTag = skipEmptyEndOfLine(text, startTag.index+startTag[0].length);
	var indexOfEndTag = text.indexOf(partEndTagString, endIndexOfStartTag);

	if (indexOfEndTag >= 0) {
		var partTiddlerText = text.substring(endIndexOfStartTag,indexOfEndTag);
		var partTiddler = new Tiddler();
		partTiddler.set(
						fullName,
						partTiddlerText,
						parentTiddler.modifier,
						parentTiddler.modified,
						parentTiddler.tags,
						parentTiddler.created);
		partTiddler.abegoIsPartTiddler = true;
		return partTiddler;
	}
	
	return null;
}

// Hijack the store.fetchTiddler to recognize the "part" addresses.
//
var hijackFetchTiddler = function() {
	var oldFetchTiddler = store.fetchTiddler ;
	store.fetchTiddler = function(title) {
		var result = oldFetchTiddler.apply(this, arguments);
		if (!result && title) {
			var i = title.lastIndexOf('/');
			if (i > 0) {
				var parentName = title.substring(0, i);
				var partName = title.substring(i+1);
				var parent = (parentName == ".") 
						? store.resolveTiddler(currentParent)
						: oldFetchTiddler.apply(this, [parentName]);
				if (parent) {
					return getPart(parent, partName, parent.title+"/"+partName);
				}
			}
		}
		return result;	
	};
};

// for debugging the plugin is not loaded through the systemConfig mechanism but via a script tag. 
// At that point in the "store" is not yet defined. In that case hijackFetchTiddler through the restart function.
// Otherwise hijack now.
if (!store) {
	var oldRestartFunc = restart;
	window.restart = function() {
		hijackFetchTiddler();
		oldRestartFunc.apply(this,arguments);
	};
} else
	hijackFetchTiddler();




// The user must not edit a readOnly/partTiddler
//

config.commands.editTiddler.oldIsReadOnlyFunction = Tiddler.prototype.isReadOnly;

Tiddler.prototype.isReadOnly = function() {
	// Tiddler.isReadOnly was introduced with TW 2.0.6.
	// For older version we explicitly check the global readOnly flag
	if (config.commands.editTiddler.oldIsReadOnlyFunction) {
		if (config.commands.editTiddler.oldIsReadOnlyFunction.apply(this, arguments)) return true;
	} else {
		if (readOnly) return true;
	}

	return this.abegoIsPartTiddler;
}

config.commands.editTiddler.handler = function(event,src,title)
{
	var t = store.getTiddler(title);
	// Edit the tiddler if it either is not a tiddler (but a shadowTiddler)
	// or the tiddler is not readOnly
	if(!t || !t.abegoIsPartTiddler)
		{
		clearMessage();
		story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
		story.focusTiddler(title,"text");
		return false;
		}
}

// To allow the "./partName" syntax in macros we need to hijack 
// the invokeMacro to define the "currentParent" while it is running.
// 
var oldInvokeMacro = window.invokeMacro;
function myInvokeMacro(place,macro,params,wikifier,tiddler) {
	var oldCurrentParent = currentParent;
	if (tiddler) currentParent = tiddler;
	try {
		oldInvokeMacro.apply(this, arguments);
	} finally {
		currentParent = oldCurrentParent;
	}
}
window.invokeMacro = myInvokeMacro;

// To correctly support the "./partName" syntax while refreshing we need to hijack 
// the config.refreshers.tiddlers to define the "currentParent" while it is running.
// 
(function() {
	var oldTiddlerRefresher= config.refreshers.tiddler;
	config.refreshers.tiddler = function(e,changeList) {
		var oldCurrentParent = currentParent;
		try {
			currentParent = e.getAttribute("tiddler");
			return oldTiddlerRefresher.apply(this,arguments);
		} finally {
			currentParent = oldCurrentParent;
		}
	};
})();

// Support "./partName" syntax inside <<tabs ...>> macro
(function() {
	var extendRelativeNames = function(e, title) {
		var nodes = e.getElementsByTagName("a");
		for(var i=0; i<nodes.length; i++) {
			var node = nodes[i];
			var s = node.getAttribute("content");
			if (s && s.indexOf("./") == 0)
				node.setAttribute("content",title+s.substr(1));
		}
	};
	var oldHandler = config.macros.tabs.handler;
	config.macros.tabs.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
		var result = oldHandler.apply(this,arguments);
		if (tiddler)
			extendRelativeNames(place, tiddler.title);
		return result;
	};
})();

// Scroll the anchor anchorName in the viewer of the given tiddler visible.
// When no tiddler is defined use the tiddler of the target given event is used.
window.scrollAnchorVisible = function(anchorName, tiddler, evt) {
	var tiddlerElem = null;
	if (tiddler) {
		tiddlerElem = document.getElementById(story.idPrefix + tiddler);
	}
	if (!tiddlerElem && evt) {
		var target = resolveTarget(evt);
		tiddlerElem = story.findContainingTiddler(target);
	}
	if (!tiddlerElem) return;

	var children = tiddlerElem.getElementsByTagName("a");
	for (var i = 0; i < children.length; i++) {
		var child = children[i];
		var name = child.getAttribute("name");
		if (name == anchorName) {
			var y = findPosY(child);
			window.scrollTo(0,y);
			return;
		}
	}
}

} // of "install only once"
//}}}

/***
<html><sub><a href="javascript:;" onclick="scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

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

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

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

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

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

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

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

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

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

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

merge(config.optionsDesc,{
		pasPassword: "Test password"
	});
*/
//}}}
{{nocol{}}}

This describes the changes made to the plugins that are tagged with PatchedPlugin. These plugins should not be redistributed outside of the coursebook. The following plugins have been patched:

{{sectionTOC{}}}

! AnnotationsPlugin

Fixed usage comments from:

{{{
((text to annotate(annotation goes here)
}}}

to

{{{
((text to annotate(annotation goes here)))
}}}

in both places.

! FootnotesPlugin

Fix for issues when rendered as part of saving rss feed. It tries to add itself to the containing tiddler as though it was being rendered in the story column. But for RSS there is no story and it errors. Added:

{{{
 if (!story.findContainingTiddler(place)) return;
}}}

at the top of the handler function.

Also fixed a mising check to see if tiddler was defined:
{{{
Story.prototype.refreshTiddler = function(title,template,force)
{
    var tiddler = old_footnotes_refreshTiddler.apply(this,arguments);
	if (tiddler && tiddler.notes && tiddler.notes.length)
	{ ...
}}}
prepended the "{{{tiddler &&}}}" to the if statement in case the refresh returns null (was causing an error in IE 7).

! PartTiddlerPlugin

Change {{{<<br>>}}} to {{{<br />}}}.

! QuizzerPlugin

Added {{{return false;}}} at the end of checkOut to prevent IE from alerting about leaving the web page.

! SlideShowPlugin -- changes merged to upstream. No longer modified.

Added
{{{
return false;
}}}
at the end of all the functions that are called by ~createTiddlyButton. This prevents IE from popping up a
window asking if you want to navigate away from the page that makes the slide show mode pretty useless.

Also there is an onclick inline function assigned to the var onclick in config.macros.slideShow.handler that needed a return false at the end and I added one to the line:
{{{
if(this.nSlides==0) return false;
}}}
in confg.macros.slideShow.onClick.

! SyncFromSourcePlugin

change ~FileAdaptor.minHostName to ~AdaptorBase.minHostName to get it to work with newer tiddlywikis.

!TableSortingPlugin

From: http://groups.google.com/group/TiddlyWiki/browse_thread/thread/cced75d513e00a21

{{{
The fix is to use a more precise conditional by changing these two
lines:
        if(!x && hasClass(h,"autosort")) {
        if(x)
to:
        if(x===null && hasClass(h,"autosort")) {
        if(x!==null)

That should do it. 
}}}

! TiddlerNotesPlugin

From discussion in:

http://groups.google.com/group/TiddlyWiki/browse_thread/thread/c70af7be67524685/770b706c64529caa?#770b706c64529caa

Well guess I answered my own question. I started firebug and reloaded the tw. Then I switched to the script tab and enabled "break on all errors". Then I opened the import tab, switched to web and clicked on select a server and that resulted in:
{{{
77 if(attribs){
78     for(var n in attribs){
79            e.setAttribute(n,attribs[n]);
80     }
81 }
}}}
the error it reports is:
{{{
    e is not defined
}}}
this code is inside the function:
{{{
 function createTiddlyButton
(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey,attribs)
}}}
Looking at the function: {{{function createTiddlyElement (theParent,theElement,theID,theClass,theText,attribs)}}}
it uses the variable e in a similar way, however in createTiddlyButton the variable is:
{{{
  var theButton = document.createElement("a");
}}}
could it be that e.setAttribute should be theButton.setAttribute? 

Yes it should be.

!! Enhancement to allow printing of notes without empty notes blocks

When printing the story column, the notes block were taking up a lot of room and if they were empty, they were just wasted space.
I could turn off printing of the notes block, but I wanted to print them if the notes blocks had content. I patched the TiddlerNotesPlugin
to add the class ~TiddlerNotesExists to the notes blocks where there is a notes tiddler (indicating useful information). The patch replaced:
{{{
		var box = createTiddlyElement(place,"div","notesContainer"+tiddler.title,"TiddlerNotes",null,{"source":tiddler.title,params:paramString,heading:heading,tag:tag,suffix:suffix});
}}}
in the notes handler with:
{{{
                // rouilj add a class for notes that have contents in a tiddler.
                var notesTiddlerExists = store.tiddlerExists(tiddler.title+"-"+suffix);
		var box = createTiddlyElement(place,"div","notesContainer"+tiddler.title,"TiddlerNotes"  + (notesTiddlerExists?" TiddlerNotesExists":""),null,{"source":tiddler.title,params:paramString,heading:heading,tag:tag,suffix:suffix});
}}}
note the space between the " and ~TiddlerNotesExists. It must be there so that ~TiddlerNotes has a space after it otherwise the class names aren't correct.

Then the stylesheet was changed to not display the class ~TiddlerNotes but to display ~TiddlerNotesExists when printing. Also the edit notes button was hidden for printing.

<<sectionTOC>>
{{nocol{}}}
<<tiddler OpenStoryButton with: "Open all presentations">>
Intro to the coursebook and tiddlywiki in general
[[Slide Welcome]]
[[What is a TiddlyWiki]]
[[Tiddler Types in This Coursebook]]

[[Coursebook Orientation]]

[[Using Notebook]]

The parts of this coursebook:
   * Chapters
   * Presentations (shows)
   * Quizzes

[[Course Structure]]
[[Using Presentations]]
[[Using Chapters]]
[[Goals]]
[[Presentations]]
[[Textbook]]
[[Quizzes]]
[[Notebook]]
[[Live Book/Errata]]
[[Online during class]]
[[Online after class]]
[[Printed documentation]]
[[Creating the Student's Coursebook]]
[[Differences between student and instructor books]]
       [[Instructor has tools for improving editing/creation]]
            Tool for mass editing of tiddlers, tags
            Tool for maintaining different versions of tiddlers
            Tools for embedding/attaching files inside tw document
            Tool for showing relations between tiddlers
            Tool for easier tag management
            Configuration that displays missing tiddlers rather then replacing with nothing
            Double click to edit a tiddler is enabled
        [[Instructor tiddlywiki has themes for presentations]]
            student book has a stripped down content and navigation/note taking interface
        [[Student is a read-mostly config]]
            Only notes are easy to edit
            Content editing must be invoked by a menu, double clicking doesn't work
            Content can be overwritten during sync
        [[Instructor book can publish documents]]
            Student book without contents (framework)
                Meant to be portable for multiple classes.
            Student content to be imported
                Imported into framework to allow separation of framework updates from content updates
                Content updates are smaller than the whole tiddlywiki
            rss feed of content changes
    [[Presentation modes]]
    [[Presentation modes - Instructor]]
    instructor
            example slide
            No notes displayed
    [[Presentation modes - Student]]
        student
            example slide
            Instructor annotations
            Student notes
       [[Presentation modes - Print]]
        print
            example slide
                print display controlled by css. each slide on new page to allow for hand printed notes
       [[Presentation modes - Story]]

    [[Chapter creation]]
        sequence of tiddlers
            story makes up a linear chapter
            because tiddlers are stand alone entities (and are the unit of notetaking for the students) flow of prose is somewhat tricky. References to other tiddler content is tricky because this maybe the only tiddler shown.
    [[Printing]]
        Slides to pdf or paper
        content/chapters to pdf
            may still miss some tiddlers.
                Check orphaned tiddler list
[[Areas for Improvement]]
[[Any Questions?]]
[[This is the End]]
;tags underused
: tagging provides more semantic info and provides linkages between tiddlers using tagclouds or other linkage tools. See {{exclude{[[Content Bugs##Possible tag taxonomy for content]]}}} for one sample. It's possible the tag taxonomy may be different for each course and a single taxonomy is not possible.
;more flexibility with themes
: I often have three levels of slides: <<tiddler "Presentation  4 - Improvements-Notes##slideLevels">> where the layout of the slides is different. E.G. the primary slide may be a picture with overlayed text. So the normal border etc of a standard presentation should be suppressed for this slide. While the third level slides may have a different color, border or dividing line to indicate that this slide is not as important as the second or primary slides. This also allows me to skip quickly through third level slides by sight when I am running short of time or audience interest in a particular secondary point is lagging.

;discovering relations between tiddlers
: This is something that I played with originally. There are a number of plugins from [[hypergraphs|http://project.dahukanna.net/tiddlywiki/twextensions.htm]], To ~TiddlyGraph: http://ideia.tiddlyspot.com/, to ~RelatedTiddlersPlugin: http://www.tiddlytools.com/#RelatedTiddlersPlugin, to using match tags to find all tiddlers with similar sets of tags. I haven't found a good solution yet that is cross browser, simple to interpret/use.

;edit cycle with multiple users
:when I was producing my first coursebook, my editor was in california and she got emails with the tiddlywiki in it to review. Ideally she would have been able to add her own notes (notebook) in a separate namespace and then send the tiddlywiki back to me. Then I could import her notes into my tiddlywiki an respond to them. However the notes plugin doesn't quite work that way, so we were stuck having to use manual notes and context clues to handle the edits. Using an online collaborative platform like tiddlyspot may be a good way around that, but... Also the revisions plugin allows multiple revisions so in theiry she could edit it and I could compare, but frankly the comparison/revision mchanism is kind of clunky.

/%
!slideLevels
* Primary topic/graphic
* Secondary topic
* Supporting
!end
%/
By default every presentation gets:
* start instructor show button
* start student show button
* print mode button
displayed at the top of the control tiddler for the presentation
<<<
@@vertical-align:bottom;[img(24px,)[warning-icon.png]]@@ If these buttons are missing, make sure {{{presentation}}} is the first tag on the tiddler.
<<<
You can add a different  {{{<<slideShow>>}}} macro calls to get a looping slide show button, or other execution type. See [[SlideShowPluginDoc##Options]] for a description of the modes that the slide show can operate in. Make sure to include the macro call it inside of a  {{exclude{  ...  }}} block so it's arguments (to style/theme tiddlers ...) aren't displayed as part of the presentation. If you are using  a single tiddler presentation see [[Creating a Presentation]] for the proper [[class syntax|http://www.tiddlywiki.com/#CustomCssClass]] to hide the display of the slideshow start button during the presentation.

To add instructor notes for the students to view, add the instructor notes inside of a {{comment{ ... }}} class block. These will be displayed on a colored background to the student, but are not displayed on the screen.

To learn how to add overlays see [[SlideShowPluginDoc##Incremental display]].
* Advancing a slide when a slide has overlays just displays the next overlay set
* Student view has overlays disabled, all the overlayed sections are displayed when the student displays the slide. This makes it easier for the student to stay in sync with the instructor as slide changes are obvious, but overlay reveals can be missed by the student.

When generating a looping slideshow, set the slide display time to a standard base increment that most of your slides will use.
Then add <html><pre>{{overlay1{}}}, {{overlay2{}}} ...</pre></html> to make a given slide display for an additional increment for each empty overlay.

You can add links on the [[presentation control tiddler|Glossary/presentationControlTiddler]] to other tiddlers that are not part of the slide show by enclosing the links inside of an exclude class block.  <<tiddler [[Presentation Tips##excludeClass]]>> Also you will want to tag that referenced tiddler with the *excludeStory* tag.

Presentations can also be tagged with story to allow all the tiddlers in the presentation to be opened in order in the story column. This is a fast way of displaying the entire presentation for review/editing or [[printing|Printing Slide Set]].

/%
!excludeClass
<html><pre>
{{exclude{ [[other tiddler reference]] }}}
</pre></html>
!end
%/
* Instructor
* Student
* Print
* Story
* instructor
example slide
{{comment{
Note that no instructor notes are displayed
}}}
fixme example slide

{{comment{
Each slide by default prints at the top of a new page. So you can create 2, 4, 8 up pages
using your printer's mechanism for putting multiple pages on a single sheet of paper.
}}}
FIXME example slide

{{comment{
This isn't a presentation mode supplied by the SlideShowPlugin. Instead it treats the slideshow as a list of tiddlers to display in presentation order in the story column. This allows printing of notebooks for the tiddlers (which the print presentation mode doesn't).

This is as close to a storyboard as I could get and is the mode I print off to use as my guide during presentations. Note that each tiddler and it's associated notebook is printed on a new page again allowing multi-up printing using the standard printer driver.
}}}
example slide FIXME
{{comment{
Note the instructor annotations that are highlighted at the bottom of the slide.
Also the notebook for the student is available.
}}}
<<matchTags inline {{if (store.getTiddlerText("InstructorSlideShowStyleSheet")) {displayargs="theme:InstructorSlideShowStyleSheet toc:titles noClicks footer:'copyright&copy; 2010<br />John Rouillard' clock:+ tooltip:'Start %0 slideshow in instructor projection mode' "} else {displayargs="noClicks noKeyboard noOverlays toc:titles tooltip:'Start %0 slideshow in student mode' "}; "* <<slideShow tiddler:'%0' label:'%0' " + displayargs + ">" + "> @@font-size: smaller;([[open|%0]])@@"}} "\n" sort:title presentation>>
@@display:none; use sort order to override default title based ordering. Anything with an explicit order will be sorted before the title sorted section. @@
<<tiddler SlideSubstyle##levelTwo>>

{{comment{
presentation picture

* Have multiple slide shows corresponding to a single lesson/chapter in document.
* Support overlays for presentation (but not in student copy).
* Provide instructor notes for students to view (but not in presentation)
* Allow students to take their own notes on slides
* Automatic presentations for class breaks, before class etc
}}}
* slide shows
* chapters
* student notes

{{comment{
If you are going to be printing content, some care is required with the use of [[dynamic content|Dynamic Content]].
Choose dynamic content mechanisms that are printable, or do not put required information into dynamic content since it may not be printable.

While you can print to PDF, this is good for little more than printing a hard copy of the document. Hyperlinks and other active content in the TiddlyWiki are not active in the pdf. Bookmarks can be added to the pdf afterwards that allow the user to jump to the target of links, but this is time consuming and prone to error.
}}}
! People still like paper
* Start of chapters print on new page
* Each slide in a presentation prints on new page
* Best with linear content, paper doesn't work well for non-linear content
* Can print to pdf using printer driver but no active content of the TiddlyWiki survives

{{comment{
Chapters and presentations are linear and the best candiates for printing. Printing reference pages may
also be useful. However there are probably going to be tiddlers that are not displayed in a linear context.
TiddlyWiki provides the [[orphaned tiddler list]] to help identify tiddlers that are not linked or [[transcluded|Glossary/transcluded]] into other tiddlers.
}}}
Reading material on a computer is still not as easy as reading it printed on paper. Printing a chapter is a matter of displaying the chapter(s) tiddlers in order in the story column and using the browser's print function to print the story. A [[style sheet with instructions for printing|StyleSheet]] (search for {{{@media print }}} to find the printing section) is included in the coursebook. Directions for making some basic changes can be found in [[Changing the Style Sheet]].

!! Setting up the Story Column
To print:
* Select the chapter from pull the down box, or click on the title link for the chapter in the left hand MainMenu.
** This prints the chapter content and any personal notes.

You can open multiple chapters by opening the chapters in order, but you need to set/change the story display options.
* In the chapter pulldown:
## select "close other tiddlers" under viewing options
## select the first chapter you want to display
## select only: "open at bottom" under viewing options
## select additional chapters in the order you want them displayed
* print using the browsers print mechanism

Note that each chapter should print starting on a new page if
{{{
<<tiddler ChapterStart>>
}}}
is prepended to the first line of the first tiddler in the chapter. See [[Changing the Style Sheet]] if you want to modfiy this.
Before printing the slide set you will probably want to set the title of the Coursebook to reflect the particular presentation you are printing. The title is used
in the page header and possibly other places depending on your output mode. You can use the "change title" link in the instructor slider in the right sidebar to set a title. Usually it is the presentation name. Note this is also used for the file naming with PDFCreator if you set it to use auto filename, it must be unique in the first 10 or so characters or one print file will overwrite another.

There are two printing modes you can do from the Instructor Coursebook:
* print instructor slides including instructor notes, comments for the students etc. This mode does not look like the presentation slides.
* the slides as presented on the screen (think powerpoint slide print).

To print something suitable as a handout to the presentation attendees that includes the notes to the attendees (SlideShowPlugin print mode):
* Select the @@open@@ link next to the presentation title from presentation menu
** In the control tiddler, choose print mode to display the slide content as it would be shown on the screen. Note that all overlays are displayed for printing. These slides can be printed 2-up on a sheet of paper (using the print settings dialog box) and are suitable for use as handouts for the students.
** Use the browser's menu to start the print process.
** Pressing any key on the keyboard will end the print mode.

To print the instructor slides/notes etc
* Select the presentation from the drop down select box:
** This opens all the slide tiddlers in the story column. When printed it shows: slide content, instructor notes (inside of comment blocks), and personal notes (notebook). It is not formatted like a slide. Text is smaller and other settings appropriate to a slide show presentation are not applied.

In both cases every slide tidder prints on a new page. If you want to change this, you need to edit the PrintingSlideShowStyleSheet as described in [[Changing Slide Printing|Changing the Style Sheet##Changing Slide Printing]]
/*{{{*/
/* Default style sheet settings for printing */
#contentWrapper.slideShowMode #displayArea{
 font-size: 150%;
 margin: 1em 15.5em 0em 1em !important;
}

h1,h2,h3 {margin-top:0.3em}

.slideFooterOff #navigator{
 display: none;
}

#controlBar{
 display: none;
}

@media print {
.tiddler{
 page-break-after: always;
 border: 2px solid blue;
 margin: 1em 0 1em 0;
 padding: 0.5em
}
.viewer pre { background-color: transparent; }

#contentWrapper.slideShowMode .comment{
 background-color: transparent;
}
}

.notes {
display: none;
}

.comment{
 border: 1pt dashed;
 padding: 0.5em;
}

#contentWrapper.slideShowMode  #displayArea {margin: 1em 0em 0em 0em !important;}
}
/*}}}*/
/***
|Name|QuickEditPlugin|
|Source|http://www.TiddlyTools.com/#QuickEditPlugin|
|Documentation|http://www.TiddlyTools.com/#QuickEditPlugin|
|Version|2.4.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Support functions for ~QuickEdit package: styles, utility functions, and 'toggleQuickEdit' command|
!!!!!Revisions
<<<
2009.06.11 [2.4.3] added keyup() function to abbreviate listbox handling for CR and ESC
2009.05.07 [2.4.2] added processed() function to abbreviate event handler code
2008.09.07 [2.4.1] added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.05.17 [2.4.0] copied code from StickyPopupPlugin to remove dependency
2008.05.12 [2.3.0] added "toggleQuickEdit" command handler (replaces inline script command)
2008.01.11 [2.2.0] converted from inline script
2007.03.29 [1.0.0] initial release (as inline script)
<<<
!!!!!Code
***/
//{{{
version.extensions.QuickEditPlugin= {major: 2, minor: 4, revision: 3, date: new Date(2009,6,11)};

// SET STYLESHEET
setStylesheet("\
.quickEdit a { border:2px outset ButtonFace; padding:0px 3px !important; \
	-moz-border-radius:.5em; -webkit-border-radius:.5em; \
	-moz-appearance:button !important; -webkit-appearance:push-button !important; \
	background-color:ButtonFace; color:ButtonText !important;  \
	line-height:200%; font-weight:normal; } \
.quickEdit a:hover { border: 2px inset ButtonFace; background-color:ButtonFace; }\
", "quickEditStyles");

// REMOVE COOKIE
if (window.removeCookie===undefined) {
	window.removeCookie=function(name) {
		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;'; 
	}
}

// UTILITY FUNCTIONS
config.quickEdit = {
	processed: function(ev) { ev=ev||window.event;
		ev.cancelBubble=true;
		if(ev.stopPropagation) ev.stopPropagation();
		return false;
	},
	keyup: function(ev){ var k=(ev||window.event).keyCode;
		if (k==13) this.onclick();
		if (k==27) Popup.remove();
	},
	getField: function(where) {
		var here=story.findContainingTiddler(where); if (!here) return null;
		var e=story.getTiddlerField(here.getAttribute("tiddler"),"text");
		if (e&&e.getAttribute("edit")=="text") return e;
		return null;
	},
	setSelection: function(where,newtext) {
		var e=this.getField(where); if (!e) return false;
		e.focus(); replaceSelection(e,newtext);
		return false;
	},
	wrapSelection: function(where,before,after) {
		var e=this.getField(where); if (!e) return false;
		e.focus(); replaceSelection(e,before+config.quickEdit.getSelection(e)+after);
		return false;
	},
	getSelection: function(e) {
		var seltext="";
		if (e&&e.setSelectionRange)
			seltext=e.value.substr(e.selectionStart,e.selectionEnd-e.selectionStart);
		else if (document.selection) {
			var range = document.selection.createRange();
			if (range.parentElement()==e) seltext=range.text
		}
		return seltext;
	},
	promptForFilename: function(msg,path,file) {
		if(window.Components) { // moz
			try {
				netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
				var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
				var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
				picker.init(window, msg, nsIFilePicker.modeOpen);
				var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
				thispath.initWithPath(path);
				picker.displayDirectory=thispath;
				picker.defaultExtension='jpg';
				picker.defaultString=file;
				picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterImages);
				if (picker.show()!=nsIFilePicker.returnCancel)
					var result="file:///"+picker.file.persistentDescriptor.replace(/\\/g,'/');
			}
			catch(e) { alert('error during local file access: '+e.toString()) }
		}
		else { // IE
			try { // XP only
				var s = new ActiveXObject('UserAccounts.CommonDialog');
				s.Filter='All files|*.*|JPG files|*.jpg|GIF files|*.gif|PNG files|*.png|';
				s.FilterIndex=1; // default to JPG
				s.InitialDir=path;
				s.FileName=file;
				if (s.showOpen()) var result=s.FileName;
			}
			catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE
		}
		return result;
	}
}
//}}}

//{{{
if (config.options.chkShowQuickEdit===undefined) config.options.chkShowQuickEdit=false;
config.commands.toggleQuickEdit = {
	hideReadOnly: true,
	getText: function() { return config.options.chkShowQuickEdit?'\u221Aquickedit':'quickedit'; },

	tooltip: 'show QuickEdit toolbar buttons',
	handler: function(event,src,title) {
		config.options.chkShowQuickEdit=!config.options.chkShowQuickEdit;
		config.macros.option.propagateOption("chkShowQuickEdit","checked", config.options.chkShowQuickEdit,"input");
		if (config.options.chkShowQuickEdit) saveOptionCookie("chkShowQuickEdit");
		else removeCookie("chkShowQuickEdit");
		src.innerHTML=config.commands.toggleQuickEdit.getText();
		story.forEachTiddler(function(t,e){if (story.isDirty(t)) refreshElements(e);});
		return false;
	}
};
//}}}

// // COPIED FROM [[StickyPopupPlugin]] TO ELIMINATE PLUGIN DEPENDENCY
//{{{
if (config.options.chkStickyPopups==undefined) config.options.chkStickyPopups=false;
Popup.stickyPopup_onDocumentClick = function(ev)
{
	// if click is in a sticky popup, ignore it so popup will remain visible
	var e = ev ? ev : window.event; var target = resolveTarget(e);
	var p=target; while (p) {
		if (hasClass(p,"popup") && (hasClass(p,"sticky")||config.options.chkStickyPopups)) break;
		else p=p.parentNode;
	}
	if (!p) // not in sticky popup (or sticky popups disabled)... use normal click handling
		Popup.onDocumentClick(ev);
	return true;
};
try{removeEvent(document,"click",Popup.onDocumentClick);}catch(e){};
try{addEvent(document,"click",Popup.stickyPopup_onDocumentClick);}catch(e){};
//}}}
/%
|Name|QuickEdit_convert|
|Source|http://www.TiddlyTools.com/#QuickEdit_convert|
|Version|2.4.3|
|Author|Eric Shulman|
|License|see http://www.TiddlyTools.com/#QuickEditPlugin|
|Type|html|
|Requires|QuickEditPlugin|
|Description|quickedit - convert between comma/tab-separated and TW table format|

Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

%/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1" 
title="convert between comma/tab-separated and TW table format"
onclick="var e=config.quickEdit.getField(this);
	if (e) e.focus(); var txt=config.quickEdit.getSelection(e);
	if (txt.indexOf(',')+txt.indexOf('\t')+txt.indexOf('|')==-3) {
		alert('Please select text containing tabs, commas, or TiddlyWiki table syntax.');
		return false;
	}
	var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
	var s=createTiddlyElement(p,'select'); s.button=this;
	s.options[0]=new Option('select a converter...','');
	if (txt.indexOf(',')!=-1) {
		s.options[s.length]=new Option('commas -> table','commasToTable');
		s.options[s.length]=new Option('commas -> tabs','commasToTabs');
	}
	if (txt.indexOf('\t')!=-1) {
		s.options[s.length]=new Option('tabs -> table','tabsToTable');
		s.options[s.length]=new Option('tabs -> commas','tabsToCommas');
	}
	if (txt.indexOf('|')!=-1) {
		s.options[s.length]=new Option('table -> tabs','tableToTabs');
		s.options[s.length]=new Option('table -> commas','tableToCommas');
	}
	s.size=s.length;
	s.onclick=function(){ if (!this.value.length) return;
	        var e=config.quickEdit.getField(this.button); if (!e) return false;
		e.focus(); var txt=config.quickEdit.getSelection(e);
		switch(this.value) {
			case 'tabsToTable':
				txt=txt.replace(/\t/g,'|').replace(/^|$/g,'|');
				txt=txt.replace(/\n/g,'|\n|').replace(/^\|$/g,'');
				break;
			case 'tableToTabs':
				txt=txt.replace(/\t/g,' ').replace(/\|/g,'\t');
				txt=txt.replace(/^\t/g,'').replace(/\t$/g,'');
				txt=txt.replace(/\n\t/g,'\n').replace(/\t\n/g,'\n');
				break;
			case 'commasToTable':
				txt=txt.replace(/,/g,'|').replace(/^|$/g,'|');
				txt=txt.replace(/\n/g,'|\n|').replace(/^\|$/g,''); 
				break;
			case 'tableToCommas':
				txt=txt.replace(/,/g,' ').replace(/\|/g,',');
				txt=txt.replace(/^,/g,'').replace(/,$/g,''); 
				txt=txt.replace(/\n,/g,'\n').replace(/,\n/g,'\n'); 
				break;
			case 'tabsToCommas':
				txt=txt.replace(/\t/g,',');
				break;
			case 'commasToTabs':
				txt=txt.replace(/,/g,'\t');
				break;
		}
		replaceSelection(e,txt);
		Popup.remove(); return false;
	};
	s.onkeyup=config.quickEdit.keyup;
	Popup.show();
	s.focus();
	return config.quickEdit.processed(event);"
>convert</a></html>
<<matchTags inline "* [[%0]]" "\n" sort:title quiz>> @@display:none; use sort order to override default title based ordering. Anything with an explicit order will be sorted before the title sorted section. @@
/***
|''Name:''|QuizzerPlugin|
|''Description:''|Makes quizzes with optional grades|
|''Version:''|1.0.2|
|''Date:''|Nov 11, 2008|
|''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|
|''Documentation:''|[[QuizzerPlugin Documentation|QuizzerPluginDoc]]|
|''Author:''|Paulo Soares|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.1.0|
***/
//{{{
config.macros.quiz = {
	wrongAnswer: "Incorrect answer. Please think again.",
	rightAnswer: "That's right!",
	trueValue: "True",
	falseValue: "False",
	handler: function(place,macroName,params,wikifier,paramString){
		var par = paramString.parseParams("list",null,true);
		var type = getParam(par,"type","M");
		var panelType = (type.length>1) ? type.charAt(1) : "";
		type = type.charAt(0);
		var id = getParam(par,"id","");
		if(id=="" && type!="M") return; // not sure about this
		var value = getParam(par,"value",false);
		var tiddler = getParam(par,"tiddler","");
		var score = parseFloat(getParam(par,"score",0));
		var toolTip = "";
		if(type=="T"){
			toolTip = this.trueValue;
			if(value==false){
				var tempTiddler=tiddler;
				tiddler="";
				var tempScore=score;
				score=0;
			}
		}
		this.createAnswer(place, type, toolTip, true, panelType, tiddler, value, score, id);
		if(type=="T"){
			tiddler=(value==false)?tempTiddler:"";
			score=(value==false)?tempScore:0;
			toolTip = this.falseValue;
			this.createAnswer(place, type, toolTip, false, panelType, tiddler, !value, score, id);
		}
	},
	createAnswer: function(place, type, toolTip, correction, panelType, tiddler, value, score, id){
		var checked=false;
		if(correction){
			var correct = createTiddlyElement(place,"span","","correction","");
			correct.style.display='none';
			correct.style.fontWeight='bold';
			checked=true;
		}
		if(type=="M"){
			var btn = createTiddlyCheckbox(place,"",false,this.onClickAnswer);
		} else {
			var btn = createTiddlyRadiobox(place,"",checked,this.onClickAnswer,id);
		}
		btn.className = "answerItem";
		btn.value=score;
		if(toolTip!="") btn.title=toolTip;
		var panelClass = (panelType=="=") ? "sliderPanel" : "floatingPanel"; //default to floating
		var text = (tiddler!="") ? store.getTiddlerText(tiddler) : ""; 
		if(text==""){text = (value) ? this.rightAnswer : this.wrongAnswer;}
		var panel = createTiddlyElement(null,"div","",panelClass);
		panel.style.display = "none"; //default to closed
		panel.onclick=function(){this.style.display="none";};
		place.appendChild(panel);
		wikify(text,panel,null);
	},
	onClickAnswer: function(e){
		if(!e) var e = window.event;
		var panel = this.nextSibling;
		if(this.checked){
			var validated = 1;
			var visiblePanel=document.getElementById('visiblePanel');
			var sC = Story.prototype.findContainingTiddler(this).id.substr(7)+'_scoreCard';
			var scoreCard=document.getElementById(sC);
			if(visiblePanel){
				visiblePanel.style.display="none";
				visiblePanel.id="";
			}
			if(scoreCard){validated = scoreCard.value;}
			if(validated==1){
				panel.style.display = "block";
				panel.id="visiblePanel";
				var left= e.clientX +10;
				panel.style.left = left + "px";
			}
		} else {
			panel.style.display = "none";
			panel.id="";
		}
	}
};

config.macros.score= {
	trueSymbol: "✔",
	falseSymbol: "✘",
	label: "Score »",
	handler: function(place,macroName,params,wikifier,paramString,tiddler){
		var btn = createTiddlyButton(place,this.label,"",this.checkOut);
		btn.id=tiddler.title+"_scoreCard";
		btn.value=0;
	},
	checkOut: function(e){
		if(this.value==1) return;
		var total=score=points=0;
		var answers=getElementsByClass("answerItem",document.getElementById('viewer'));
		var answersLen=answers.length;
		for(var i=0; i<answersLen; i++) {
			points=parseFloat(answers[i].value);
			score+=answers[i].checked*points;
			if(points>0)total+=points;
			var correct=answers[i].previousSibling;
			if(correct.className=="correction"){
				if(answers[i].checked == (points>0)){
					correct.firstChild.data=config.macros.score.trueSymbol;
					correct.style.color = '#0f0';
				} else {
					correct.firstChild.data=config.macros.score.falseSymbol;
					correct.style.color = '#f00';
				}
				correct.style.display='inline';
			}
		}
		var text = " " + score+"/"+total;
		createTiddlyElement(this,"span","","",text);
		this.value=1;
                return false;
	}
};

function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null ) node = document;
	if ( tag == null ) tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	for (var i = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {classElements.push(els[i]);}
	}
	return classElements;
}

function createTiddlyRadiobox(theParent,caption,checked,onChange,id){
	var cb = document.createElement("input");
	cb.type = "radio";
	cb.name = id;
	cb.onclick = onChange;
	theParent.appendChild(cb);
	cb.checked = checked;
	cb.className = "chkOptionInput";
	if(caption) wikify(caption,theParent);
	return cb;
}

setStylesheet("/*{{{*/\n.floatingPanel {\n color: black;\n;position: absolute;\nz-index: 10;\npadding: 0.5em;\nbackground-color: #eee;\nborder: 1px solid #333;\ncursor: crosshair}\n\n.sliderPanel {padding: 0.5em;\nborder: 1px dotted #333;\nwidth: auto;\ncursor: crosshair}\n\n/*}}}*/","AnswerPanelStyles");

config.shadowTiddlers.QuizzerPluginDoc="The documentation is missing. It is available [[here|http://www.math.ist.utl.pt/~psoares/addons.html#QuizzerPluginDoc]].";
//}}}
!!!!Syntax
The QuizzerPlugin has five parameters; most are optional:
//{{{
<<quiz [type:type[=]] [id:id] [tiddler:tiddler] [value:value] [score:score]>>
//}}}
Parameters:
*type (string)
**"M" (multiple answer checkbox) (default)
**"S" (single-answer radio button group)
**"T" (true/false question)
***append "=" for sliding panel (e.g., T=, S=, M=) 
*id (string)
**required for types S  and T only
***for type S value must be unique across a group of questions
***for type T value must be unique for each question 
*tiddler (string, //optional//)
**display text from tiddler in the panel
**default is config.macros.answer.wrongAnswer or config.macros.answer.rightAnswer according to the value of the next parameter
*value
**use {{{value:true}}} to indicate that the true answer is right
**should be omitted otherwise
*score (number)
**sets the score for an answer
** default is 0
<<tiddler SlideSubstyle##levelThree>>
Yes there must be quizzes.
{{comment{
picture quiz/exam

* Scored multiple choice, true/false, single answer
* Support essay/example questions
}}}
/***
|''Name:''|RSSReaderPlugin|
|''Description:''|This plugin provides a RSSReader for TiddlyWiki|
|''Version:''|1.1.2|
|''Date:''|2008-09-02|
|''Source:''|http://tiddlywiki.bidix.info/#RSSReaderPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#RSSReaderPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''Credit:''|BramChen for RssNewsMacro|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''OptionalRequires:''|http://www.tiddlytools.com/#NestedSlidersPlugin|
***/
//{{{
version.extensions.RSSReaderPlugin = {
	major: 1, minor: 1, revision: 2,
	date: new Date("2008-09-02"),
	source: "http://TiddlyWiki.bidix.info/#RSSReaderPlugin",
	author: "BidiX",
	coreVersion: '2.2.0'
};

config.macros.rssReader = {
	dateFormat: "DDD, DD MMM YYYY",
	itemStyle: "display: block;border: 1px solid black;padding: 5px;margin: 5px;", //useed  '@@'+itemStyle+itemText+'@@'
	msg:{
		permissionDenied: "Permission to read preferences was denied.",
		noRSSFeed: "No RSS Feed at this address %0",
		urlNotAccessible: " Access to %0 is not allowed"
	},
	cache: [], 	// url => XMLHttpRequest.responseXML
	desc: "noDesc",
	
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var desc = params[0];
		var feedURL = params[1];
		var toFilter = (params[2] ? true : false);
		var filterString = (toFilter?(params[2].substr(0,1) == ' '? tiddler.title:params[2]):'');
		var place = createTiddlyElement(place, "div", "RSSReader");
		wikify("^^<<rssFeedUpdate "+feedURL+" [[" + tiddler.title + "]]>>^^\n",place);
		if (this.cache[feedURL]) {
			this.displayRssFeed(this.cache[feedURL], feedURL, place, desc, toFilter, filterString);
		}
		else {
			var r = loadRemoteFile(feedURL,config.macros.rssReader.processResponse, [place, desc, toFilter, filterString]);
			if (typeof r == "string")
				displayMessage(r);
		}
		
	},

	// callback for loadRemoteFile 
	// params : [place, desc, toFilter, filterString]
	processResponse: function(status, params, responseText, url, xhr) { // feedURL, place, desc, toFilter, filterString) {	
		if (window.netscape){
			try {
				if (document.location.protocol.indexOf("http") == -1) {
					netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
				}
			}
			catch (e) { displayMessage(e.description?e.description:e.toString()); }
		}
		if (xhr.status == 404)
		 {
			displayMessage(config.macros.rssReader.noRSSFeed.format([url]));
			return;
		}
		if (!status)
		 {
			displayMessage(config.macros.rssReader.noRSSFeed.format([url]));
			return;
		}
		if (xhr.responseXML) {
			// response is interpreted as XML
			config.macros.rssReader.cache[url] = xhr.responseXML;
			config.macros.rssReader.displayRssFeed(xhr.responseXML, params[0], url, params[1], params[2], params[3]);
		}
		else {
			if (responseText.substr(0,5) == "<?xml") {
				// response exists but not return as XML -> try to parse it 
				var dom = (new DOMParser()).parseFromString(responseText, "text/xml"); 
				if (dom) {
					// parsing successful so use it
					config.macros.rssReader.cache[url] = dom;
					config.macros.rssReader.displayRssFeed(dom, params[0], url, params[1], params[2], params[3]);
					return;
				}
			}
			// no XML display as html 
			wikify("<html>" + responseText + "</html>", params[0]);
			displayMessage(config.macros.rssReader.msg.noRSSFeed.format([url]));
		}
	},

	// explore down the DOM tree
	displayRssFeed: function(xml, place, feedURL, desc, toFilter, filterString){
		// Channel
		var chanelNode = xml.getElementsByTagName('channel').item(0);
		var chanelTitleElement = (chanelNode ? chanelNode.getElementsByTagName('title').item(0) : null);
		var chanelTitle = "";
		if ((chanelTitleElement) && (chanelTitleElement.firstChild)) 
			chanelTitle = chanelTitleElement.firstChild.nodeValue;
		var chanelLinkElement = (chanelNode ? chanelNode.getElementsByTagName('link').item(0) : null);
		var chanelLink = "";
		if (chanelLinkElement) 
			chanelLink = chanelLinkElement.firstChild.nodeValue;
		var titleTxt = "!![["+chanelTitle+"|"+chanelLink+"]]\n";
		var title = createTiddlyElement(place,"div",null,"ChanelTitle",null);
		wikify(titleTxt,title);
		// ItemList
		var itemList = xml.getElementsByTagName('item');
		var article = createTiddlyElement(place,"ul",null,null,null);
		var lastDate;
		var re;
		if (toFilter) 
			re = new RegExp(filterString.escapeRegExp());
		for (var i=0; i<itemList.length; i++){
			var titleElm = itemList[i].getElementsByTagName('title').item(0);
			var titleText = (titleElm ? titleElm.firstChild.nodeValue : '');
			if (toFilter && ! titleText.match(re)) {
				continue;
			}
			var descText = '';
			descElem = itemList[i].getElementsByTagName('description').item(0);
			if (descElem){
				try{
					for (var ii=0; ii<descElem.childNodes.length; ii++) {
						descText += descElem.childNodes[ii].nodeValue;
					}
				}
				catch(e){}
				descText = descText.replace(/<br \/>/g,'\n');
				if (desc == "asHtml")
					descText = "<html>"+descText+"</html>";
			}
			var linkElm = itemList[i].getElementsByTagName("link").item(0);
			var linkURL = linkElm.firstChild.nodeValue;
			var pubElm = itemList[i].getElementsByTagName('pubDate').item(0);
			var pubDate;
			if (!pubElm) {
				pubElm = itemList[i].getElementsByTagName('date').item(0); // for del.icio.us
				if (pubElm) {
					pubDate = pubElm.firstChild.nodeValue;
					pubDate = this.formatDateString(this.dateFormat, pubDate);
					}
					else {
						pubDate = '0';
					}
				}
			else {
				pubDate = (pubElm ? pubElm.firstChild.nodeValue : 0);
				pubDate = this.formatDate(this.dateFormat, pubDate);
			}
			titleText = titleText.replace(/\[|\]/g,'');
			var rssText = '*'+'[[' + titleText + '|' + linkURL + ']]' + '' ;
			if ((desc != "noDesc") && descText){
				rssText = rssText.replace(/\n/g,' ');
				descText = '@@'+this.itemStyle+descText + '@@\n';				
				if (version.extensions.nestedSliders){
					descText = '+++[...]' + descText + '===';
				}
				rssText = rssText + descText;
			}
			var story;
			if ((lastDate != pubDate) && ( pubDate != '0')) {
				story = createTiddlyElement(article,"li",null,"RSSItem",pubDate);
				lastDate = pubDate;
			}
			else {
				lastDate = pubDate;
			}
			story = createTiddlyElement(article,"div",null,"RSSItem",null);
			wikify(rssText,story);
		}
	},
	
	formatDate: function(template, date){
		var dateString = new Date(date);
		// template = template.replace(/hh|mm|ss/g,'');
		return dateString.formatString(template);
	},
	
	formatDateString: function(template, date){
		var dateString = new Date(date.substr(0,4), date.substr(5,2) - 1, date.substr(8,2)
			);
		return dateString.formatString(template);
	}
	
};

config.macros.rssFeedUpdate = {
	label: "Update",
	prompt: "Clear the cache and redisplay this RssFeed",
	handler: function(place,macroName,params) {
		var feedURL = params[0];
		var tiddlerTitle = params[1];
		createTiddlyButton(place, this.label, this.prompt, 
			function () {
				if (config.macros.rssReader.cache[feedURL]) {
					config.macros.rssReader.cache[feedURL] = null; 
			}
			story.refreshTiddler(tiddlerTitle,null, true);
		return false;});
	}
};

//}}}
This plugin provides a RSSReader for TiddlyWiki. If TiddlyWiki is viewed over HTTP, RSSReaderPlugin requires a ProxyService.

See examples : <<tag RSSFeed>>.
See documentation : RSSReaderPluginDoc

if NestedSlidersPlugin is available, item contents are folded. 
//last update: RSSReaderPlugin v 1.1.1//

!Description
This plugin provides a RSSReader for TiddlyWiki
* It accesses asynchronously an RSSFeed
*Depending on the chanel item format, each item could be written as :
**simple text wikified
**html

!Usage
{{{
<<rssReader noDesc|asHtml|asText rssUrl ['filtering string']>>
	noDesc: only title of item is printed

	asHtml: if you know that description contain html (links, img ...), 
		the text is enclosed with <html> </html> tags

 	asText: if the description should not be interpreted as html the 
		description is wikified

	rssUrl: the rssFeed url that could be accessed. 
	
	'filtering string': if present, the rssfeed item title must contained 
		this string to be displayed. 
		If 'filering string' contained space characters only, the tiddler 
		title is used for filtering.

}}}

For security reasons, if the TiddlyWiki is accessed from http, a ProxyService should be used to access an rssFeed from an other site.

!examples
| !reader | !RSSFeed type | !working from |
| BidiXTWRSS | Description asHtml | file: or tiddlywiki.bidix.info |
| [[Le Monde]] | Description asText | file: or tiddlywiki.bidix.info using proxy |
| YahooNewsSport | Description asHtml | file: or tiddlywiki.bidix.info using proxy |
| TiddlyWikiRSS | Description asHtml | file: or tiddlywiki.bidix.info using proxy |
| [[Libération]] | noDesc | file: or tiddlywiki.bidix.info using proxy |
| [[TestComment]] | asText and filters | file: or tiddlywiki.bidix.info using proxy |
see : <<tag RSSFeed>> for the full list.

!Revision history
* V1.1.0 (2207/04/13)
**No more import functions
* V1.0.0 (2006/11/11)
**refactoring using core loadRemoteFile function
**import using new tiddlywiki:tiddler element
**import and presentation preserved without EricShulman's NestedSliderPlugin
**better display of items 
* v0.3.0 (24/08/2006)
** Filter on RSS item title
** Place to display redefined for asynchronous processing
* v0.2.2 (22/08/2006)
**Haloscan feed has no pubDate.
* v0.2.1 (08/05/2006)
* v0.2.0 (01/05/2006)
**Small adapations for del.icio.us feed
* v0.1.1 (28/04/2006)
**Bug : Channel without title 
* v0.1.0 (24/04/2006)
** initial release
! Did you know:
<<wikify {{var items=store.getTiddlerText("Factoids",'').split("\n----\n"); items[Math.floor(Math.random()*items.length)];}}>>
insert content from random content tiddler:

<<tiddler {{tids=store.getMatchingTiddlers("content"); tids[Math.floor(Math.random()*tids.length)].title;}}>>
<<loadTiddlers "label:Import new content from %0" updates {{var items=store.getTiddlerText("AllUrls",'').split("\n----\n"); items[Math.floor(Math.random()*items.length)];}}>>

See also AllUrls.
{{sectionTOC{}}}

!The instructor tiddlywiki

This topic exists only in the instructor tiddlywiki. It is not exported to the student tw's.

! Creating Content

To create content, click on the new content link in the right hand column. It will start a new tiddler tagged with the word "content". All of the content you create for the class must have the content tag otherwise it won't be published to the students. Also the content tiddlers are shown with  special view template that allows the students to record and view notes on a separate tiddler that is associated with the content tiddler.

In addition to content you can also tag tiddlers with the tag "structure". These are also exported, but unlike the content tiddlers, thie structure tag is designed to tag things like style sheets or themes that are needed for the student tiddlywiki to operate as opposed to things
that the student will read.

To edit content, click on the edit link at the top right of the tiddler. Because it is a content tiddler, using double mouse click to edit the tiddler is disabled to prevent the students from accidentally editing the tiddler and it also makes using double click to select text work better for the student.

It is suggested that you group your content into chapters and list them in order in the ChapterList which is displayed in the MainMenu.
The tiddler macro can be used to display the tiddler content into a single readable chapter while still retaining multiple content tiddlers that are reusable.

Chapters can be created as single tiddlers and later split into multiple tiddlers based on section headings.
[[Splitting Chapters]]

! Creating Presentations

To create a presentation, start a new content tiddler then add links to tiddlers that contain the slide contents. Add:
{{{
   <<slideshow theme:InstructorSlideShowStyleSheet >>
}}}
and any other options you want to use (e.g. clock etc) as documented in SlideShowPluginDoc.

When this button/macro is clicked in the Instructor book, a slide show will start that allows keyboard navigation (using the space bar, arrow keys and pageup/down keys) as well as the navigation buttons and table of contents menu (obtained by clicking on the slide number in the lower right). Overlays are revealed as you move through the presentation and comments on the slides are not displayed.

When this button/macro is clicked on in the studentbook, the InstructorSlideShowStyleSheet will be missing (as it is tagged InstructorOnly) and the default theme defined by: SlideShowStyleSheet will provide a student view of the slide show as you present yours on the screen. This default theme displays all overlays and comments to the student so you can add additional reference material. Also there is a place for the students to record their notes as you progress through the presentation.

It is suggested that you list your presentations in order PresentationList which is displayed in the MainMenu.

!! Creating  a Slide

A slide tiddler is pretty much the same as a regular tiddler except that you can use overlays and other styling. See SlideShowPluginDoc for details on creating a slide tiddler.

Note that in student view mode, overlays and comments are displayed.

! Special Tags

As you saw above tiddler tags control what happens to the tiddlers.
<part taglist>
|sortable|k
|Tag  <<autosort>>           |Description         |h
|attachment  |A tiddler that has an attached file with the AttachFilePlugin. Because the data feed apparently doesn't work with IE, it is a good idea to also embed the file inside a [[preformatted block|FormattingCheatSheet##Preformatted Text]] to allow users to cut/paste it. |
|chapter        |A tiddler defining a chapter    |
|content       |A tiddler that is going to be published to the students and makes up the content of the coursebook.    |
|DeletedTiddler   |A marker for tiddlers that have been replaced. The tiddler marked DeletedTiddler is a place holder that overwrites the tidder with that name in the student's coursebook. They can later clean up the deleted tiddlers.  |
|directions    |A descriptive tiddler that has directions on using the tiddlywiki rather than content on the material being presented. |
|examples    |A descriptive tag for a tiddler that walks the student through an example. It can be used to gather all examples into an example TOC.  |
|excludeStory |Any tiddler that shows up in a story is opened when the story is displayed unless that tiddler is tagged with excludeStory.  This is used to prevent naviagation tiddlers, or links to other tiddlers in the chapter tiddlers that act as a table of contents/outline for a chapter from being displayed.  |
|fixme          |A descriptive tiddler indicating that something is incorrect in the tagged tiddler.                                                   |
|InstructorOnly  |Tiddler that has meaning only for the instructor ~TiddlyWiki (e.g. this tiddler). It is not published for the students.    |
|~KeepRevisions  |A tiddler tagged with this will have the old version saved when a change is made.    |
|nopublish    |This tiddler will not be published even if it has a content or structure tag. Use for tagging incomplete tiddlers that are in the process of being finished.   |
|noReload   |A tiddler tagged with noReload will not be overwritten by the LoadTiddlersPlugin. It is usually applied to notes to make sure that a publishing error that publishes notes won't replace the notes in a student's coursebook.  |
|Notes         |A tag used by the TiddlerNotesPlugin to identify tiddlers that should be shown as notes. Notes are never published from the instructor book.|
|PatchedPlugin  |A plugin tiddler that has been patched from the released version   |
|presentation     |A tiddler defining a presentation    |
|quiz            |A descriptive tag for finding quizzes in the document, it has no operational meaning, but could be used for a TOC of quizzes.  |
|Revisions     |An older version of a tiddler tagged with the ~KeepRevisions tag    |
|scripts        |A tag indicating that the tiddler is an inline script/program providing functionality to the coursebook.  |
|slide           |A descriptive tag for identifying all the tiddlers that are going to be displayed as slides using the SlideShowPlugin. It has no operational meaning but can be used to generate a TOC of all the slide tidders.  |
|spellchecked  |Marks the tiddler where spell checking was left off. Start from first tiddler in all tiddler listing.    |
|story                |A tiddler that contains links to other tiddlers and can be used to open all the linked tiddlers (in order) in the story column    |
|structure     |A tiddler that is going to be published to the student but provides things like style sheets or themes for use in the student book.   |
|temporary    |A tiddler tagged with this will not be saved. Useful for scratch tiddlers.       |
|TOC                 |A table of contents tiddler that lists all the chapters, quizzes or presentations.    |
</part>

! Publishing for Students and others.
On the right hand side you will see a slider marked instructor. This has five items in it defined in the tiddler InstructorSidebarFunctions:

<<tiddler InstructorSidebarFunctions>>

The first link lets you change the title of the page. The page title shows up when printing from your browser and is intended to be used to allow a useful header on printouts. Clicking on the link displays a popup where you can type in your new title. Clicking cancel keeps the current title and typing {{{default}}} into the box will set the title to the default one for the tiddlywiki.

The second link allows you to configure the coursebook with different urls. For example you may want to run different courses off the same tiddlywiki (e.g. fall and spring semester or am and pm classes). This allows swapping the content of the GettingStarted tiddler that contains the key url's for the coursebook in hidden [[slices|Glossary/slice]].
FIXME consider removing this, or providing a pulldown/type box to enter the replacement tiddler.

The third link @@save studentbook@@ saves a copy of the studentbook that the students can download then then import the saved content to get a working studentbook. It does not export items tagged with InstructorOnly.

The fourth link @@save content@@ saves the content and structure tiddlers in a purestore format (without the tiddlywiki javascript code). The url in SiteUrl  should be changed to the location where this purestore file is published.

The fifth link @@save rss for content@@ generates an rss feed for content/structure tiddlers. The url for the rssReader macro in ContentChanges should be modified to point to the location where this file is published.

At some point there may be a link to save a blank instructor book. But for now you just have to manually [[export (using the backstage link|Using the Backstage Link]] all tiddlers not marked with content to get a blank instructor book.

! Important Tiddlers

*PatchedPlugin - a tiddler page that records which tiddlers have been patched. Going to that tiddler will also list all the plugins tagged with the PatchedPlugin tag.

! Plugins

There are a number of plugins used in this ~TiddlyWiki

!! Content Creation Plugins

This table documents useful plugins/macros for creating content.

|sortable|k
|<<autosort>> Plugin   | Docs                          | Feature                                                             |h
|AnnotationsPlugin   |in plugin topic     |adds a popup when rolling over a word or term  |
|AttachFilePlugin         |AttachFilePluginInfo  |Allows embedding supporting files in the tiddlywiki. May not work well with IE.  |
|FootnotesPlugin         |in plugin topic   |Creates numbered footnotes at the end of the tiddler. |
|NestedSlidersPlugin    |NestedSlidersPluginInfo   |Allows creation of folded content. PartTiddlerPlugin is useful with this as well. Can be useful to allow additional info to be recorded without overloading the user initially.   Also use for exercises. Have solution be a slider so it's exposed when the user want's to check the answers |
|PartTiddlerPlugin         |in plugin topic     |Allows using sections of a larger tiddler for annotations/popups and tiddler transclusion. Doesn't allow parts to be nested within each other however.   |
|QuizzerPlugin |QuizzerPluginDoc  |Allows creation of quizzes within tiddlers.  |
|SectionLinksPlugin|in plugin topic |Allows links to sections within another tiddler. Also allows use of {{{ {{sectionTOC{...}}} }}} to add a table of contents to a tiddler  |
|SlideShowPlugin         |SlideShowPluginDoc    |Mechanism for creating presentations                   |
|SparklinePlugin  |in plugin topic   |Allows simple area graphs inline with the text.  |
|StorySaverPlugin |StorySaverPluginInfo |Allows saving/displaying a set of tiddlers as a unit. Compose chapters from seperate tiddlers.  |
|TableSortingPlugin  |in plugin topic     |Allows dynamic sorting of tables       |


!! Functionality Plugins

This table documents useful plugins/macros that allow enhanced functionality of this ~TiddlyWiki.

|sortable|k
|Plugin <<autosort>>   | Docs                          | Feature                                                             |h
|FIXME |    |    |
|GotoPlugin   |GotoPluginInfo   |Provides the goto box to jump to a specific tiddler   |
|IntelliTaggerPlugin  |http://tiddlywiki.abego-software.de/doc/IntelliTagger.pdf  |Provides autocompletion of tags when editing them  |
|IntelliTagsEditCommandPlugin  |in plugin topic   |Provides edit mode for changing tags  |
|RedirectMacro    |in plugin topic      |Allows aliasing of words/terms to tiddlers without any special markup    |
|RSSReaderPlugin  |RSSReaderPluginDoc   |Provides an rss feed display for changes to the coursebook published by the author   |
|ShowPopup     |in plugin topic   |Display a tiddler as a popup. Good for reference panels.     |
|TemporaryTiddlersPlugin|in plugin topic  |Do not save any tiddlers tagged with {{{temporary}}}                               |
|TiddlerNotesPlugin      |in plugin topic              |Allows students to record notes into seperate tiddlers so content tiddlers can be updated at will without losing the student's notes.   |
|UnsavedChangesPlugin  |in plugin topic |Adds a menu item to the right sidebar when there are unsaved tiddlers.   |
|YourSearchPlugin       |[[YourSearch Help]]     |Enhanced searching capabilities.                         |

! Other tiddlers tagged with systemConfig

indicating they are actively modify operation of the TW.

CompareTiddlersPlugin
CopyTiddlerPlugin
CoreTweaksLocal
ExportTiddlersPlugin
FieldsEditorPlugin
FootnotesPlugin
ImagePathList
ImagePathPlugin
ImageSizePlugin
ImportTiddlersPlugin
InlineJavascriptPlugin
LoadTiddlersPlugin
MatchTagsPlugin
RefreshCommand
RevisionsPlugin
SaveAsPlugin
SectionLinksPlugin
SlideShowPlugin
SparklinePlugin
StorySaverPlugin
TableSortingPlugin
TaggedTemplateTweak
TemporaryTiddlersPlugin
TiddlerNotesPlugin
TiddlerTweakerPlugin
TiddlyLockPlugin
ToggleSideBarMacro
UnsavedChangesPlugin
YourSearchPlugin
zzLocalSettings

<<sectionTOC>>
/***
|Macro|redirect (alias)|
|Author|[[Clint Checketts]] and Paul Petterson|
|Version|1.1 Jan 26, 2006|
|Location|http://checkettsweb.com/styles/themes.htm#RedirectMacro|
|Description|This macro tells TW to find all instances of a word and makes it point to a different link. For example, whenever I put the word 'Clint' in a tiddler I want TiddlyWiki to turn it into a link that points to a tiddler titled 'Clint Checketts' Or the word 'TW' could point to a tiddler called 'TiddlyWiki' It even matches clint (which is lowercase) [[Clint]] leet lEEt LEET|
|Usage|{{{<<redirect TW TiddlyWiki>>}}} |
|Example|<<redirect TW "TiddlyWiki">> <<redirect Clint "Clint Checketts">> (Nothing should appear, its just setting it all up)<<redirectExact lEEt Elite>>|

!Revisions
1.1- Fixed tiddler refresh so a tiddler declaring a redirect will also render the redirect
1.0- Updated to work with TiddlyWiki 2.0 (thanks to Udo Borkowski)
0.9- Original release October 2005

!Code
***/
//{{{
version.extensions.redirectExact = {major: 1, minor: 2, revision: 0, date: new Date(2005,10,24)};
config.macros.redirectExact = {label: "Pickles Rock!"};
config.macros.redirectExact.handler = function(place,macroName,params,wikifier,paramString,tiddler){
 config.macros.redirect.handler(place,macroName,params,wikifier,paramString,tiddler);
}

version.extensions.redirect = {major: 1, minor: 2, revision: 0, date: new Date(2005,10,24)};
config.macros.redirect = {label: "Pickles Rock!"};

config.macros.redirect.handler = function(place,macroName,params,wikifier,paramString,tiddler){

var redirectExists = false
// Check to see if the wikifier exists
for (var i=0;i<config.formatters.length;i++)
 if (config.formatters[i].name == "redirect"+params[0])
 redirectExists = true;

//If it doesn't exist, add it!
if (!redirectExists){
 for( var i=0; i<config.formatters.length; i++ )
 if ( config.formatters[i].name=='wikiLink') break ;

 if ( i >= config.formatters.length ) {
 var e = "Can't find formatter for wikiLink!" ;
 displayMessage( e ) ;
 throw( e ) ;
 }

var pattern;
 if (macroName == 'redirect'){pattern=params[0].escapeRegExp().replace(/([A-Z])/img, function($1) {return("["+$1.toUpperCase()+$1.toLowerCase()+"]");});
 } else {
 pattern=params[0].escapeRegExp();
 }

 config.formatters.splice( i, 0, {
 name: "redirect"+params[0],
 match: "(?:\\b)(?:\\[\\[)?"+pattern+"(?:\\]\\])?(?:\\b)",
 subst: params[1],
 handler: function(w) {
 var link = createTiddlyLink(w.output,this.subst,false);
 w.outputText(link,w.matchStart,w.nextMatch);
 }
 });
 formatter = new Formatter(config.formatters); //update the tiddler
 if(tiddler) story.refreshTiddler(tiddler.title,null,true); //refresh tiddler so the new rule is applied
} // End if
}
//}}}
[img[pageLayout.png]] @@fixme missing image pageLayout.png@@

The normal view of the tiddlywiki coursebook shown above (as opposed to presentation view, full screen view etc) of the coursebook TiddlyWiki consists of three columns topped by a title bar which displays the contents of SiteTitle and SiteSubtitle (and the [[backstage|Using the Backstage Link]] link). The three columns in left to right order are called:
# [[main menu|MainMenu]]
# story
# [[sidebar|SideBarOptions]]

!! The Main Menu column
In the left hand column, you have the MainMenu which provides links to:
;[[Welcome]]
:The welcome page displayed when the TiddlyWiki is first opened. In the instructor coursebook the ReadMe tiddler is also displayed by default. You can add more links by editing the MainMenu.
;ContentChanges
: This links to the embedded rss feed reader and allows the student to view changes that have occurred in the coursebook. The setting for the rss feed is controlled by the slices at the bottom of GetingStarted.
; [[Bookmarks|BookmarkList]] (open)
: Clicking on [[Bookmarks|BookmarkList]] in the MainMenu opens a popup display of the [[BookmarkList]] tiddler. This is a normal tiddler that can be edited using [[tiddlywiki markup|FormattingCheatSheet]]. All content tiddlers include a ''bookmark'' link in their toolbar. Clicking on that link will automatically add a link to the tidder to the Bookmark tiddler. This makes it easy for students to bookmark a tiddler and later rearrange the bookmark links. The @@(open)@@ link next to Bookmarks opens the Bookmarks tiddler in the story column to allow the student to edit the list of bookmarks.
;Toggle Right Bar »
:Clicking on this link makes the side bar on the right disappear/reappear. This allows more of the available display screen to be used for the story column.
<<tiddler [[TiddlyWiki Page Layout (Instructor)##mainMenu]]>>
Below these links is the ChapterList that provides access to the coursebook content in multiple ways. Use of this is discussed in [[Using the Main Menu]].

!! The Story Column
This column is where most of the work in a TiddlyWiki will occur. It has a list of open tiddlers (story table of contents or STOC, not to be confused with a table of contents within a tiddler) at the top of the story column and below that are all of the tiddlers that are open. In [[Working with Tiddlers]] the two modes (view and edit) of the tiddler is discussed as is how to generate new info, change tags, titles etc.

!! The Sidebar Column
This column has controls associated with administering the tiddlywiki. The links are:
;goto
:The box labeled goto allows you to type in the name of a tiddler and after three characters are entered (or return is pressed) it will display tiddlers whose title matches what you are typing. This is a fast way of jumping to a tiddler. Note that some browsers (Internet Explorer for example) don't display the tiddlers below the search box. Instead they display the matching box off to the right of the search box, so you have to scroll to see the matching tiddlers. See also [[Bugs And Feature Requests|Bugs And Feature Requests##GotoPlugin]].
;search
:<<tiddler [[Reference Appendix 1 - TiddlyWiki Page Layout##search]] /% this content moved to end because of advanced formatting requirements including lists %/
;close all
:closes all tiddlers in the story column except tiddlers in edit mode.
; permaview
:Changed the url of the current page to include all of the currently open tiddlers. This url can be bookmarked using the browser's bookmark function. When the bookmark is opened, the same tiddlers will be opened in the story column.
;new tiddler
: Start editing a new tiddler.
<<tiddler [[TiddlyWiki Page Layout (Instructor)##newTiddlers]] >>
These links relate to saving TiddlyWiki content
;There are 5 unsaved tiddlers...
: this link shows up *only* when there is modified content in the TiddlyWiki. It can be used to display the modified tiddlers in the story column or save the tiddlers in the same way that the @@save changes@@ link does.
;save changes
: this links saves the tiddlers manually. Usually you would use the link above, But this is a standard link for tiddlywikis, so it is being kept even though there is another mechanism. <<tiddler [[TiddlyWiki Page Layout (Instructor)##saveChanges]] >>
<<tiddler [[TiddlyWiki Page Layout (Instructor)##instructorMenu]] >>
The last set of links deals with customizing and finding out useful info in the tiddlywiki.
;options »
:The options submenu controls a number of features of TiddlyWiki as well as letting you change other options. These setting are stored in your browser, so they will change if you use a different browser or access the TiddlyWiki on a different computer.
; tabs for {{{Off Timeline All Tags More}}}
:<<tiddler [[Reference Appendix 1 - TiddlyWiki Page Layout##optionTabs]] >> /% content moved to hidden section below due to formatting requirements %/

/%
! Outline
uses the ChapterList
        Use anatomy picture pointing out:
            Header
                Site Title
                Site Subtitle
            MainMenu (left)
                actions
                Presentations
                Chapters
                Quizzes
            Story column (center)
                TOC
                tiddlers in view/edit mode
            Sidebar (right)
                Actions
                Tabset
!search
This is the YourSearchPlugin search box that allows you to search for words/phrases in:
* tiddler content
* just in titles (when the search term is started with a ! (think section header)
* just in tags (when the search term is started with a #)
so: {{{#slide "link to" !edit}}} typed into the box will display a list of tiddlers that are:
* tagged with slide (because of #slide)
* has the phrase "link to" in the content (phrases are surrounded by quotes)
* has the word edit in the title (because of !edit)
Full details on the syntax and capabilities of the search box can be found at [[YourSearch Help]].
!optionTabs
Rendering these tabs can slow down TiddlyWiki on page refreshes, so by default the {{{Off}}} tab is selected.. However there are some useful features to be found here.
;Timeline
: Provides a list of tiddlers that have been changed grouped by the date of change
; All
: lists all the tiddlers in the coursebook
; Tags
: Lists all the tags used in the coursebook/TiddlyWiki. Allows display of the tagged tiddlers
; More
: provides access to the following tabs<part missingTab >
;;Missing
:: tiddlers that are referenced but do not exist. Clicking on the missing tiddler opens it and the @@references@@ link in the expanded toolbar can be used to find the tiddlers that have references to the missing tiddler. This can be used to find obsolete references after changing a tiddler title. The tab sometimes lists tiddlers that exist because of the way it scans for links to tiddlers. These existing tiddlers show up in bold faced type and not italics.</part>
;; Orphans
:: A list of tiddlers that are not linked to from other tiddlers.
;; Shadowed
:: A list of tiddlers where the default value for the tiddler has been overridden.
!end
%/
[[Reference Appendix 1 - TiddlyWiki Page Layout]]
[[Working with Tiddlers]]
[[Using the Content Links in the Main Menu]]
[[Using the Backstage Link]]

/***
***/

//{{{

config.commands.refresh = {
 text: 'refresh',
 tooltip: 'Refresh this tiddler',
 handler: function(e,src,title) {
  clearMessage();
  story.refreshTiddler(title,false,true); // force=true
  return false;
 }
};

//}}}
/***
|Name|RelatedTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#RelatedTiddlersPlugin|
|Version|1.1.8|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|InlineJavascriptPlugin, NestedSlidersPlugin, StyleSheetShortcuts|
|Description|starting from a selected tiddler, display a list and/or tree of linked or transcluded tiddlers|
!!!!!Usage
<<<
Starting from a specified tiddler (default=current tiddler), {{{<<relatedTiddlers>>}}} recursively follows the internal links[] data to find all other tiddlers that are related to it by linking (e.g., {{{[[TiddlerName]]}}}) or used as macro parameter (e.g., {{{<<tiddler TiddlerName>>}}}).

The results can be displayed as a simple flat list of related tiddler titles, or as an indented tree diagram that shows the specific connections between the related tiddlers, and can be helpful for identifying clusters of interdependent tiddlers or simply generating an on-the-fly site map for quick discovery and navigation through complex or unfamiliar document content. 
//{{{
<<relatedTiddlers TiddlerName hideform "exclude list">>
//}}}
*''TiddlerName'' (optional)<br>specifies the starting tiddler (and hides the 'select a tiddler' form controls).  Use keyword ''here'' to specify the current tiddler.
*''hideform'' (optional)<br>when present, suppress display of 'select tiddler' droplist and buttons.
*''"exclude list"'' (optional)<br>space-separated list of tiddlers whose links should not be followed.  Use quotes or double-square brackets to ensure list is processed as a single parameter.
The plugin also defines two functions that can be called externally (from other plugins or scripts) to generate and retrieve either a list of links or a formatted "tree view":
>{{{var list=config.macros.relatedTiddlers.getList(start,exclude,callback);}}}
>{{{var tree=config.macros.relatedTiddlers.getTree(start,exclude,callback);}}}
where ''start'' and 'exclude'' are the same as the macro parameters described above, plus an optional reference to a callback function that allows you to generate an alternative list/tree, based on application-specific data (such tiddler references contained in tags or custom fields), rather than using the default "links" list, like this:
>{{block{
{{{
window.myCallback=function(tiddler) {
	var list=[];
	// ... fill the list based on the specified tiddler ...
	return list;
}
}}}
}}}
The function takes a tiddler object as input, and returns a list of tiddler titles that are //directly// linked (or otherwise related) to that specific tiddler.  {{{getList()}}} and {{{getTree()}}} then use this information to find all the //indirect// connections between tiddlers to produce the list or tree output.
<<<
!!!!!Configuration
<<<
<<option chkRelatedTiddlersShowList>> show list display
<<option chkRelatedTiddlersShowTree>> show tree display
<<option chkRelatedTiddlersZoom>> enable autosizing of tree display //(aka, "zoom" or "shrink-and-grow")//
don't follow links contained in these tiddlers: <<option txtRelatedTiddlersExclude>>
<<<
!!!!!Examples
<<<
{{smallform{<<relatedTiddlers>>}}}

Using getList()/getTree() public API from other scripts/plugins:
><script show>
	var start="About";
	var exclude=config.options.txtRelatedTiddlersExclude.readBracketedList();
	var callback=null;
	var list=config.macros.relatedTiddlers.getList(start,exclude,callback);
	var tree=config.macros.relatedTiddlers.getTree(start,exclude,callback);
	return "There are "+list.length+" tiddlers related to [["+start+"]]...\n"+tree;
</script>
<<<
!!!!!Revisions
<<<
2009.09.29 [1.1.8] in findRelatedTiddlers(), fixed recursion when using non-null callback
2007.11.11 [1.1.7] in findRelatedTiddlers(), refactored into separate getlinks(),<br>and added param for optional callback function that can be used to return an alternative set of links.<br>Also added API functions, getTree() and getList() for use by other scripts
2007.07.13 [1.1.6] performance optimizations, more code cleanup
2007.07.10 [1.1.5] extensive code cleanup
2007.07.08 [1.1.0] converted from inline script
2007.06.29 [1.0.0] started (as inline script)
<<<
!!!!!Code
***/
//{{{
version.extensions.RelatedTiddlersPlugin={major: 1, minor: 1, revision: 8, date: new Date(2009,9,29)};

// initialize 'autozoom' and 'exclude' tree options (defaults are not to zoom, and to follow all links)
if (config.options.chkRelatedTiddlersZoom===undefined)
	config.options.chkRelatedTiddlersZoom=false;
if (config.options.txtRelatedTiddlersExclude===undefined)
	config.options.txtRelatedTiddlersExclude='GettingStarted DefaultTiddlers';
if (config.options.chkRelatedTiddlersShowList===undefined)
	config.options.chkRelatedTiddlersShowList=true;
if (config.options.chkRelatedTiddlersShowTree===undefined)
	config.options.chkRelatedTiddlersShowTree=false;

config.macros.relatedTiddlers={
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {

		// create form with unique DOM element ID (using current timestamp)... permits multiple form instances
		var now=new Date().getTime();
		var span=createTiddlyElement(place,"span");
		span.innerHTML=this.form.format(["relatedTiddlers_form"+now]);
		var form=span.getElementsByTagName("form")[0]; // find form that we just created
		var target=createTiddlyElement(span,"div"); // create target block in which generated output will be placed

		// initialize droplist contents (all tiddlers except hidden ones)
		var tids=store.getTiddlers('title','excludeLists');
		for (i=0; i<tids.length; i++) form.list.options[form.list.options.length]=new Option(tids[i].title,tids[i].title,false,false);

		// initialize exclude field (space-separated list)
		if (config.options.txtRelatedTiddlersExclude) form.exclude.value=config.options.txtRelatedTiddlersExclude;

		// set starting tiddler, form display, and/or exclude list from macro params (if present) and then show the results!
		var root="";
		var hide=false;
		var exclude=config.options.txtRelatedTiddlersExclude;
		if (params[0]) root=params[0]; // TiddlerName
		if (params[1]) hide=(params[1].toLowerCase()=="hideform"); // keyword: "hideform" or "showform" (default)
		if (params[2]) exclude=params[2]; // list of tiddlers whose links should not be followed
		if (root=="here") { var tid=story.findContainingTiddler(place); if (tid) root=tid.getAttribute("tiddler"); }
		if (store.tiddlerExists(root)) {
			// NOTE:  don't hide form when running IE, where putting initial focus on hidden form creates an error
			if (!config.browser.isIE) form.style.display=hide?"none":"block"; // show/hide the controls
			form.list.value=root; // set the root
			form.exclude.value=exclude; // set 'exclude' field
			form.get.click(); // DISPLAY INITIAL RESULTS (if tiddler is selected)
		}
	},
	form:
		"<form id='%0' action='javascript:;' style='display:inline;margin:0;padding:0;' onsubmit='return false'><!-- \
		--><span class='fine' style='float:left;vertical-align:bottom;width:39.5%;'><i>find all tiddlers related to:</i></span><!-- \
		--><span class='fine' style='float:left;vertical-align:bottom;'><i>exclude links contained in:</i></span><!-- \
		--><div style='clear:both'><!-- \
		--><select name=list size=1 style='width:39.5%' onchange='this.form.get.click()'><!-- \
		--><option value=''>select a tiddler...</option><!-- \
		--></select><!-- \
		--><input type='text' option='txtRelatedTiddlersExclude' name='exclude' value='' style='width:40%' \
			title='enter the names of tiddlers whose links should NOT be followed' \
			onkeyup='if (event.keyCode==13) { this.blur(); this.form.get.click(); }'  \
			onchange='config.options[this.getAttribute(\"option\")]=this.value;saveOptionCookie(this.getAttribute(\"option\"));'><!-- \
		--><input type=button name=get value='get related' style='width:10%'  \
			onclick='config.macros.relatedTiddlers.show(this.form,this.form.nextSibling);'><!-- \
		--><input type=button name=done value='done' disabled style='width:10%'  \
			onclick='this.form.list.selectedIndex=0; this.form.get.click();'><!-- \
		--></div><!-- \
		--></form>",
	styles:
		".relatedTiddlers blockquote \
			{ border-left:1px dotted #999; margin:0 25px; padding-left:.5em; font-size:%0%; line-height:115%; } \
		.relatedTiddlers .borderleft \
			{ margin:0; padding:0; margin-left:1em; border-left:1px dotted #999; padding-left:.5em; } \
		.relatedTiddlers .fourcolumns \
			{ display:block; -moz-column-count:4; -moz-column-gap:1em; -moz-column-width:25%} \
		.relatedTiddlers a \
			{ font-weight:normal; } \
		.relatedTiddlers .bold, .relatedTiddlers .bold a \
			{ font-weight:bold; } \
		.relatedTiddlers .floatright \
			{ float:right; } \
		.relatedTiddlers .clear \
			{ clear:both; }	",
	toggleform:
		"{{floatright{<html><a href='javascript:;' class='button' title='show/hide tiddler selection droplist and buttons' \
		onclick='var here=story.findContainingTiddler(this); var tid=here?here.getAttribute(\"tiddler\"):\"\"; \
			var f=document.getElementById(\"%0\"); var hide=(f.style.display!=\"none\"); \
			f.style.display=hide?\"none\":\"inline\"; this.innerHTML=hide?\"show form\":\"hide form\"; return false;'>%1</a></html>}}}",
	treecheck:
		"{{floatright{@@display:none;<<option chkRelatedTiddlersShowTree>>@@<html><a href='javascript:;' class='button' onclick='this.parentNode.previousSibling.firstChild.click(); return false;'>tree view</a></html>}}}",
	tree:
		"{{clear{\n----\n}}} \
		{{floatright small{<<option chkRelatedTiddlersZoom>>autosize tree display}}} \
		{{fine{\n''tiddlers linked from or included by'' [[%0]]\n}}}%1",
	listcheck:
		"{{floatright{@@display:none;<<option chkRelatedTiddlersShowList>>@@<html><a href='javascript:;' class='button' onclick='this.parentNode.previousSibling.firstChild.click(); return false;'>list view</a></html>}}}",
	list:
		"{{clear{\n----\n}}} \
		{{fine{\n''tiddlers containing links to'' [[%0]]\n}}} \
		{{small fourcolumns borderleft{\n%1}}} \
		{{fine{\n''tiddlers linked from or included by'' [[%0]]\n}}} \
		{{borderleft{\n \
			{{fine{\n''bold''=//direct links//, plain=//indirect links//, ''...''=//links not followed//}}} \
			{{small fourcolumns{\n%2}}} \
		}}}",
	skipped:
		"<html><span title='links from %0 have NOT been followed'>...</span></html>",
	mouseover: function(ev) {
		this.saveSize=this.style.fontSize;
		this.style.fontSize='100%';
		this.style.borderLeftStyle='solid';
	},
	mouseout: function(ev) {
		this.style.fontSize=this.saveSize;
		this.style.borderLeftStyle='dotted';
	},
	findRelatedTiddlers: function(tid,tids,treeout,level,exclude,callback) { 
		// recursively build list of related tids (links and includes FROM the root tiddler) and generate treeview output
		var t=store.getTiddler(tid);
		if (!t || tids.contains(tid)) return tids; // tiddler already in results (or missing tiddler)... just return current results
		tids.push(t.title); // add tiddler to results
		var skip=exclude && exclude.contains(tid);
		treeout.text+=level+"[["+tid+"]]"+(skip?this.skipped.format([tid]):"")+"\n";
		if (skip) return tids; // branch is pruned... don't follow links
		var links=callback?callback(t):this.getLinks(t);
		for (var i=0; i<links.length; i++) tids=this.findRelatedTiddlers(links[i],tids,treeout,level+">",exclude,callback);
		return tids;
	},
	getLinks: function(tiddler) {
		if (!tiddler.linksUpdated) tiddler.changed();
		return tiddler.links;
	},
	getTree: function(start,exclude,callback) {
		// get related tiddlers and generate blockquote-indented tree output
		var list=[]; var tree={text:""}; var level="";
		list=this.findRelatedTiddlers(start,list,tree,level,exclude,callback);
		return tree.text;
	},
	getList: function(start,exclude,callback) {
		// get related tiddlers and generate blockquote-indented tree output
		var list=[]; var tree={text:""}; var level="";
		list=this.findRelatedTiddlers(start,list,tree,level,exclude,callback);
		return list;
	},
	show: function(form,target) {
		removeChildren(target); form.done.disabled=true; // clear any existing output and disable 'done' button
		var start=form.list.value; if (!start.length) return; // get selected starting tiddler.  If blank value (heading), do nothing

		// get related tiddlers and generate blockquote-indented tree output
		var rels=[]; var treeview={text:""}; var level="";
		var exclude=config.options.txtRelatedTiddlersExclude.readBracketedList();
		var rels=this.findRelatedTiddlers(start,rels,treeview,level,exclude);
		rels.shift(); // remove self from list
		rels.sort(); // sort titles alphabetically

		// generate list output
		var tid=store.getTiddler(start);
		var relsview=""; for (t=0; t<rels.length; t++) {
			relsview+=tid.links.contains(rels[t])?("{{bold{[["+rels[t]+"]]}}}"):("[["+rels[t]+"]]");
			if (exclude && exclude.contains(rels[t])) relsview+=this.skipped.format([rels[t]]);
			relsview+="\n";
		}
	
		// get references TO the root tiddler, add to related tiddlers and generate refsview output
		var refs=[]; var referers=store.getReferringTiddlers(start);
		for(var r=0; r<referers.length; r++)
			if(referers[r].title!=start && !referers[r].tags.contains("excludeLists")) refs.push(referers[r].title);
		var refcount=refs.length; var relcount=rels.length; // remember individual counts
		for (var r=0; r<refs.length; r++) rels.pushUnique(refs[r]); // combine lists without duplicates
		var total=rels.length; // get combined total
		var refsview="[["+refs.sort().join("]]\n[[")+"]]\n";
	
		// set custom blockquote styles for treeview
		setStylesheet(this.styles.format([config.options.chkRelatedTiddlersZoom?80:100]),'relatedTiddlers_styles');

		// assemble and render output
		var summary=(total?(total+" tiddler"+(total==1?" is":"s are")):"There are no tiddlers")+" related to: [["+start+"]]";
		var list=this.list.format([start,refsview.length?refsview:"//none//",relsview.length?relsview:"//none//"]);
		var tree=this.tree.format([start,treeview.text]);
		var toggle=this.toggleform.format([form.id,(form.style.display=='none'?'show form':'hide form')]);
		var sep="{{floatright{ | }}}";
		var showList=total && config.options.chkRelatedTiddlersShowList;
		var showTree=relcount && config.options.chkRelatedTiddlersShowTree;
		var out="{{relatedTiddlers{"+toggle+(relcount?sep+this.treecheck:"")+(total?sep+this.listcheck:"")+summary+(showList?list:"")+(showTree?tree:"")+"}}}";
		wikify(out,target);
		form.done.disabled=false; // enable 'done' button

		// add mouseover/mouseout handling to blockquotes (for autosizing)
		var blocks=target.getElementsByTagName("blockquote");
		for (var b=0; b<blocks.length; b++)
			{ blocks[b].onmouseover=this.mouseover; blocks[b].onmouseout=this.mouseout; }

		// add side-effect to checkboxes so that display is refreshed when a checkbox state is changed
		var checks=target.getElementsByTagName("input");
		for (var c=0; c<checks.length; c++) {
			if (checks[c].type.toLowerCase()!="checkbox") continue;
			checks[c].coreClick=checks[c].onclick; // save standard click handler
			checks[c].formID=form.id; // link checkbox with correponding form
			checks[c].onclick=function() { this.coreClick.apply(this,arguments); document.getElementById(this.formID).get.click(); }
		}
	}
}
//}}}
/%
|Name|RescueStoreAreaCommand|
|Source|http://www.TiddlyTools.com/#RescueStoreAreaCommand|
|Version|1.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|script bookmarklet|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|rescue tiddler changes from online document when net goes down during editing|
%/<script label="$1" title="rescue tiddlers from current document storeArea">
	if(typeof version==undefined||version.title!='TiddlyWiki')
		{alert(document.location.href+'\n\nis not a TiddlyWiki document');return false;}
	if (!confirm('Preparing to rescue storeArea contents... press OK to proceed')) return false;
	var sa=store.allTiddlersAsHtml().htmlEncode();
	var win=window.open();
	win.document.open();
	win.document['write']('<html><body><pre>'+sa+'</pre></body></html>');
	win.document.close();
	alert('copy/paste the displayed storeArea content into a local text file');
	win.focus();
</script><script>
	if ("$1"=="$"+"1") place.lastChild.innerHTML="Rescue current storeArea contents";
</script>
! ~TiddlyWiki resources

|tiddlywikiHomepage:|http://www.tiddlywiki.com  |
|tiddlywikiGoogleGroup:|http://groups.google.com/group/TiddlyWiki  |
|tiddlywikiMarkupCheatSheet:|http://tiddlywiki.org/wiki/TiddlyWiki_Markup  |

! Class resources

|classContent: | <<tiddler [[GettingStarted::courseHomeContent]]>> |
/***
|Name|RevisionsPlugin|
|Source|http://www.linux-lovers.be/RevisionsPlugin/#RevisionsPlugin|
|Version|1.0.1|
|Author|Willy De la Court (willy [dot] delacourt [at] telenet [dot] be)|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.5|
|Type|plugin|
|Requires||
|Overrides|config.commands.saveTiddler|
|Description|Create revisions of a tiddler when changes are saved|
!!!Usage
<<<
This plugin automatically updates the default (shadow) ToolbarCommands slice definitions to insert the ''revisions'' command.

When you select the ''revisions'' command, a drop down popup is shown with all the revisions of the current tiddler.

The plugin takes control of the ''saveTiddler'' command and check the tags of the current tiddler. If the current tiddler is taged with the <<tag KeepRevisions>> tag then the ''saveTiddler'' command automatically will create a new revision of the tiddler.

All revision tiddlers will be tagged with <<tag Revisions>>, <<tag excludeLists>> and <<tag excludeMissing>>.

Note: if you are already using customized toolbar definitions, you will need to manually add the ''revisions'' toolbar command to your existing ToolbarCommands tiddler, e.g.:
{{{
|EditToolbar|... revisions ... |
}}}
<<<
!!!Revisions
<<<
2009.03.27 [1.0.1] added some documentation
2009.03.23 [1.0.0] initial version
<<<
!!!Code
***/
//{{{
version.extensions.RevisionsPlugin= {major: 1, minor: 0, revision: 0, date: new Date(2009,3,23)};

config.extensions.RevisionsPlugin = {};
config.extensions.RevisionsPlugin.core_saveTiddler_handler = config.commands.saveTiddler.handler;
merge(config.commands.saveTiddler,{
	zeroPad: 4,
	keepRevisonsTag: "KeepRevisions",
	suffixText: " Revision(%0)",
	newtags: ["Revisions", "excludeLists", "excludeMissing"],
	keepTags: false
	});

config.commands.saveTiddler.handler = function(event,src,title) {
	if(store.tiddlerExists(title) && store.getTiddler(title).isTagged(this.keepRevisonsTag)) {
		// Not a new tiddler and tagged with keepRevisonsTag
		n = 1;
		var newTitle = title + this.suffixText.format([String.zeroPad(n, this.zeroPad)]);
		while (store.tiddlerExists(newTitle) || document.getElementById(story.idPrefix + newTitle)) {
			n++;
			newTitle = title + this.suffixText.format([String.zeroPad(n, this.zeroPad)]);
		}
		var text = store.getTiddlerText(title, '');
		var newtags = this.newtags;
		var newfields = {};
		var tid = store.getTiddler(title);
		if (tid) {
			if(this.keepTags)
				for (var t = 0; t < tid.tags.length; t++) newtags.push(tid.tags[t]);
			store.forEachField(tid,
				function(t, f, v) {
					newfields[f] = v;
				},
			true);
		}
		store.saveTiddler(newTitle, newTitle, text, tid.modifier, tid.modified, newtags, newfields, false);
	}
	return config.extensions.RevisionsPlugin.core_saveTiddler_handler.apply(this,arguments);
}

config.commands.revisions = {
	type: "popup",
	text: "revisions",
	tooltip: "Show revisions of this tiddler",
	shortSuffixText: " Revision("
}

config.commands.revisions.handlePopup = function(popup,title) {
	var tiddlertitle = title;
	store.forEachTiddler(function(title,tiddler) {
		if(title.startsWith(tiddlertitle + config.commands.revisions.shortSuffixText))
			createTiddlyLink(createTiddlyElement(popup,"li"),title,true,null,false,null,true);
		});
};

config.shadowTiddlers.ToolbarCommands = config.shadowTiddlers.ToolbarCommands.replace(
	/jump/m,
	"revisions jump");

//}}}
<<slideShow  theme:InstructorSlideShowStyleSheet2 toc:titles noClicks footer:"copyright&copy; 2010<br />John Rouillard" clock:-60 label:"Start cycling show" auto:15 cycle tooltip:"Start slideshow in instructor projection mode"'>>

This tiddler is to be displayed during a class lunch break. It auto-advances each slide after a 30 second interval and loops back to the beginning. It also display a 1 hour countdown timer that indicates when the class will resume.

[[Random Factoid]]

FIXME: need a style file that makes the title of this tiddler be large and centered so it shows prominently on each slide.
The slide titles for the default instructor theme are fine.
/***
|Name|SaveAsPlugin|
|Source|http://www.TiddlyTools.com/#SaveAsPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveAsPluginInfo|
|Version|2.7.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|Save current document to another path/filename|
!!!!!Documentation
<<<
see [[SaveAsPluginInfo]]
<<<
!!!!!Revisions
<<<
2009.10.13 2.7.0 added 'here' param (saves current tiddler)
2009.08.16 2.6.2 fixed handling for backstage
| Please see [[SaveAsPluginInfo]] for additional revision details |
2006.02.03 1.0.0 Created
<<<
!!!!!Code
***/
//{{{
version.extensions.SaveAsPlugin= {major: 2, minor: 7, revision: 0, date: new Date(2009,10,13)};

config.macros.saveAs = {
	label: 'save as...',
	labelparam: 'label:',
	prompt: 'Save current document to a different path/file',
	promptparam: 'prompt:',
	filePrompt: 'Please select or enter a target path/filename',
	targetparam: 'target:',
	defaultFilename: 'new.html',
	filenameparam: 'filename:',
	currfilekeyword: 'here',
	typeparam: 'type:',
	type_TW: 'tw', type_PS: 'ps', type_TX: 'tx', type_CS: 'cs', type_NF: 'nf', // file type tokens
	type_map: {
		tiddlywiki:'tw', tw:'tw', wiki: 'tw',
		purestore: 'ps', ps:'ps', store:'ps',
		plaintext: 'tx', tx:'tx', text: 'tx',
		comma:     'cs', cs:'cs', csv:  'cs',
		newsfeed:  'nf', nf:'nf', xml:  'nf', rss:'nf'
	},
	limitparam: 'limit:',
	replaceparam: 'replace',
	mergeparam: 'merge',
	quietparam: 'quiet',
	openparam: 'open',
	askParam: 'ask',
	hereParam: 'here',
	askMsg: "Enter a tag filter (use * for all tiddlers, 'none' for blank document)",
	hereMsg: 'Enter a tiddler title',
	emptyParam: 'none',
	confirmmsg: "Found %0 tiddlers matching\n\n'%1'\n\nPress OK to proceed",
	mergeprompt: '%0\nalready contains tiddler definitions.\n'
		+'\nPress OK to add new/revised tiddlers to current file contents.'
		+'\nPress Cancel to completely replace file contents',
	mergestatus: 'Merged %0 new/revised tiddlers and %1 existing tiddlers',
	okmsg: '%0 tiddlers written to %1',
	failmsg: 'An error occurred while creating %1',
	filter: '',
	handler: function(place,macroName,params) {
		if ((params[0]||'').startsWith(this.labelparam))
			var label=params.shift().substr(this.labelparam.length);
		if ((params[0]||'').startsWith(this.promptparam))
			var prompt=params.shift().substr(this.promptparam.length);
		if ((params[0]||'').startsWith(this.targetparam))
			var target=params.shift().substr(this.targetparam.length);
		if ((params[0]||'').startsWith(this.filenameparam))
			var filename=params.shift().substr(this.filenameparam.length);
		if ((params[0]||'').startsWith(this.typeparam))
			var filetype=this.type_map[params.shift().substr(this.typeparam.length).toLowerCase()];
		if ((params[0]||'').startsWith(this.limitparam))
			var limit=params.shift().substr(this.limitparam.length);
		var q=((params[0]||'')==this.quietparam);   if (q) params.shift();
		var o=((params[0]||'')==this.replaceparam); if (o) params.shift();
		var m=((params[0]||'')==this.mergeparam);   if (m) params.shift();
		var a=((params[0]||'')==this.openparam);    if (a) params.shift();
		var btn=createTiddlyButton(place,label||this.label,prompt||this.prompt,
			function(){ config.macros.saveAs.go( this.getAttribute('target'),
				this.getAttribute('filename'), this.getAttribute('filetype'),
				this.getAttribute('filter'), this.getAttribute('limit'),
				this.getAttribute('quiet')=='true',
				this.getAttribute('overwrite')=='true',
				this.getAttribute('merge')=='true',
				this.getAttribute('autoopen')=='true',
				this);
				return false;
			});
		if (target) btn.setAttribute('target',target);
		if (filename) btn.setAttribute('filename',filename);
		btn.setAttribute('filetype',filetype||this.type_TW);
		btn.setAttribute('filter',params.join(' '));
		btn.setAttribute('limit',limit||0);
		btn.setAttribute('quiet',q?'true':'false');
		btn.setAttribute('overwrite',o?'true':'false');
		btn.setAttribute('merge',m?'true':'false');
		btn.setAttribute('autoopen',a?'true':'false');
	},
	go: function(target,filename,filetype,filter,limit,quiet,overwrite,merge,autoopen,here) {
		var cm=config.messages; // abbreviation
		var cms=config.macros.saveAs; // abbreviation
		if (window.location.protocol!='file:') // make sure we are local
			{ displayMessage(cm.notFileUrlError); return; }

		// get tidders, confirm filtered results
		var tids=cms.selectTiddlers(filter,here);
		if (tids===false) return; // cancelled by user
		if (cms.filter!=cms.emptyParam && cms.filter.length && !quiet)
			if (!confirm(cms.confirmmsg.format([tids.length,cms.filter]))) return;

		// get target path/filename
		if (!filetype) filetype=this.type_TW;
		target=target||cms.getTarget(filename,filetype==this.type_TX?'txt':filetype==this.type_CS?'csv':'html');
		if (!target) return; // cancelled by user

		var link='file:///'+target.replace(/\\/g,'/');
		var samefile=link==decodeURIComponent(window.location.href);
		var p=getLocalPath(document.location.href);
		if (samefile) {
			if (config.options.chkSaveBackups)
				{ var t=loadOriginal(p);if(t)saveBackup(p,t); }
			if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function)
				saveRss(p);
		}
		var notes='';
		var total={val:0};
		var out=this.assembleFile(target,filetype,tids,limit||0,notes,quiet,overwrite,merge,total);
		var ok=saveFile(target,out);
		if (ok && autoopen) {
			if (!samefile) window.open(link).focus();
			else { store.setDirty(false); window.location.reload(); }
		}
		if (!quiet || !(ok && autoopen))
			displayMessage((ok?this.okmsg:this.failmsg).format([total.val,target]),link);
	},
	selectTiddlers: function(filter,here) {
		var cms=config.macros.saveAs; // abbreviation
		var tids=[]; cms.filter=filter||'';
		if (filter==cms.emptyParam)
			return tids;
		if (filter==config.macros.saveAs.hereParam) {
			var here=story.findContainingTiddler(here);
			if (here) var tid=here.getAttribute('tiddler');
			else var tid=prompt(config.macros.saveAs.hereMsg,'');
			while (tid && !store.tiddlerExists(tid)) {
				var err='"'+tid+'" not found.\nPlease try again.\n\n';
				var tid=prompt(err+config.macros.saveAs.hereMsg,tid);
			}
			if (!tid) return false;  // cancelled by user
			return [store.getTiddler(tid)];
		}
		if (filter==config.macros.saveAs.askParam) {
			filter=prompt(config.macros.saveAs.askMsg,'');
			if (!filter) return false;  // cancelled by user
			cms.filter=filter=='*'?'':filter;
		}
		if (!filter||!filter.length||filter=='*') tids=store.getTiddlers('title');
		else tids=store.filterTiddlers('[tag['+filter+']]');
		return tids;
	},
	getTarget: function(defName,defExt) {
		var cms=config.macros.saveAs; // abbreviation
		// get new target path/filename
		var newPath=getLocalPath(window.location.href);
		var slashpos=newPath.lastIndexOf('/'); if (slashpos==-1) slashpos=newPath.lastIndexOf('\\'); 
		if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
		if (!defName||!defName.length) { // use current filename as default
			var p=getLocalPath(window.location.href);
			var s=p.lastIndexOf('/'); if (s==-1) s=p.lastIndexOf('\\'); 
			if (s!=-1) defName=p.substr(s+1);
		}
		var defFilename=(defName||cms.defaultFilename).replace(/.html$/,'.'+defExt);
		var target=cms.askForFilename(cms.filePrompt,newPath,defFilename,defExt);
		if (!target) return; // cancelled by user
		// if specified file does not include a path, assemble fully qualified path and filename
		var slashpos=target.lastIndexOf('/'); if (slashpos==-1) slashpos=target.lastIndexOf('\\');
		if (slashpos==-1) target=target+(defName||cms.defaultFilename).replace(/.html$/,'.'+defExt);
		return target;
	},
	askForFilename: function(msg,path,file,defExt) {
		if(window.Components) { // moz
			try {
				netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
				var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
				var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
				picker.init(window, msg, nsIFilePicker.modeSave);
				var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
				thispath.initWithPath(path);
				picker.displayDirectory=thispath;
				picker.defaultExtension=defExt||'html';
				picker.defaultString=file;
				picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
				if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
			}
			catch(e) { alert('error during local file access: '+e.toString()) }
		}
		else { // IE
			try { // XP/Vista only
				var s = new ActiveXObject('UserAccounts.CommonDialog');
				s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
				s.FilterIndex=(defExt=='txt')?2:3; // default to HTML files;
				s.InitialDir=path;
				s.FileName=file;
				if (s.showOpen()) var result=s.FileName;
			}
			catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE
		}
		return result;
	},
	plainTextHeader:
		 'Source:\n\t%0\n'
		+'Title:\n\t%1\n'
		+'Subtitle:\n\t%2\n'
		+'Created:\n\t%3 by %4\n'
		+'Application:\n\tTiddlyWiki %5 / %6 %7\n\n',
	plainTextTiddler:
		'- - - - - - - - - - - - - - -\n'
		+'|     title: %0\n'
		+'|   created: %1\n'
		+'|  modified: %2\n'
		+'| edited by: %3\n'
		+'|      tags: %4\n'
		+'- - - - - - - - - - - - - - -\n'
		+'%5\n',
	plainTextFooter:
		'',
	newsFeedHeader:
		 '<'+'?xml version="1.0"?'+'>\n'
		+'<rss version="2.0">\n'
		+'<channel>\n'
		+'<title>%1</title>\n'
		+'<link>%0</link>\n'
		+'<description>%2</description>\n'
		+'<language>en-us</language>\n'
		+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
		+'<pubDate>%3</pubDate>\n'
		+'<lastBuildDate>%3</lastBuildDate>\n'
		+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
		+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
	newsFeedTiddler:
		'\n%0\n',
	newsFeedFooter:
		'</channel></rss>',
	pureStoreHeader:
		 '<html><body>'
		+'<style type="text/css">'
		+'	#storeArea {display:block;margin:1em;}'
		+'	#storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
		+'	#pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
		+'</style>'
		+'<div id="pureStoreHeading">'
		+'	TiddlyWiki "PureStore" export file<br>'
		+'	Source'+': <b>%0</b><br>'
		+'	Title: <b>%1</b><br>'
		+'	Subtitle: <b>%2</b><br>'
		+'	Created: <b>%3</b> by <b>%4</b><br>'
		+'	TiddlyWiki %5 / %6 %7<br>'
		+'	Notes:<hr><pre>%8</pre>'
		+'</div>'
		+'<div id="storeArea">',
	pureStoreTiddler:
		'%0\n%1',
	pureStoreFooter:
		'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
	assembleFile: function(target,filetype,tids,limit,notes,quiet,overwrite,merge,total) {
		var revised='';
		var now = new Date().toLocaleString();
		var src=convertUnicodeToUTF8(document.location.href);
		var title = convertUnicodeToUTF8(wikifyPlain('SiteTitle').htmlEncode());
		var subtitle = convertUnicodeToUTF8(wikifyPlain('SiteSubtitle').htmlEncode());
		var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
		var twver = version.major+'.'+version.minor+'.'+version.revision;
		var v=version.extensions.SaveAsPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
		var headerargs=[src,title,subtitle,now,user,twver,'SaveAsPlugin',pver,notes];
		switch (filetype) {
			case this.type_TX: // plain text
				var header=this.plainTextHeader.format(headerargs);
				var footer=this.plainTextFooter;
				break;
			case this.type_CS: // comma-separated
				var fields={};
				for (var i=0; i<tids.length; i++) for (var f in tids[i].fields) fields[f]=f;
				var names=['title','created','modified','modifier','tags','text'];
				for (var f in fields) names.push(f);
				var header=names.join(',')+'\n';
				var footer='';
				break;
			case this.type_NF: // news feed (XML)
				headerargs[0]=store.getTiddlerText('SiteUrl','');
				var header=this.newsFeedHeader.format(headerargs);
				var footer=this.newsFeedFooter;
				tids=store.sortTiddlers(tids,'-modified');
				break;
			case this.type_PS: // PureStore (no code)
				var header=this.pureStoreHeader.format(headerargs);
				var footer=this.pureStoreFooter;
				break;
			case this.type_TW: // full TiddlyWiki
			default:
				var currPath=getLocalPath(window.location.href);
				var original=loadFile(currPath);
				if (!original) { alert(config.messages.cantSaveError); return; }
				var posDiv = locateStoreArea(original);
				if (!posDiv) { alert(config.messages.invalidFileError.format([currPath])); return; }
				var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
				var footer = '\n'+original.substr(posDiv[1]);
				break;
		}
		if (parseInt(limit)!=0) tids=tids.slice(0,limit);
		var out=this.getData(target,filetype,tids,quiet,overwrite,merge,fields);
		var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
		// if full TW, insert page title and language attr, and reset MARKUP blocks as needed...
		if (filetype==this.type_TW) {
			var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
			revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
			revised=updateLanguageAttribute(revised);
			var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
			revised=updateMarkupBlock(revised,'PRE-HEAD',
				titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
			revised=updateMarkupBlock(revised,'POST-HEAD',
				titles.contains('MarkupPostHead')?'MarkupPostHead':null);
			revised=updateMarkupBlock(revised,'PRE-BODY',
				titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
			revised=updateMarkupBlock(revised,'POST-SCRIPT',
				titles.contains('MarkupPostBody')?'MarkupPostBody':null);
		}
		total.val=out.length;
		return revised;
	},
	getData: function(target,filetype,tids,quiet,overwrite,merge,fields) {
		// output selected tiddlers and gather list of titles (for use with merge)
		var out=[]; var titles=[];
		var url=store.getTiddlerText('SiteUrl','');
		for (var i=0; i<tids.length; i++) {
			out.push(this.formatItem(store,filetype,tids[i],url,fields));
			titles.push(tids[i].title);
		}
		// if TW or PureStore format, ask to merge with existing tiddlers (if any)
		if (filetype==this.type_TW || filetype==this.type_PS) {
			if (overwrite) return out; // skip merge... forced overwrite
			var txt=loadFile(target);
			if (txt && txt.length) {
				var remoteStore=new TiddlyWiki();
				if (version.major+version.minor*.1+version.revision*.01<2.52) txt=convertUTF8ToUnicode(txt);
				if (remoteStore.importTiddlyWiki(txt) && (merge||confirm(this.mergeprompt.format([target])))) {
					var existing=remoteStore.getTiddlers('title');
					for (var i=0; i<existing.length; i++)
						if (!titles.contains(existing[i].title))
							out.push(this.formatItem(remoteStore,filetype,existing[i],url));
					if (!quiet) displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
				}
			}
		}
		return out;
	},
	formatItem: function(s,f,t,u,fields) {
		if (f==this.type_TW)
			var r=s.getSaver().externalizeTiddler(s,t);
		if (f==this.type_PS)
			var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
		if (f==this.type_NF)
			var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
		if (f==this.type_TX)
			var r=this.plainTextTiddler.format([t.title, t.created.toLocaleString(), t.modified.toLocaleString(),
				t.modifier, String.encodeTiddlyLinkList(t.tags), t.text]);
		if (f==this.type_CS) {
			function toCSV(t) { return '"'+t.replace(/"/g,'""')+'"'; } // always encode CSV
			var out=[ toCSV(t.title), toCSV(t.created.toLocaleString()), toCSV(t.modified.toLocaleString()),
				toCSV(t.modifier), toCSV(String.encodeTiddlyLinkList(t.tags)), toCSV(t.text) ];
			for (var f in fields) out.push(toCSV(t.fields[f]||''));
			var r=out.join(',');
		}
		return r||'';
	}
};
//}}}
//{{{
// automatically add saveAs to backstage
config.tasks.saveAs = {
	text: 'saveAs',
	tooltip: config.macros.saveAs.prompt,
	action: function(){ clearMessage(); config.macros.saveAs.go(); }
}
config.backstageTasks.splice(config.backstageTasks.indexOf('save')+1,0,'saveAs');
//}}}
|Name|SaveAsPluginInfo|
|Source|http://www.TiddlyTools.com/#SaveAsPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveAsPluginInfo|
|Version|2.7.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|Documentation for SaveAsPlugin|
>//Note: This plugin replaces ''[[NewDocumentPlugin]]'' (except for the HTML+CSS "snapshot" features, which are now provided by [[SnapshotPlugin]].//
!!!!!Usage
<<<
This plugin automatically adds a 'save as' command to the TiddlyWiki 'backstage' menu so you can quickly create an exact copy of the current TiddlyWiki document.  The plugin also defines a macro that you can use to place a "save as..." command link into your sidebar/mainmenu/any tiddler (or wherever you like).  When the command link is clicked, a system-specific dialog box will be displayed so you can select/enter the desired target path and filename.
{{{
<<saveAs "label:..." "prompt:..." "filename:..." "type:..." "limit:..."
	quiet replace merge open filter|ask|here|none>>
}}}
//(all parameters are optional)//
*''label:...''<br>custom link text (instead of "save as...")
*''prompt:...''<br>custom tooltip text
*''filename:...''<br>default filename to be shown when asking for an output path/file
*''type:...''<br>a keyword, indicating one of the following output file formats:
**''~TiddlyWiki''<br>(or ''wiki'' or ''tw'') a TiddlyWiki HTML document 
**''~PureStore''<br>(or ''store'' or ''ps'') a TiddlyWiki "PureStore" HTML export file (just tiddlers, no core code)
**''~PlainText''<br>(or ''text'' or ''tx'') a plain text file listing of tiddler //source// content
**''Comma''<br>(or ''csv'' or ''cs'') a Comma-Separated Value (CSV) database/spreadsheet file
**''~NewsFeed''<br>(or ''xml'' or ''rss'' or ''nf'') an RSS ~NewsFeed XML file
*''limit:...''<br>output is limited to the specified number of tiddlers
*''quiet''<br>normally, when using filtering (see below), the number of matching tiddlers is reported and you are asked to confirm before saving those tiddlers to a new file.  Use the ''quiet'' keyword to suppress this confirmation step.
*''replace''<br>overwrites existing output file, if any, without confirmation.
*''merge''<br>merges with existing output file, if any, without confirmation.
*''open''<br>opens the newly created document file in a separate browser tab/window.
*''filter''<br>selects a subset of tiddlers to be written into the new document.  If omitted, all tiddlers in the document are written to the new file.  ''filter'' can either:
**a tag value<br>selects only tiddlers that are tagged with that value.  To select tiddlers based on a combination of tags, you can install [[MatchTagsPlugin]] to construct complex 'tag expressions' using full 'boolean' logic with AND, OR, and NOT operators, as well as nested parentheses.
**''ask''<br>prompts you to enter a tag (or tag expression) whenever you click on the 'save as...' command
**''here''<br>selects the current tiddler (if any).  If the command is not embedded within a tiddler, you will be prompted to enter a tiddler title.
**''none''<br>omits all tiddlers and creates a new //empty// document
<<<
!!!!!Examples
<<<
save all tiddlers:
>{{{<<saveAs>>}}}<br>try it: <<saveAs>>
save only tiddlers matching a single tag:
>{{{<<saveAs "label:create Import/Export starter" "filename:TW+ImportExport.html" ImportExportPackage>>}}}
>try it: <<saveAs "label:create Import/Export starter" "filename:TW+ImportExport.html" "ImportExportPackage>>
save to a ~PureStore format:
>{{{<<saveAs "label:create Import/Export archive" "filename:ImportExportPackage.html" type:PureStore open ImportExportPackage>>}}}
>try it: <<saveAs "label:create Import/Export archive" "filename:ImportExportPackage.html" type:PureStore open ImportExportPackage>>
save to a ~PlainText format:
>{{{<<saveAs "label:create Import/Export source listing" type:PlainText open ImportExportPackage>>}}}
>try it: <<saveAs "label:create Import/Export source listing" type:PlainText open ImportExportPackage>>
save tiddlers matching a complex combination of tags (requires [[MatchTagsPlugin]]):
>{{{<<saveAs (alpha or settings) and not systemConfig>>}}}
>try it: <<saveAs (alpha or settings) and not systemConfig>>
prompt for tag or tag expression each time:
>{{{<<saveAs "label:custom save as..." ask>>}}}
>try it: <<saveAs "label:custom save as..." ask>>
save this tiddler:
>{{{<<saveAs "label:save this tiddler..." {{"filename:"+tiddler.title}} quiet here>>}}}
>try it: <<saveAs "label:save this tiddler..." {{"filename:"+tiddler.title}} quiet here>>
<<<
!!!!!Revisions
<<<
2009.10.13 2.7.0 added 'here' param (saves current tiddler)
2009.08.16 2.6.2 fixed handling for backstage
2009.08.04 2.6.1 fixed handling when limit is omitted.
2009.08.03 2.6.0 added 'limit:nn' parameter.
2009.08.02 2.5.3 in getData(), if type=RSS, sort by modified (most recent first).
2009.07.03 2.5.2 TW252 fixup: don't call convertUTF8ToUnicode() for local loadFile() I/O
2009.04.30 2.5.1 custom fields in CSV output.
2009.04.19 2.5.0 added CSV format.
2008.09.29 2.4.3 in getData(), convert UTF8 to Unicode before merging (fixes international characters).
2008.09.28 2.4.2 in go(), fixed typo that prevented backstage SaveAs from working.
2008.09.24 2.4.1 if rewriting *current* file and chkSaveBackups and/or chkGenerateAnRssFeed is enabled, then write a backup file or RSS feed, respectively
2008.09.24 2.4.0 when 'open' param is used and file is saved to current location, reload() page instead of opening a new tab/window.  Added 'filename' param to specify default filename.  Added 'replace' and 'merge' keyword params to control file handling without asking user.  Improved use of 'quiet' flag to eliminate more unwanted messages
2008.09.19 2.3.2 fixed backstage SaveAs command (was defaulting to empty document).  in formatItem(), removed unnecessary convertUnicodeToUTF8() (was causing double-conversion!)
2008.09.16 2.3.1 fixed IE 'navigate away' error by returning false from button onclick handler
2008.09.11 2.3.0 added support for alternative file formats: ~PlainText (TX), ~PureStore (PS), or ~NewsFeed (XML) in addition to existing ~TiddlyWiki (TW) document format
2008.09.06 2.2.1 corrected handling of autoopen attribute so it only applies when "open" param is specified
2008.08.01 2.2.0 added "open" param to auto-open newly saved document
2008.07.20 2.1.3 added "quiet" param to bypass confirmation when using tag filter
2008.04.22 2.1.2 corrected use of getTarget() to check for "user cancelled"
2008.04.22 2.1.1 documentation fixes
2008.04.22 2.1.0 added support for tag filtering to completely replace [[NewDocumentPlugin]] (now retired)
2008.04.12 2.0.1 automatically add "saveAs" to backstage commands
2008.04.12 2.0.0 initial release based on [[NewDocumentPlugin]]

__Previous revisions from [[NewDocumentPlugin]]__
2008.04.20 1.8.0 added support for 'noCSS' and 'viewer' params for alternative snapshot output
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.04 [*.*.*] update for ~TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.03.30 1.7.0 added support for "print" param as alternative for "snap".  When "print" is used, the filename is ignored and ouput is directed to another browser tab/window, where the print dialog is then automatically triggered
2007.03.30 1.6.1 added support for "here" keyword for current tiddler elementID and "prompt:text" param for specifying tooltip text
2007.02.12 1.6.0 in onClickNewDocument(), reset HTML source 'markup'
2006.10.23 1.5.1 in onClickNewDocument(), get saved parameter value for snapID instead of using default "contentWrapper" (oops!)
2006.10.18 1.5.0 new optional param for 'snap'... specify alternative DOM element ID (default is still "contentWrapper")
2006.08.03 1.4.3 in promptForFilename(), for IE (~WinXP only), added handling for ~UserAccounts.~CommonDialog
2006.07.29 1.4.2 in onClickNewDocument(), okmsg display is now linked to newly created file
2006.07.24 1.4.1 in promptForFilename(), check for nsIFilePicker.returnCancel to allow nsIFilePicker.returnOK **OR** nsIFilePicker.returnReplace to be processed
2006.05.23 1.4.0 due to very poor performance, support for tag *expressions* has been removed, in favor of a simpler "containsAny()" scan for tags
2006.04.09 1.3.6 in onClickNewDocument, added call to convertUnicodeToUTF8() to better handle international characters
2006.03.15 1.3.5 added nsIFilePicker() handler for selecting filename in moz-based browsers.  IE and other non-moz browsers still use simple prompt() dialog
2006.03.15 1.3.0 added "label:text" param for custom link text.  added special "all" filter parameter for "save as..." handling (writes all tiddlers to output file)
2006.03.09 1.2.0 added special "snap" filter parameter to generate and write "snapshot" files containing static HTML+CSS for currently rendered document
2006.02.24 1.1.2 Fix incompatiblity with TW 2.0.5 by removing custom definition of getLocalPath() (which is now part of TW core)
2006.02.03 1.1.1 concatentate 'extra' params so that tag expressions don't have to be quoted.   moved all text to 'formatted' string definitions for easier translation.
2006.02.03 1.1.0 added support for tag EXPRESSIONS.  plus improved documentation and code cleanup
2006.02.03 1.0.0 Created
<<<
/%
!info
|Name|SaveToClipboard|
|Source|http://www.TiddlyTools.com/#SaveToClipboard|
|Version|1.3.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion, bookmarklet|
|Description|save current document to clipboard|
|Browsers|FireFox, IE, Safari, Chrome, Opera (fallback)|
Usage
<<<
{{{
<<tiddler SaveToClipboard>>
<<tiddler SaveToClipboard with: label>>
}}}
Some browsers lack direct file I/O functions and/or do not currently support use of the [[tiddlysaver.jar|http://www.tiddlywiki.com/#TiddlySaver]] Java extension, preventing use of the normal <<saveChanges>> command to update the stored document.  As a workaround, the <<tiddler SaveToClipboard##show with: "save to clipboard">> command ''copies the source for the current document, including all tiddler changes, directly to the system clipboard'', so you can paste the clipboard contents into a new, empty file (using a text editor), save it to your local filesystem with an '.html' extension, and then open it in your browser to continue working locally.  

To construct the new file content, the previously saved file is first read in, and then merged with the current set of tiddlers (including all new/revised content).  If the saved file is not available (e.g., it was renamed/deleted after it was opened, or it is stored on a remote server that is not currently accessible), only the TiddlyWiki 'storeArea' is output to the clipboard (i.e., TiddlyWiki "~PureStore" format).  Tiddlers saved in PureStore-formatted files can be imported into an empty TiddlyWiki document using the ''backstage>import'' feature (or TiddlyTools' [[ImportTiddlersPlugin|http://www.TiddlyTools.com#ImportTiddlersPlugin]]).  You can [[obtain an empty TiddlyWiki document from http://www.TiddlyWiki.com|http://www.TiddlyWiki.com/empty.html]].

Note: some browsers do not permit program-controlled access to the system clipboard.  In this case, the clipboard output is instead ''displayed as plain text in a new browser tab/window'', so you can manually select and copy that text to the clipboard before pasting it to a new, empty file as described above.
<<<
Example
<<<
{{{<<tiddler SaveToClipboard with: "save to clipboard">>}}}
<<tiddler SaveToClipboard##show with: "save to clipboard">>
^^Note: drag this command link to your browser toolbar to create an [[InstantBookmarklet|InstantBookmarklets]]^^
<<<
<<tiddler SaveToClipboard##code with: {{store.getTiddlerText('SaveToClipboard##show')}}>>
!end
!code
Code
<<<
{{{
$1
}}}
<<<
!end
!show
<html><nowiki><a href="javascript:;" title="save current document to clipboard"
onmouseover="
	this.href='javascript:void(eval(decodeURIComponent(%22(function(){try{('
	+encodeURIComponent(encodeURIComponent(this.onclick))
	+')()}catch(e){alert(e.description?e.description:e.toString())}})()%22)))';"
onclick="
	if(typeof version==undefined||version.title!='TiddlyWiki')
		{alert(document.location.href+'\n\nis not a TiddlyWiki document');return false;}

	window.saveToClipboard=function(success,params,txt,url,xhr) {
		function copy(out) {
			if(window.Components) { // FIREFOX
				netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
				var id='@mozilla.org/widget/clipboardhelper;1';
				var clip=Components.classes[id].getService(Components.interfaces.nsIClipboardHelper);
				clip.copyString(out);
			} else if(window.clipboardData) { // IE
				window.clipboardData.setData('text',out);
			} else if(document.execCommand) { // CHROME, SAFARI, IE6
				var ta=document.createElement('textarea');
				ta.style.position='absolute';
				ta.style.left='-100%';
				document.body.appendChild(ta);
				ta.value=out; ta.select();
				document.execCommand('Copy',false,null);
				document.body.removeChild(ta);
			} else throw('cannot access clipboard');
		}
		var pos=locateStoreArea(txt||'');
		if(success&&pos) {
			displayMessage(txt.length+' bytes read, adding new/revised tiddlers...');
			var out=updateOriginal(txt,pos,url);
		} else {
			if (!confirm('cannot load source file.\ncopy tiddler \x22store area\x22 only?')) return;
			var pre='<!--POST-SHADOWAREA-->\n<div id=\x22storeArea\x22>\n';
			var post='</div>/n<!--POST-STOREAREA-->\n';
			var out=pre+store.allTiddlersAsHtml()+post;
		}
		var msg=out.length+' bytes copied to ';
		try	 { copy(out); msg+='clipboard'; }
		catch(e) { // FALLBACK
			alert('Sorry, direct clipboard access is not currently available.\n\n'
				+'The output will be displayed in another browser tab/window.\n'
				+'Select the entire text there and copy/paste into a local file');
			var t='<html><body><pre>'+out.htmlEncode()+'</pre></body></'+'html>';
			var w=window.open(); var d=w.document; d.open(); d.write(t); d.close();
			msg+='another tab/window';
		}
		displayMessage(msg);
	}
	var url=document.location.href;
	clearMessage(); displayMessage('loading TiddlyWiki code from'); displayMessage(url);
	if (document.location.protocol!='file:') loadRemoteFile(url, window.saveToClipboard);
	else window.saveToClipboard(true,null,loadOriginal(getLocalPath(url)),url,null);
 	return false;
">$1</a></html>
!end
%/<<tiddler {{var src='SaveToClipboard'; src+(tiddler&&tiddler.title==src?'##info':'##show')}}
	with: {{'$1'!='$'+'1'?'$1':'[+] - copy entire document to clipboard'}}>>
/***
|Name|SectionLinksPlugin|
|Source|http://www.TiddlyTools.com/#SectionLinksPlugin|
|Documentation|http://www.TiddlyTools.com/#SectionLinksPlugin|
|Version|1.3.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|allow tiddler sections in TiddlyLinks to be used as anchor points|
This plugin enhances the processing of section references so they can be used in links to auto-scroll to the indicated heading within a tiddler (i.e., similar to the 'anchor' behavior provided in HTML by {{{<a name="foo">}}} and {{{<a href="#foo">...</a>}}})
!!!Usage
<<<
!!!!!{{{<<tiddler>>}}} macro 
>The {{{<<tiddler SomeTiddler##SomeSection>>}}} syntax has been extended so that when the tiddler title is omitted or the 'here' keyword is used (e.g., {{{<<tiddler ##SomeSection>>}}} or {{{<<tiddler here##SomeSection>>}}}), then the current containing tiddler is implied by default.
!!!!!~TiddlyLink syntax
>the standard link syntax has been extended so that a section name can included in a tiddler link (e.g., {{{[[SomeTiddler##SomeSection]]}}}).  When clicked, the tiddler is displayed and the specified section heading will be automatically scrolled into view. If the tiddler title is omitted or the 'here' keyword is used (e.g., {{{[[##SomeSection]]}}} or {{{[[here##SomeSection]]>>}}}), then the current containing tiddler is implied by default.
!!!!!"""<<sectionTOC>>""" macro
>This macro generates a 'Table of Contents'-style numbered-bullet list with links to all sections within the current tiddler.  Simply place the following macro at the //end of the tiddler content// (i.e., following all section headings):
{{{
<<sectionTOC>> or <<sectionTOC className>>
}}}
>Note: The macro must occur at the end of the tiddler in order to locate the rendered section headings that precede it. In addition, to position the macro's //output// within the tiddler, you must create a special 'target element' that uses a specified classname (default='sectionTOC'), like this:
{{{
{{sectionTOC{}}}
}}}
>When the {{{<<sectionTOC>>}}} macro is rendered, it will find the matching 'sectionTOC'-classed element and writes it's output there.  You can also add the macro and/or target elements directly to the [[ViewTemplate]] definition, so that every tiddler can automatically display the table of contents:
{{{
<span class='sectionTOC'></span> <!-- target element -->
...
<span macro='sectionTOC'></span> <!-- must be at end of tiddler -->
}}}
<<<
!!!Revisions
<<<
2009.08.21 [1.3.4] added handling to ignore leading/trailing whitespace in section references
2009.08.21 [1.3.3] in createTiddlyLink(), add tiddlyLinkNonExistingSection class if matching section is not found
2009.08.14 [1.3.2] in createTiddlyLink(), don't override core value for ~TiddlyLink attribute
2009.08.02 [1.3.1] in sectionTOC.handler(), trim leading/trailing whitespace from generated section links
2009.08.01 [1.3.0] in scrollToSection(), apply 3-tier section matching (exact, startsWith, contains)
2009.07.06 [1.2.2] fixed displayTiddler() hijack
2009.07.03 [1.2.1] in {{{<<sectionTOC>>}}}, suppress output if target is not found
2009.06.02 [1.2.0] added support for 'here' keyword in {{{[[here##section]]}}} links and {{{<<tiddler here##section>>}}} macro
2009.04.09 [1.1.1] in sectionTOC macro, make target visible when TOC is rendered.
2009.01.18 [1.1.0] added {{{<<sectionTOC>>}}} macro to generate numbered-bullet links to sections of current tiddler
2009.01.06 [1.0.0] converted to stand-alone plugin
2008.10.14 [0.0.0] initial release (as [[CoreTweaks]] #784 - http://trac.tiddlywiki.org/ticket/784)
<<<
!!!Code
***/
//{{{
version.extensions.SectionLinksPlugin= {major: 1, minor: 3, revision: 4, date: new Date(2009,8,21)};

Story.prototype.scrollToSection = function(title,section) {
	if (!title||!section) return; var t=this.getTiddler(title); if (!t) return null;
	var elems=t.getElementsByTagName('*'); var heads=[];
	for (var i=0; i<elems.length; i++)
		if (['H1','H2','H3','H4','H5'].contains(elems[i].nodeName)) heads.push(elems[i]);
	for (var i=0; i<heads.length; i++)
		if (getPlainText(heads[i]).trim()==section) break;
	if (i==heads.length) for (var i=0; i<heads.length; i++)
		if (getPlainText(heads[i]).trim().startsWith(section)) break;
	if (i==heads.length) for (var i=0; i<heads.length; i++)
		if (getPlainText(heads[i]).trim().indexOf(section)!=-1) break;
	if (i<heads.length) { var h=heads[i];
		// if section heading is collapsed, click to expand it - see [[FoldHeadingsPlugin]]
		if (hasClass(h,'foldable') && h.nextSibling.style.display=='none') h.onclick();
		// scroll *after* tiddler animation
		var delay=config.options.chkAnimate?config.animDuration+100:0;
		setTimeout('window.scrollTo('+findPosX(h)+','+findPosY(h)+')',delay);
		return h;
	}
}
//}}}
/***
!!!!core hijacks
***/
/***
!!!!!createTiddlyLink
***/
//{{{
// [[tiddlername##section]] and [[##section]]
if (!window.createTiddlyLink_section)
	window.createTiddlyLink_section=window.createTiddlyLink;
window.createTiddlyLink=function(place,title) {
	var t=story.findContainingTiddler(place); var tid=t?t.getAttribute('tiddler'):'';
	var parts=title.split(config.textPrimitives.sectionSeparator);
	var title=parts[0]; var section=parts[1]; if (section) section=section.trim();
	if (!title.length || title.toLowerCase()=='here') title=tid;  // default=current tiddler
	arguments[1]=title;
	var btn=createTiddlyLink_section.apply(this,arguments);
	if (section) {
		btn.setAttribute('section',section);
		if (store.getTiddlerText(title+config.textPrimitives.sectionSeparator+section)===null)
			addClass(btn,'tiddlyLinkNonExistingSection');
	}
	return btn;
}
//}}}
/***
!!!!!onClickTiddlerLink
***/
//{{{
if (!window.onClickTiddlerLink_section)
	window.onClickTiddlerLink_section=window.onClickTiddlerLink;
window.onClickTiddlerLink=function(ev) {
	var e=ev||window.event;	var target=resolveTarget(e); var title=null;
	while (target!=null && title==null) {
		title=target.getAttribute('tiddlyLink');
		section=target.getAttribute('section');
		target=target.parentNode;
	} 
	var t=story.findContainingTiddler(target); var tid=t?t.getAttribute('tiddler'):'';
	if (title!=tid||!section) // avoid excess scrolling for intra-tiddler links
		onClickTiddlerLink_section.apply(this,arguments);
	story.scrollToSection(title,section);
	return false;
}
//}}}
/***
!!!!! displayTiddler
***/
//{{{
if (!Story.prototype.displayTiddler_section)
	Story.prototype.displayTiddler_section=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler)
{
	var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
	var parts=title.split(config.textPrimitives.sectionSeparator);
	var title=parts[0]; var section=parts[1]; if (section) section=section.trim();
	if (!title.length || title.toLowerCase()=='here') {
		var t=story.findContainingTiddler(place);
		title=t?t.getAttribute('tiddler'):'';
	}
	arguments[1]=title;  // default=current tiddler
	this.displayTiddler_section.apply(this,arguments);
	story.scrollToSection(title,section);
}
//}}}
/***
!!!!!isExternalLink
***/
//{{{
if (!config.formatterHelpers.isExternalLink_section)
	config.formatterHelpers.isExternalLink_section=config.formatterHelpers.isExternalLink;
config.formatterHelpers.isExternalLink=function(link) {
	if (link.indexOf(config.textPrimitives.sectionSeparator)!=-1) return false;
	return config.formatterHelpers.isExternalLink_section.apply(this,arguments);
}
//}}}
/***
!!!!!tiddler.handler
***/
//{{{
if (!config.macros.tiddler.handler_section)
	config.macros.tiddler.handler_section=config.macros.tiddler.handler;
config.macros.tiddler.handler=function(place,macroName,params,wikifier,paramString,tiddler)
{
	if (!params[0]) return;
	var sep=config.textPrimitives.sectionSeparator;
	var parts=params[0].split(sep); var tid=parts[0]; var sec=parts[1]; if (sec) sec=sec.trim();
	if ((tid.toLowerCase()=='here'||!tid.length) && sec) { // fixup for 'here##section' and '##section'
		var here=story.findContainingTiddler(place)
		var tid=here?here.getAttribute('tiddler'):tiddler?tiddler.title:'';
		arguments[2][0]=tid+sep+sec;
		arguments[4]=paramString.replace(new RegExp('(here)?'+sep+sec),tid+sep+sec);
	}
	config.macros.tiddler.handler_section.apply(this,arguments);
}
//}}}
/***
!!!!sectionTOC macro
***/
//{{{
config.macros.sectionTOC = {
	targetClass: 'sectionTOC',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var out=[];
		var targetClass=params[0]||this.targetClass;
		var t=story.findContainingTiddler(place); if (!t) return;
		var elems=t.getElementsByTagName('*');
		var level=5; // topmost heading level
		for (var i=0; i<elems.length; i++) {
			var txt=getPlainText(elems[i]).trim();
			var link='[['+txt+'|##'+txt+']]';
			switch(elems[i].nodeName) {
				case 'H1': out.push('#'+link);		level=1; break;
				case 'H2': out.push('##'+link);		level=level<2?level:2; break;
				case 'H3': out.push('###'+link);	level=level<3?level:3; break;
				case 'H4': out.push('####'+link);	level=level<4?level:4; break;
				case 'H5': out.push('#####'+link);	level=level<5?level:5; break;
				default: if (hasClass(elems[i],targetClass)) var target=elems[i];
			}
		}
		// trim excess bullet levels
		if (level>1) for (var i=0; i<out.length; i++) out[i]=out[i].substr(level-1);
		// show numbered list
		if (out.length && target) {
			if (target.style.display=='none') target.style.display='block';
			wikify(out.join('\n'),target);
		}
	}
}
//}}}
/***
!!!Invoke macro
{{{
<<sectionTOC>>
}}}
***/
// //<<sectionTOC>>
/***
! Notify the user that this is a partial coursebook and tell them how to get the full coursebook

If they find this and say 'magic words', they may get a full course book anyway as part of an e a s t e r   e g g   h u n t.
***/
//{{{
config.views.wikified.defaultText="The tiddler '%0' is not included in this coursebook sample. To receive the full coursebook, you can sign up for the S2 tutorial on Sunday November 1 at LISA 2009: http://www.usenix.org/events/lisa09/registration/"; 
config.messages.undefinedTiddlerToolTip="Click to get information on getting the missing '%0' tiddler";
//}}}

/***
! Have the tiddler macro insert a shameless plug
***/
//{{{
// if local style changes aren't present in the tiddler macro, then we are not in the instructor book
// so we want to swap in the new code.

var newcode = 'if (params[0] && tiddler && !(store.getTiddlerText(params[0]) || store.isShadowTiddler(params[0]))) return  wikify("@@font-weight: bold;color: red;***The content of tiddler [["+params[0].replace(new RegExp("/[^/]+$"), "")+"]] is not available. Click the link to find out why.***@@",place);';

var code=config.macros.tiddler.handler.toString();
if ( code.indexOf('"@@' == -1) ) {
var pos=code.indexOf('{');
code = code.substr(0,pos+1)+newcode+code.substr(pos+1);
eval('config.macros.tiddler.handler='+code);
}
//}}}
/%
!info
|Name|ShowImage|
|Source|http://www.TiddlyTools.com/#ShowImage|
|Version|1.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|display attached tiddler image without supporting plugin|
Usage:
<<<
# First, use [[AttachFilePlugin]] to create tiddlers containing base64-encoded image data with a fallback remote URL reference.
# You can then discard the plugin and associated supporting tiddlers ([[AttachFileMIMETypes]], [[AttachFilePluginFormatters]]), leaving only the attachment tiddlers (plus this tiddler, ShowImage, of course).
# Use the following syntax to display the attached images without any plugins:
{{{
<<tiddler ShowImage with: [[TiddlerName]] "tooltip" "width">>
}}}
where:
*''~TiddlerName''<br>title of the attachment tiddler to be displayed
*''tooltip'' //(optional)//<br>mouseover help text for the image (default=attachment title)
*''width'' //(optional)//<br>CSS width measurement - resizes image height proportionally (default=auto)
Note: the fallback remote URL will be used if encoded data is not attached or you are using InternetExplorer, which does not currently support the data:// URI. 
<<<
Example:
<<<
{{{
<<tiddler ShowImage with: [[AttachFileSample]] "meow!" "30px">>
}}}
<<tiddler ShowImage with: [[AttachFileSample]] "meow!" "30px">>
<<<
!end

!show
<html><img src="missing.jpg" title="$2" style="width:$3" /></html><<tiddler {{
	var src=store.getTiddlerText("$1##data");
	if (!src||config.browser.isIE)
		src=store.getTiddlerText("$1##url","missing.jpg");
	place.lastChild.firstChild.src=src;
}}>>
!end

%/<<tiddler {{"ShowImage##"+("$1"=="$"+"1"?"info":"show")}} with:
	[[$1]]
	{{"$2"=="$"+"2"?"$1"  :"$2"}}
	{{"$3"=="$"+"3"?"auto":"$3"}}
>>
/%
!info
|Name|ShowPopup|
|Source|http://www.TiddlyTools.com/#ShowPopup|
|Version|1.2.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transcluded html|
|Requires||
|Overrides||
|Description|display tiddler content in a TiddlyWiki popup panel|
Usage:
<<<
{{{
<<tiddler ShowPopup with: TiddlerName label tooltip buttonClass width popupClass>>
}}}
where:
*''~TiddlerName''<br>title of the tiddler to be displayed
*''label''<br>text for the command link
*''tooltip''<br>mouseover help text for the link
*''buttonClass''<br>CSS classname applied to the command text (default=button)
*''width''<br>width of the popup (using CSS measurements, default=auto)
*''popupClass''<br>CSS classname applied to the popup panel (default=none).<br>Use 'sticky' for persistent popups (see StickyPopupPlugin)
<<<
Example:
<<<
{{{
<<tiddler ShowPopup with: ShowPopup [[Try this]] [[show this tiddler in a popup]]>>
}}}
<<tiddler ShowPopup with: ShowPopup [[Try this]] [[show this tiddler in a popup]]>>
<<<
!end

!show
<html><hide linebreaks>
<a href="javascript:;" class="$4" title="$3" onclick="
	var p=Popup.create(this); if(!p)return;
	p.className+='$6'!='$'+'6'?' $6':'';
	var d=createTiddlyElement(p,'div');
	var s=d.style;
	s.whiteSpace='normal';
	s.width='$5'!='$'+'5'?'$5':'auto';
	s.padding='2px';
	wikify(store.getTiddlerText('$1',''),d);
	Popup.show();
	event.cancelBubble=true;
	if(event.stopPropagation)event.stopPropagation();
	return(false);
">$2</a></html>
!end

%/<<tiddler {{'ShowPopup##'+('$1'=='$'+'1'?'info':'show')}} with: [[$1]] [[$2]] [[$3]] [[$4]] [[$5]] [[$6]]>>
{{button{goto}}}
<<gotoTiddler>><<search>><<closeAll>><<permaview>><<newTiddler prompt:"Create a new tiddler.">><<tiddler InstructorSidebarFunctions##newTiddlers>><<unsavedChanges command>><<saveChanges>><<slider chkInstructorSidebarFunctions InstructorSidebarFunctions "instructor »" "save contents from instructor tw">><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
<<tiddler InstructorSiteStartup>> Place things here that should be invoked once upon loading of the TiddlyWiki
E.G. aliases defined by the AliasPlugin, or redirects or redirectExact's defined using the RedirectMacro.
{{{
<<alias ul "<script>place.style.borderLeft='thin solid black';</script>">>
<<redirectExact Single [[Rule Type Reference##Single]]>>
}}}

/% make all occurences of the term WikiWords ro WikiWord link to the glossary entry %/
<<redirectExact WikiWords [[Glossary/wikiWord]]>>
<<redirectExact WikiWord [[Glossary/wikiWord]]>>

<<alias img {{"\<\<wikify '[img(" +  store.getTiddlerSlice('Slide Tips','defaultPercent') + ", auto)[%0]]' >\>"}} >>
a textbook, notebook, quiz and presentation tool for a class
TiddlyWiki Coursebook
http://www.cs.umb.edu/~rouilj/classes/SEC_LISA09/SEC_ps.html
!! Test the display at your projection resolution

Remember to test slide display in the resolution you will be displaying at so that the slide displays without scrolling in the  instrucor presentation mode. The students can scroll the slides, but you shouldn't scroll on screen.

The
{{{
#displayArea {
 font-size: 180%;
}
}}}
setting in the InstructorSlideShowStyleSheet can be used to adjust for different resolutions. When you use images, consider how they will scale at different resolutions. An image can be scaled using {{{[img(90%,)[image_file.png]]}}} to scale it at 90% of the size of it's containg element. See the ImageSizePlugin for other examples.
<<<
[img(24px,)[tick-icon.png]] You can also use tiddler transclusion to set the percentage in one location and reference it everywhere. For example you can use a [[slice|Glossary/slice]] in a tiddler to set the size:
defaultPercent: 63%
Then you can reference it with: {{{<<wikify '[img(%0, auto)[%1]]' 'Slide Tips::defaultPercent' tick-icon.png>>}}} to get a really big (and ugly):
<<wikify '[img(%0, auto)[%1]]' 'Slide Tips::defaultPercent' tick-icon.png>>
at <<tiddler "Slide Tips::defaultPercent">> of the width of the story column.
<<<

This is encapsulated in the {{{<<img imagename.ext>>}}} that is defined in SiteStartup. Note if you change the defaultPercent display the SiteStartup tiddler to refresh the value. For example {{{<<img warning-icon.png>>}}} creates:
<<img warning-icon.png>>
using the embedded image [[warning-icon.png]]. You can also specify a local file or a url to an image.

!! Reusing content via [[transclusion|Glossary/transcluded]]

You can use the {{{<<tiddler>>}}} macro to include content from other tiddlers. Especially useful with the PartTiddlerPlugin to include examples from a section of a larger tiddler into a slide so you don't have to duplicate content.

!! Duplicating a slide in a single presentation

Sometimes you want to reuse a slide in a presentation. E.G. A slide that lays out important bullet points that you want to use to:
* tell them what you will tell them
* tell them what you told them
The underlying mechanisms for stories and presentations don't display the same tiddler twice
even if named. However there is a way around this. Create two tiddlers:
* Agenda
* Agenda - Recap
in the {{{Agenda - Recap}}} tiddler use {{{<<tiddler "Agenda">>}}} to [[transclude|Glossary/transcluded]] the contents from the Agenda tiddler into the Agenda - Recap tiddler. Any changes that occur to the Agenda tiddler will be displayed in the Agenda - Recap tiddler.
<<tiddler Welcome/coursebook>>
/***
|''Name:''|SlideShowPlugin|
|''Description:''|Creates a slide show from any number of tiddlers|
|''Author:''|Paulo Soares|
|''Contributors:''|John P. Rouillard|
|''Version:''|2.2.4|
|''Date:''|2010-04-08|
|''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|
|''Documentation:''|[[SlideShowPlugin Documentation|SlideShowPluginDoc]]|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.5.0|
***/
//{{{
if(!version.extensions.SlideShowPlugin) { //# ensure that the plugin is only installed once
version.extensions.SlideShowPlugin = {installed: true};

(function($) {
config.macros.slideShow = {maxTOCLength: 30, separator:'-s-'};

config.formatters.push( {
	name: "SlideSeparator",
	match: "^-s-+$\\n?",
	handler: function(w) {
		createTiddlyElement(w.output,"hr",null,'slideSeparator');
	}
});

config.macros.slideShow.text = {
  label: "slide show", tooltip: "Start slide show",
  quit: {label: "x", tooltip: "Quit the slide show"},
  firstSlide: {label: "<<", tooltip: "Go to first slide"},
  previous: {label: "<", tooltip: "Go back"},
  next: {label: ">", tooltip: "Advance"},
  lastSlide: {label: ">>", tooltip: "Go to last slide"},
  goto: {label: "Go to slide:"},
  resetClock: {tooltip: "Reset the clock"},
  overlay: "overlay"
};

config.macros.slideShow.handler = function(place,macroName,params,wikifier,paramString){
  var args = paramString.parseParams(null,null,false);
  this.label = getParam(args,"label",this.text.label);
  this.tooltip = getParam(args,"tooltip",this.text.tooltip);
  var onclick = function(){config.macros.slideShow.onClick(place,paramString); return false;};
  createTiddlyButton(place,this.label,this.tooltip,onclick);
  return false;
}

config.macros.slideShow.onClick = function(place,paramString) {
  var slide, cm = config.macros.slideShow;
  var title = story.findContainingTiddler(place);
  title = title ? title.getAttribute("tiddler") : null;
  var args = paramString.parseParams(null,null,false);
  title =  getParam(args,"tiddler",title);
  var argsArray = paramString.readMacroParams();
  this.single = ($.inArray('single',argsArray) > -1);
  this.clicks = ($.inArray('noClicks',argsArray) < 0);
  this.keyboard = ($.inArray('noKeyboard',argsArray) < 0);
  this.showAll = ($.inArray('showAll',argsArray) > -1);
  this.cycle = ($.inArray('cycle',argsArray) > -1);
  this.overlays = ($.inArray('noOverlays',argsArray) < 0);
  this.theme = getParam(args,"theme");
  this.tag = getParam(args,"tag");
  this.toc = getParam(args,"toc","headers");
  this.sort = getParam(args,"sort");
  this.clockFormat = getParam(args,"clockFormat",'0hh:0mm:0ss');
  this.auto = getParam(args,"auto",0);
  this.header = getParam(args,"header",title);
  this.footer = getParam(args,"footer","");
  this.clock = getParam(args,"clock");
  this.blocked = 0;
  if(this.clock){
    var startTime = new Date(0);
    this.clockCorrection=startTime.getTimezoneOffset()*60000;
    startTime = new Date();
    this.clockMultiplier = 1;
    this.clockInterval = 0;
    var clockType= parseFloat(this.clock);
    if(clockType < 0) {
      this.clockMultiplier = -1;
      this.clockInterval = -clockType*60000;
    } else if(clockType == 0){
      this.clockCorrection = 0;
      startTime = new Date(0);
    }
    this.clockStartTime=startTime.getTime();
  }
  this.slides = [];
  this.openTiddlers = [];
  $("#tiddlerDisplay > *").each(function(){cm.openTiddlers.push($(this).attr('tiddler'))});
  var count = 0;
  this.slideTOC=[];
  if(this.single){
    var newTiddler;
    var content = store.getTiddlerText(title).split(cm.separator);
    $.each(content, function(){
      count++;
      newTiddler = new Tiddler();
      newTiddler.title ="TempSlide" + count;
      newTiddler.tags[0] = "excludeLists";
      newTiddler.tags[1] = "temporarySlides";
      newTiddler.text = $.trim(this);
      store.addTiddler(newTiddler);
      cm.buildTOC(count,newTiddler.title);
      cm.slides.push(newTiddler.title);
    });
  } else {
    if(this.tag){
      var content = store.getTaggedTiddlers(this.tag,this.sort);
      $.each(content, function(){
        count++;
        cm.buildTOC(count,this.title);
        cm.slides.push(this.title);
      });
    } else {
      story.displayTiddler(null,title);
      var list = $('[tiddler='+title+']').children('.viewer').find('.tiddlyLinkExisting');
      $.each(list,function(){
        if(!$(this).parents().hasClass("exclude")){
          slide = $(this).attr('tiddlylink');
          count++;
          cm.buildTOC(count,slide);
          cm.slides.push(slide);
        }
      });
    }
  }
  this.nSlides = this.slides.length;
  if(this.nSlides==0) return false;
  clearMessage();
  this.toggleSlideStyles();
  if(!this.showAll){
    //Attach the key and mouse listeners
    if(this.keyboard && !$("#tiddlerDisplay").hasClass("noKeyboard")) $(document).keyup(cm.keys);
    if(this.clicks){
      $("#displayArea").mouseup(cm.clicker);
      document.oncontextmenu = function(){return false;}
    }
    if(this.clock) this.slideClock=setInterval(this.setClock, 1000);
    if(this.auto>0){
      this.autoAdvance=setInterval(cm.next, this.auto*1000);
    }
    this.showSlide(1);
  } else {
    story.closeAllTiddlers();
    story.displayTiddlers(null,this.slides);
    $(".tiddler").attr("ondblclick",null);
    $(document).keyup(cm.endSlideShow);
  }
  return false;
}

config.macros.slideShow.buildNavigator = function() {
  //Create the navigation bar
  var i, slidefooter = $("#controlBar")[0];
  if(!slidefooter) return;
  $(slidefooter).addClass("slideFooterOff noClicks");
  var navigator = createTiddlyElement(slidefooter,"SPAN","navigator");
  var buttonBar = createTiddlyElement(navigator,"SPAN","buttonBar");
  //Make it so that when the footer is hovered over the class will change to make it visible
  $(slidefooter).bind("mouseenter mouseleave", function(e){$(this).toggleClass("slideFooterOff");});
  //Create the control buttons for the navigation
 
  createTiddlyButton(buttonBar,this.text.firstSlide.label,this.text.firstSlide.tooltip,this.firstSlide,"button");
  createTiddlyButton(buttonBar,this.text.previous.label,this.text.previous.tooltip,this.previous,"button");
  createTiddlyButton(buttonBar,this.text.quit.label,this.text.quit.tooltip,this.endSlideShow,"button");
  createTiddlyButton(buttonBar,this.text.next.label,this.text.next.tooltip,this.next,"button");
  createTiddlyButton(buttonBar,this.text.lastSlide.label,this.text.lastSlide.tooltip,this.lastSlide,"button");
  if(this.clock){
    if(this.clock == 0){
       createTiddlyElement(navigator,"SPAN","slideClock");
    } else {
      createTiddlyButton(navigator," ",this.text.resetClock.tooltip,this.resetClock,"button","slideClock");
    }
    this.setClock();
  }
  var index = createTiddlyElement(slidefooter,"SPAN","slideCounter");
  index.onclick = this.toggleTOC;
  var toc = createTiddlyElement(slidefooter,"SPAN","toc");
  var tocLine;
  for(i=0; i<this.slideTOC.length; i++){
    $(toc).append(this.slideTOC[i][2]);
    tocLine = toc.lastChild;
    $(tocLine).addClass("tocLevel"+this.slideTOC[i][1]).css("cursor", "pointer").hover(function () {
        $(this).addClass("highlight");}, function () {
        $(this).removeClass("highlight");});
    tocLine.setAttribute("slide",this.slideTOC[i][0]);
    $(tocLine).click(config.macros.slideShow.showSlideFromTOC);
  }
  //Input box to jump to specific slide
  var tocItem = createTiddlyElement(toc,"DIV","jumpItem",null,this.text.goto.label);
  var tocJumpInput = createTiddlyElement(tocItem,"INPUT","jumpInput");
  tocJumpInput.type="text";
  $(tocJumpInput).keyup(config.macros.slideShow.jumpToSlide);
}

//Used to shorten the TOC fields
config.macros.slideShow.abbreviate = function(label){
  if(label.length>this.maxTOCLength) {
    var temp = new Array();
    temp = label.split(' ');
    label = temp[0];
    for(var j=1; j<temp.length; j++){
      if((label.length+temp[j].length)<=this.maxTOCLength){
        label += " " + temp[j];
      } else {
        label += " ...";
        break;
      }
    }
  }
  return label;
}

config.macros.slideShow.buildTOC = function(count,title) {
  var level = 1, text;
  switch(this.toc){
  case "headers":
    var frag = wikifyStatic(store.getTiddlerText(title));
    text = frag.replace(/<div class="comment">.*<\/div>/mg,"");
    var matches =  text.match(/<h[123456]>.*?<\/h[123456]>/mgi);
    if(matches){
      for (var j=0; j<matches.length; j++){
        level = matches[j].charAt(2);
        text = matches[j].replace(/<\/?h[123456]>/gi,"");
        text = this.abbreviate(text);
        this.slideTOC.push([count,level,"<div>"+text+"</div>"]);
      }
    }
    break;
  case "titles":
    text = this.abbreviate(title);
    this.slideTOC.push([count,level,"<div>"+text+"</div>"]);
  }
}

config.macros.slideShow.showSlideFromTOC = function(e) {
  var cm = config.macros.slideShow;
  var slide = parseInt(e.target.getAttribute('slide'));
  $("#toc").hide();
  cm.showSlide(slide);
  return false;
}

config.macros.slideShow.toggleTOC = function(){
  $("#toc").toggle();
  $("#jumpInput").focus().val('');
  return false;
}

config.macros.slideShow.isInteger = function(s){
  for (var i = 0; i < s.length; i++){
    // Check that current character is number
    var c = s.charAt(i);
    if (((c < "0") || (c > "9"))) return false;
  }
  // All characters are numbers
  return true;
}

config.macros.slideShow.jumpToSlide = function(e){
  var cm = config.macros.slideShow;
  if(e.which==13){
    var input= $("#jumpInput").val();
    if(cm.isInteger(input) && input>0 && input<=cm.nSlides){
      $("#toc").hide();
      cm.showSlide(input);
    } else  {$("#jumpInput").val('');}
  }
  return false;
}

config.macros.slideShow.toggleSlideStyles = function(){
  var contentWrapper = $('#contentWrapper');
  if(contentWrapper.hasClass("slideShowMode")){
    refreshPageTemplate();
    removeStyleSheet("SlideShowStyleSheet");
    if(this.theme) removeStyleSheet(this.theme);
    removeStyleSheet("SlideShowDynamicStyle"); // rouilj for changable slide formats at runtime
    setStylesheet(store.getRecursiveTiddlerText("StyleSheet"),"StyleSheet");
  } else {
    $("#displayArea").prepend('<div id="slideBlanker" style="display:none"></div><div id="slideHeader">'+this.header+'</div><div id="slideFooter">'+this.footer+'</div><div id="controlBar"></div>');
    setStylesheet(store.getRecursiveTiddlerText("SlideShowStyleSheet"),"SlideShowStyleSheet");
    if(this.theme && store.tiddlerExists(this.theme)){setStylesheet(store.getRecursiveTiddlerText(this.theme),this.theme);}
    setStylesheet("","SlideShowDynamicStyle"); // rouilj for changable slide formats at runtime
    this.buildNavigator();
  }
  contentWrapper.toggleClass("slideShowMode");
  if (this.theme) { contentWrapper.toggleClass(this.theme) } else {  contentWrapper.toggleClass("SlideShowStyleSheet")}; // rouilj
   // for dynamic slide changes, allow the dynamic code to figure out what style sheet we are using to act differently in different modes.
  return false;
}

config.macros.slideShow.showSlide = function(n){
  if(this.cycle) {
    if(n>this.nSlides) {
      n = 1;
    } else if(n<1) {
      n = this.nSlides;
    }
  } else {
    if(n>this.nSlides || n<1) return;
  }
  story.closeAllTiddlers();
  if(this.clock=='-'){this.resetClock();}
  story.displayTiddler(null,String(this.slides[n-1]));
  $(".tiddler").attr("ondblclick",null);
  this.curSlide = n;
  $("#slideCounter").text(this.curSlide+"/"+this.nSlides);
  if(this.overlays){
    var contents = $(".viewer *");
    this.numOverlays = 1;
    while(1){
      if(contents.hasClass(this.text.overlay+this.numOverlays)){
        this.numOverlays++;
      } else {break;}
    }
    this.numOverlays--;
    this.showOverlay(0);
  }
  return false;
}

config.macros.slideShow.showOverlay = function(n){
  var i, set, cm = config.macros.slideShow;
  if(!cm.overlays || cm.numOverlays == 0 || n<0 || n>cm.numOverlays){return;}
  for(i=1; i<n; i++){
    set = $(".viewer "+"."+cm.text.overlay+i);
    set.removeClass("currentOverlay nextOverlay");
    set.addClass("previousOverlay");
  }
  set = $(".viewer "+"."+cm.text.overlay+n);
  set.removeClass("previousOverlay nextOverlay");
  set.addClass("currentOverlay");
  for(i=n; i<config.macros.slideShow.numOverlays; i++){
    set = $(".viewer "+"."+cm.text.overlay+(i+1));
    set.removeClass("previousOverlay currentOverlay");
    set.addClass("nextOverlay");
  }
  cm.curOverlay = n;
}

config.macros.slideShow.firstSlide = function(){
  config.macros.slideShow.showSlide(1);
  return false;
}

config.macros.slideShow.lastSlide = function(){
  config.macros.slideShow.showSlide(config.macros.slideShow.nSlides);
  return false;
}

config.macros.slideShow.next = function(){
  var cm = config.macros.slideShow;
  if(!cm.overlays || cm.numOverlays == 0 || cm.curOverlay == cm.numOverlays) {
    cm.showSlide(cm.curSlide+1);
  } else {
    cm.showOverlay(cm.curOverlay+1);
  }
  return false;
}

config.macros.slideShow.previous = function(){
  var cm = config.macros.slideShow;
  if(!cm.overlays || cm.numOverlays == 0 || cm.curOverlay == 0) {
    cm.showSlide(cm.curSlide-1);
    cm.showOverlay(cm.numOverlays);
  } else {
    cm.showOverlay(cm.curOverlay-1);
  }
  return false;
}

config.macros.slideShow.endSlideShow=function(){
  var cm = config.macros.slideShow;
  if(cm.autoAdvance) {clearInterval(cm.autoAdvance);}
  if(this.clock) clearInterval(this.slideClock);
  story.closeAllTiddlers();
  cm.toggleSlideStyles();
  story.displayTiddlers(null,cm.openTiddlers);
  $(document).unbind();
  document.oncontextmenu =  function(){};
  var content = store.getTaggedTiddlers('temporarySlides');
  $.each(content, function(){
    store.removeTiddler(this.title);
  });
  return false;
}

// 'keys' code adapted from S5 which in turn was adapted from MozPoint (http://mozpoint.mozdev.org/)
config.macros.slideShow.keys = function(key) {
  var cm = config.macros.slideShow;
  switch(key.which) {
  case 32: // spacebar
    if(cm.auto>0 && cm.blocked==0){
      if(cm.autoAdvance){
        clearInterval(cm.autoAdvance);
        cm.autoAdvance = null;
      } else {
        cm.autoAdvance=setInterval(cm.next, cm.auto*1000);
      }
    } else {
      if(cm.blocked==0) cm.next();
    }
    break;
  case 34: // page down
    if(cm.blocked==0) cm.showSlide(cm.curSlide+1);
    break;
  case 39: // rightkey
    if(cm.blocked==0) cm.next();
    break;
  case 40: // downkey
    if(cm.blocked==0) cm.showOverlay(cm.numOverlays);
    break;
  case 33: // page up
    if(cm.blocked==0) cm.showSlide(cm.curSlide-1);
    break;
  case 37: // leftkey
    if(cm.blocked==0) cm.previous();
    break;
  case 38: // upkey
    if(cm.blocked==0) cm.showOverlay(0);
    break;
  case 36: // home
    if(cm.blocked==0) cm.firstSlide();
    break;
  case 35: // end
    if(cm.blocked==0) cm.lastSlide();
    break;
  case 27: // escape
    cm.endSlideShow();
    break;
  case 66: // B
    $("#slideBlanker").toggle();
    cm.blocked = (cm.blocked +1)%2;
    break;
  }
  return false;
}

config.macros.slideShow.clicker = function(e) {
  var cm = config.macros.slideShow;
  if(cm.blocked==1 || $(e.target).attr('href') || $(e.target).parents().andSelf().hasClass('noClicks')){
    return true;
  }
  if($("#toc").is(':visible')){
    cm.toggleTOC();
  } else {
    if((!e.which && e.button == 1) || e.which == 1) {
      cm.next();
    }
    if((!e.which && e.button == 2) || e.which == 3) {
      cm.previous();
    }
  }
  return false;
}

config.macros.slideShow.setClock = function(){
  var cm = config.macros.slideShow;
  var actualTime = new Date();
  var newTime = actualTime.getTime() - cm.clockStartTime;
  newTime = cm.clockMultiplier*newTime+cm.clockInterval+cm.clockCorrection;
  actualTime.setTime(newTime);
  newTime = actualTime.formatString(cm.clockFormat);
  $("#slideClock").text(newTime);
  return false;
}

config.macros.slideShow.resetClock = function(){
  var cm = config.macros.slideShow;
  if(cm.clock == 0) return;
  var time = new Date(0);
  if(cm.clockStartTime>time){
    var startTime = new Date();
    cm.clockStartTime=startTime.getTime();
  }
  return false;
}

config.shadowTiddlers.SlideShowStyleSheet="/*{{{*/\n.header, #mainMenu, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{\n display:none !important\n}\n\n#slideBlanker{\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 90; \n background-color: #000;\n opacity: 0.9;\n filter: alpha(opacity=90)\n}\n\n.nextOverlay{\n visibility: hidden\n}\n\n.previousOverlay,.currentOverlay{\n visibility: visible\n}\n\n#displayArea{\n font-size: 250%;\n margin: 0 !important;\n padding: 0\n}\n\n#controlBar{\n position: fixed;\n bottom: 2px;\n right: 2px;\n width: 100%;\n text-align: right\n}\n\n#controlBar .button{\n margin: 0 0.25em;\n padding: 0 0.25em\n}\n\n#slideHeader{\n font-size: 200%;\n font-weight: bold\n}\n\n#slideFooter{\n position: fixed;\n bottom: 2px\n}\n\n.slideFooterOff #navigator{\n visibility: hidden\n}\n\n#slideClock{\n margin: 0 5px 0 5px\n}\n\n#slideCounter{\n cursor: pointer;\n color: #aaa\n}\n\n#toc{\n display: none;\n position: absolute;\n font-size: .75em;\n bottom: 2em;\n right: 0;\n background: #fff;\n border: 1px solid #000;\n text-align: left\n}\n\n#jumpItem{\n padding-left:0.25em\n}\n\n#jumpInput{\n margin-left: 0.25em;\n width: 3em\n}\n\n.tocLevel1{\n font-size: .8em\n}\n\n.tocLevel2{\n margin-left: 1em;\n font-size: .75em\n}\n\n.tocLevel3{\n margin-left: 2em;\n font-size: .7em\n}\n\n.tocLevel4{\n margin-left: 3em;\n font-size: .65em\n}\n\n.tocLevel5{\n margin-left: 4em;\n font-size: .6em\n}\n\n.tocLevel6{\n margin-left: 5em;\n font-size: .55em\n}\n/*}}}*/";

config.shadowTiddlers.SlideShowPluginDoc="The documentation is available [[here|http://www.math.ist.utl.pt/~psoares/addons.html#SlideShowPluginDoc]].";
})(jQuery)
}
//}}}
!Description
This plugin turns any number of tiddlers into a slide show. A single macro provides a flexible way to present a set of tiddlers, including:
#a full screen presentation that hides the TiddlyWiki structure (header, sidebar, main menu);
#a way to navigate through a set of tiddlers keeping the TiddlyWiki structure (similar to the [[NavigationMacro|http://tw.lewcid.org/#NavigationMacro]] by Saq Imtiaz);
#a display of all the selected tiddlers ready to be printed.
!Main features
Most features that are usually found in presentation software are available. 
*Build a slide show from a list of tiddlers' titles or selecting a specific tag with optional sort
*Build a slide show from a single tiddler where slides are divided by a separator
*Fully customizable presentations (CSS knowledge required)
*Auto-advancing slide show (kiosk mode) and looping (circular mode)
*Incremental display (several overlays or layers in a slide)
*Optional clock with 4 different modes:
**local time
**elapsed time of presentation
**elapsed time for each slide
**countdown clock for a given period
*Screen blanking for pauses
!Installation
To install this plugin copy the tiddler SlideShowPlugin to your TiddlyWiki, label it with the ''systemConfig'' tag, save the TW and refresh the browser.
Optionally, you can also copy this documentation tiddler. If you don't, a link to the original one in my site is provided.  
!Quick start
The simplest way to make a slide show is to create a new tiddler with references to all the tiddlers you want to include in your presentation. Any reference or group of references to tiddlers that should be skipped must be wrapped in a {{{exclude}}} class as in the following example:
{{{
MissingSlide
[[First slide|SlideShowExample-1]] {{exclude{(the tiddler SlideShowPluginDoc will not be included in the presentation)}}}
SlideShowExample-2
SlideShowExample-3
SlideShowExample-4
}}}
Add {{{<<slideShow>>}}} anywhere in the tiddler, close the edit form, click the ''slide show'' button and there you are. Move forward/backward in the presentation with the mouse left/right button. If you move the mouse pointer over the bottom of the browser window you will see a few navigation buttons. Click the ''x'' button or press the ''Escape'' key to exit.
!Options
{{{
<<slideShow
  noClicks
  noKeyboard
  noOverlays
  cycle
  showAll
  single
  tiddler:tiddler
  label:string
  tooltip:string
  tag:tag
  sort:field
  theme:tiddler
  toc:string
  auto:time
  clock:type
  clockFormat:string
  header:string
  footer:string
>> 
}}}
''noClicks''
Disables navigation through mouse clicks on the tiddlers. This is useful when there are lots of clickable elements in the presentation.
If you want to keep using the mouse to move around the presentation and there are occasional elements that require mouse clicking, these can be formatted with a {{{noClicks}}} class (read more [[here|http://www.tiddlywiki.com/#CustomCssClass]]).

''noKeyboard''
Disables keyboard navigation.

''noOverlays''
Disables the incremental display of overlays.

''cycle''
The slide shows runs in a continuous loop. 

''showAll''
To print a presentation all the selected tiddlers are opened in the specified order. Press any key to return to the default TiddlyWiki layout.

''single''
Use this if a presentation is defined in a single tiddler.

''tiddler''
Use this option to indicate the tiddler where your slide show is defined when it is not the same one that contains the button that starts the presentation.

''label''
Text to replace the default text in the slide show button.

''tooltip''
Text to be shown when the mouse is over the slide show button.

''tag''
Use this option to create a slide show with the tiddlers with the provided tag instead of providing a list of tiddlers.

''sort''
If the ''tag'' option is used you can use this other option to sort the tiddlers according to a specific field. Valid values are: //created// (default), //modified//, //title// and //text//.

''theme''
A user provided tiddler containing CSS rules that define the style of the slide show. To redefine the default style, edit the SlideShowStyleSheet shadow tiddler. 

''toc''
Choose the type of table of contents. Possible values: ''titles'' will enable the use of the tiddlers titles, ''headers'' (default) to choose html headers (h1, h2,...), anything else will disable the table of contents.  

''auto''
The slide show auto advances after the defined number of seconds. The slide show can be paused by pressing the ''space bar''.

''clock''
Displays a clock near the navigation buttons at the bottom of the screen. Four types of clocks can be defined:
#''clock:0'' -- shows the local time.
#''clock:'+''' -- displays the elapsed time of the presentation. Click the clock display to reset the time.
#''clock:'-''' -- displays the elapsed for each slide. Click the clock display to reset the time.
#''clock:-20'' -- displays a countdown clock for the given (negative) number of minutes. Click the clock display to reset the time.
''clockFormat''
A string that defines the clock format. The default is '0hh:0mm:0ss' where the prefix '0' forces a leading zero. 

''header''
A string to be used as a permanent header for the slide show. By default it's used the title of tiddler that defines the slide show.

''footer''
A string to be used as a permanent footer for the slide show. By default the footer is empty.
!Incremental display
A succession of overlays (or layers) can be defined in each slide by marking blocks of text with
{{{
{{overlay1{...some text...}}}, {{overlay2{...some text...}}}, {{overlay3{...some text...}}}, ...
}}}
The default name of the classes (//overlay//) can be redefined with //config.macros.slideShow.text.overlay = "layer"//, for example. 
To costumize the way overlays are shown you can redefine the following CSS classes
*.previousOverlay 
*.currentOverlay 
*.nextOverlay 
in a ~StyleSheet. The default style simply hides the next overlays and shows the current and the previous ones as normal text.
!Slide show navigation
You can navigate through a slide show using the keyboard or the mouse. 
!!Mouse navigation
Left (right) clicking on a slide jumps to the next (previous) slide or overlay. To move to the first or last slides you must use the navigation bar at the bottom of the browser's window.
!!Keyboard
The following keys are defined:
*Home - first slide
*~PageUp - previous slide
*~PageDown - next slide
*End - last slide
*Escape - exit slide show
*Up arrow - first overlay
*Left arrow - previous overlay/slide
*Pause/Right arrow - next overlay/slide
*Down arrow - last overlay
*Spacebar - pause/resume slide show in auto advance mode, next overlay/slide otherwise
*B - blank screen and block the slide show
!Miscellaneous 
Any block of text marked as
{{{
{{comment{For my eyes only!}}}
}}}
will not be displayed in the slide show.

All translatable strings are defined in //config.macros.slideShow.text// parameter. See SlideShowPluginMsgPT with the portuguese translation as an example.
/*{{{*/
/* Default slide show style sheet settings */
.header, #mainMenu, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{
 display:none !important
}

#slideBlanker{
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 z-index: 90; 
 background-color: #000;
 opacity: 0.9;
 filter: alpha(opacity=90)
}

.nextOverlay{
 visibility: hidden
}

.previousOverlay,.currentOverlay{
 visibility: visible
}

#displayArea{
 font-size: 250%;
 margin: 0 !important;
 padding: 0
}

#controlBar{
 position: fixed;
 bottom: 2px;
 right: 2px;
 width: 100%;
 text-align: right
}

#controlBar .button{
 margin: 0 0.25em;
 padding: 0 0.25em
}

#slideHeader{
 font-size: 200%;
 font-weight: bold
}

#slideFooter{
 position: fixed;
 bottom: 2px
}

.slideFooterOff #navigator{
 visibility: hidden
}

#slideClock{
 margin: 0 5px 0 5px
}

#slideCounter{
 cursor: pointer;
 color: #aaa
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 bottom: 2em;
 right: 0;
 background: #fff;
 border: 1px solid #000;
 text-align: left
}

#jumpItem{
 padding-left:0.25em
}

#jumpInput{
 margin-left: 0.25em;
 width: 3em
}

.tocLevel1{
 font-size: .8em
}

.tocLevel2{
 margin-left: 1em;
 font-size: .75em
}

.tocLevel3{
 margin-left: 2em;
 font-size: .7em
}

.tocLevel4{
 margin-left: 3em;
 font-size: .65em
}

.tocLevel5{
 margin-left: 4em;
 font-size: .6em
}

.tocLevel6{
 margin-left: 5em;
 font-size: .55em
}

/* local changes for coursebook */

/* Disable slide blanker */
#slideBlanker {
 opacity: 0.0;
 filter: alpha(opacity=0)
}

/* Don't do overlay displays, display whole thing at once. */
.nextOverlay{
 visibility: visible
}

/* navigator always visible, black text on white background */
.slideFooterOff #navigator{
 visibility: visible;
 background: #FFF;
 foreground: #000;
}

#displayArea{
 font-size: 130%;
}

.title {
display: block !important;
left-margin: 6em;
}

/* put control bar in top right of header */
#controlBar{
 position: relative;
 bottom: 2px;
 right: 2px;
 width: 100%;
 text-align: right;
}

#controlBar .button {
border: 2px solid #000;
border-style: outset;
}

/* put toc as drop down menu not drop up */
#toc{
 font-size: 1em;
 top: 2em;
 right: 0;
 background: #888;
}

/* display comments in student mode with sea green background  */
#contentWrapper.slideShowMode .comment{
 display: block !important;
 background: #FFCC00;
}
.notes {
display: block;
}

#openTiddlers { display: none !important }
/*}}}*/
!PageTemplate
<!--{{{-->
<div id='displayArea'>
<div id='slideBlanker' style='display:none'></div>
<div id='slideHeader'></div>
<div id='tiddlerDisplay'></div>
<div id='slideFooter'></div>
<div id='controlBar' class='slideFooterOff noClicks'></div>
</div>
<!--}}}-->
!ViewTemplate
<!--{{{-->
<div class='title' macro='view title'></div>
<div class='viewer' macro='view text wikified'></div>
<!--}}}-->
!contentViewTemplate
<!--{{{-->
theme
<div class='title' macro='view title'></div>
<div class='viewer' macro='view text wikified'></div>
<!--}}}-->
!StyleSheet
/*{{{*/
#slideBlanker{
 position:absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 z-index: 90; 
 background-color: #000;
 opacity:.9;filter: alpha(opacity=90);
}

#backstageShow, #contentWrapper.slideShowMode .comment{
 display: none !important;
}

#contentWrapper.slideShowMode .nextOverlay{
 visibility: hidden;
}

#contentWrapper.slideShowMode .previousOverlay, #contentWrapper.slideShowMode .currentOverlay{
 visibility: visible;
}

#contentWrapper.slideShowMode #displayArea{
 font-size: 220%;
 margin: 0 !important;
 padding: 0;
}

#controlBar{
 position: fixed;
 bottom: 2px;
 right: 2px;
 width: 100%;
 text-align: right;
}

#controlBar .button{
 margin:0em 0.25em;
 padding:0em 0.25em;
}

#slideHeader{
 font-size: 200%;
 font-weight: bold;
}

#slideFooter{
 position: absolute;
 bottom: 2px;
 font-size: 50%;
}

.slideFooterOff #navigator{
 visibility: hidden;
}

#slideClock{
 margin: 0 5px 0 5px
}

#slideCounter{
 cursor: pointer;
}

#toc{
 display: none;
 position: absolute;
 font-size: .75em;
 bottom: 2em;
 right: 0;
 background: #fff;
 border: 1px solid #000;
 text-align: left;
}

.tocJumpItem input{
 margin-left: 1em;
 width: 3em
}

.tocLevel1{
 font-size: .8em;
}

.tocLevel2{
 margin-left: 1em;
 font-size: .75em;
}

.tocLevel3{
 margin-left: 2em;
 font-size: .7em;
}

.tocLevel4{
 margin-left: 3em;
 font-size: .65em;
}

.tocLevel5{
 margin-left: 4em;
 font-size: .6em;
}

.tocLevel6{
 margin-left: 5em;
 font-size: .55em;
}
/*}}}*/
These sections are used in presentations to provide the text before the buttons that start the slideshows (so the tiddlers mentioned aren't included in the slideshow). Make sure each section is only one line. No blank lines as they display as blank lines when used. The end section merely defines the end for the print section.

!Instructor
Instructor show with theme {{exclude{[[InstructorSlideShowStyleSheet]]}}}:
!Student
Student show with theme  {{exclude{SlideShowStyleSheet}}}:
!Print
Print show with theme {{exclude{[[PrintingSlideShowStyleSheet]]}}}:
!end
This tiddler has jQuery scripts that can be included in side of slides to dynamically change the layout.
!levelOne
<script>
if ( jQuery("body .slideShowMode").length == 0) return;
// We are in slide show mode since the body has a slideShowMode class inside it
if ( jQuery("body .InstructorSlideShowStyleSheet").length == 0) return;
// We are running an instructor slide show so do all the bells and whistles

if ( '$1' == "$" + "1" ) {background="none" } else {background = '$1';};
if ( typeof lastBackground == "undefined") {
     // Assume levelOne will be used as the first substyle. So save the default bg and repeat setting in case
     // they are needed later.
     lastBackground=jQuery("body").css("background-image");
     lastBackgroundRepeat=jQuery("body").css("background-repeat");
}

// Empty existing style
jQuery("#SlideShowDynamicStyle").text("");

// set the style elements in the SlideShowDynamicStyle id'ed style element reserved for our use
jQuery("#SlideShowDynamicStyle").append(".slideShowMode .title {display: none !important}\n"); // ditch the title
jQuery("#SlideShowDynamicStyle").append("body {background-image: " + background + "  }\n" ); // set a background image from the argument
jQuery("#SlideShowDynamicStyle").append("body {background-repeat: no-repeat }\n"); // no repeat
jQuery("#SlideShowDynamicStyle").append("body {-moz-background-size: 100%,auto }\n"); // use firefox for display scale image 100% horiz.
</script>
!levelTwo
<script>
if ( jQuery("body .slideShowMode").length == 0) return;
// We are in slide show mode since the body has a slideShowMode class inside it
/* revert to the basic style sheets either by undoing what was done above or .....
    if ( '$1' == "$" + "1" ) {background=lastBackground; bgrepeat=lastBackgroundRepeat} else {background = '$1'; bgrepeat="no-repeat";};
    jQuery("#SlideShowDynamicStyle").append(".slideShowMode .title {visibility: visible}\n")
    jQuery("#SlideShowDynamicStyle").append(".slideShowMode .title {display: block}\n");
    jQuery("#SlideShowDynamicStyle").append("body {background-image: " + background + " }\n" );
    jQuery("#SlideShowDynamicStyle").append("body {background-repeat: " + bgrepeat + " }\n");
    jQuery("#SlideShowDynamicStyle").append("body {-moz-background-size: auto,auto }\n");
*/
// just empty the style that is reserved for our use.
jQuery("#SlideShowDynamicStyle").text("");
</script>
!levelThree
<script>
if ( jQuery("body .slideShowMode").length == 0) return;
// We are in slide show mode since the body has a slideShowMode class inside it
if ( jQuery("body .InstructorSlideShowStyleSheet").length == 0) return;
// we are running an instructor slide show so do all the bells and whistles

// Empty existing style
jQuery("#SlideShowDynamicStyle").text("");

jQuery("#SlideShowDynamicStyle").append(".slideShowMode .title {background-color: #FF0000}\n");
</script>
!end
/***
|''Name''|SparklinePlugin|
|''Description''|provides support for [[sparklines|http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR&topic_id=1]]|
|''Version''|1.0.0|
|''Status''|stable|
|''Source''|http://www.tiddlywiki.com/coreplugins.html#SparklinePlugin|
|''~CodeRepository:''|http://svn.tiddlywiki.org/Trunk/association/plugins/SparklinePlugin/SparklinePlugin.js |
|''License''|[[BSD open source license]]|
|''~CoreVersion''|2.3.0|
|''Feedback''|[[TiddlyWiki community|http://groups.google.com/group/TiddlyWiki]] |
|''Keywords''|visualization|
!Usage
{{{
<<sparkline numbers>>
}}}
The macro accepts space-separated numeric values as parameter.
!!Examples
Activity on http://www.tiddlywiki.com during the month of April 2005:
{{{<<sparkline 163 218 231 236 232 266 176 249 289 1041 1835 2285 3098 2101 1755 3283 3353 3335 2898 2224 1404 1354 1825 1839 2142 1942 1784 1145 979 1328 1611>>}}}
<<sparkline 163 218 231 236 232 266 176 249 289 1041 1835 2285 3098 2101 1755 3283 3353 3335 2898 2224 1404 1354 1825 1839 2142 1942 1784 1145 979 1328 1611>>
!Code
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}
/%
|Name|SplitTiddler|
|Source|http://www.TiddlyTools.com/#SplitTiddler|
|Version|1.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|html|
|Description|split tiddler contents into separate tiddlers|

%/<html><nowiki><style>
#tiddlerSplitTiddler .tagged { display:none; }
#tiddlerSplitTiddler .label { font-size:90%;font-style:italic;white-space:nowrap; }
#tiddlerSplitTiddler table, #tiddlerSplitTiddler tr, #tiddlerSplitTiddler td
	{ border:0; margin:0; padding:0; }
</style><table><tr><td><form>
<table style='width:100%'><tr><td style='width:20%'>
	<div class='label'>source tiddler:</div>
	<select name='src' value='' style='width:99%;padding:2px;margin:0'
		title='select a tiddler containing source material'>
	<option value=''>select a tiddler...</option>
	</select>
</td><td style='width:20%'>
	<div class='label'>target title format:</div>
	<input name='titleformat' value='%0 - %1' style='width:99%'
		title='format for target tiddler titles'>
</td><td style='width:20%'>
	<div class='label'>output format:</div>
	<input name='format' value='%4' style='width:99%'
		title='format for target tiddler content'>
</td><td style='width:20%'>
	<div class='label'>target field:</div>
	<input name='fieldname' value='text' style='width:99%'
		title='field to hold content in target tiddler'>
</td><td style='width:20%'>
	<div class='label'>add tags:</div>
	<input name='tags' value='' style='width:99%'
		title='tags for target tiddlers'>
</td></tr></table>
<div style='font-size:80%;font-style:italic;text-align:center;color:gray'>
%0=source title, %1=first line of item, %2=first word of item, %3=item number, %4=item content
</div>
<div style='float:left;margin-right:1em'>
<div class='label'>split source content by:</div>
<div style='line-height:2.1em'>
<input type='radio' name='splitby' value='charcount'>every
<input name='charcount' value='1000' onfocus='this.select()' style='width:3em'
	title='split content every N characters'> characters<br>
<input type='radio' name='splitby' value='linecount'>every
<input name='linecount' value='20' onfocus='this.select()' style='width:3em'
	title='split content every N lines'> lines<br>
<input type='radio' name='splitby' value='match' CHECKED>match
<input name='sep' value='\n----\n' onfocus='this.select()' style='width:8em'
	title='match character sequence to split content'><br>
&nbsp; <input type='checkbox' name='regexp' title='match using regular expressions (text patterns)'>use RegExp text pattern<br>
</div></div>
<div style='float:left;margin-right:1em'>
<div class='label'>options:</div>
<input type='checkbox' name='warn' checked>confirm overwrites<br>
<input type='checkbox' name='show'>show tiddlers when done<br>
<input type='checkbox' name='limit'>create only
<input name='maxtids' value='8' style='width:2em'> tiddlers<br>
<input type='checkbox' name='index' checked>create an index tiddler<br>
&nbsp;&nbsp; index item format:
<input name='indexformat' value='<<tiddler [[%0 - %1]]>>' style='width:10em'
	title='%0=target tiddler title'>
</div>
<input type='button' style='float:right;height:5em;margin-top:2.5em' value='split tiddler' onclick="
	var f=this.form;
	if (!f.src.value.length)
		{ alert('select a tiddler title'); f.src.focus(); return false; }
	if (!f.titleformat.value.length)
		{ alert('enter a target title format'); f.titleformat.focus(); return false; }
	if (!f.src.value.length)
		{ alert('enter an output item format'); f.format.focus(); return false; }
	var start=new Date().getTime();
	var src=store.getTiddlerText(f.src.value);
	if (!src) { displayMessage('\x27'+f.src.value+'\x27 not found'); return false; }
	var tags=f.tags.value;
	var parts=[];
	if (f.splitby[0].checked) { /* chars */
		for (var i=0; i<src.length; i+=f.charcount.value)
			parts.push(src.substr(i,f.charcount.value));
	} else if (f.splitby[1].checked) { /* lines */
		var lines=src.split('\n');
		var t=''; var c=f.linecount.value;
		while (lines.length) {
			t+=lines.shift()+'\n'; c--;
			if (!c) { parts.push(t); var c=f.linecount.value; t=''; }
		}
	} else { /* match text/regexp */
		var sep=!f.regexp.checked?f.sep.value.unescapeLineBreaks():new RegExp(f.sep.value);
		var pieces=src.split(sep);
		for (var i=0; i<pieces.length; i++) if (pieces[i].length) parts.push(pieces[i]);
	}
	var msg='Found '+parts.length+' items in \x27'+f.src.value+'\x27. OK to proceed?';
	if (!confirm(msg)) return false;
	if (parts.length) store.suspendNotifications();
	var pad=parts.length.toString().length;
	var tids=[]; var out=[];
	var srctitle=f.src.value;
	var fmt=f.format.value.unescapeLineBreaks();
	var titlefmt=f.titleformat.value.unescapeLineBreaks();
	var fieldname=f.fieldname.value.toLowerCase();
	var indexfmt=f.indexformat.value.unescapeLineBreaks();
	var max=f.limit.checked?f.maxtids.value:parts.length;
	var warn=f.warn.checked;
	for (var p=0; p<max; p++) {
		var lines=parts[p].split('\n');
		var firstline=lines[0];
		var firstword=firstline.split(' ')[0];
		var itemnum=String.zeroPad(p+1,pad);
		if (titlefmt.indexOf('%2')!=-1) /* remove firstword if used in title */
			{ var words=lines[0].split(' '); words.shift(); lines[0]=words.join(' '); var discard=!words.length; }
		if (titlefmt.indexOf('%1')!=-1 || discard) /* remove firstline if used in title */
			lines.shift();
		var content=lines.join('\n');
		var args=[srctitle,firstline,firstword,itemnum,content];
		var tid=titlefmt.format(args).replace(/[\[\]\|]/g,'_');
		var txt=fmt.format(args);
		var fields={}; if (fieldname!='text')
			{ fields[fieldname]=txt; txt='<<view '+fieldname+' wikified>>'; }
		var tags=tags.format(args);
		if (warn && store.tiddlerExists(tid) && !confirm(config.messages.overwriteWarning.format([tid])))
			continue;
		store.saveTiddler(tid,tid,txt,config.options.txtUserName,new Date(),tags,fields);
		if (f.index.checked) out.push(indexfmt.format(args));
		tids.pushUnique(tid);
	}
	var elapsed=(new Date().getTime()-start)/1000;
	if (parts.length) store.resumeNotifications();
	if (tids.length) {
		if (f.index.checked) {
			var tid=f.src.value+'Index';
			if (!warn||!store.tiddlerExists(tid)||confirm(config.messages.overwriteWarning.format([tid])))
				store.saveTiddler(tid,tid,out.join('\n'),config.options.txtUserName,new Date(),[],{});
		}
		store.notifyAll();
		if (f.show.checked) story.displayTiddlers(story.findContainingTiddler(this),tids);
		displayMessage('created '+tids.length+' target tiddlers in '+elapsed+' seconds');
	}
"><div style='clear:both'></div>
</form></td></tr></table></html><<tiddler {{
	var list=place.lastChild.getElementsByTagName('form')[0].src;
	store.forEachTiddler(function(title,tiddler){
		list.options[list.length]=new Option(title,title);
	});
'';}}>>
Before splitting a tiddler:

# rename source tiddler to "SOURCE Chapter ...."
# add InstructorOnly tag to SOURCE tiddler

To split:

# Open SplitTiddler. In SplitTiddler:
## Select the SOURCE tiddler (may need to close/refresh to get updated list)
## Set target title format {{{Chapter  X - %1}}}
## Set output format: {{{%4}}}
## add the tag "content"
## split on section headings so: {{{^! |\n! }}} using match mechanism
## check use ~RegExp text pattern
## check:
*** Confirm overwrites
*** show tiddlers when done
*** create an index tiddler
# index item format: {{{[[Chapter  X - %1]]}}} to match the target title format

After split:
# delete any TOC only tiddlers
# Check the first tidder the %1 text can be the first line of the tiddler if there is no starting section header. Paste the text into the tiddler and create a section head.
# Look for new orphaned references to original tiddler as it is unlikely that the new story tiddler will be the best reference.
# Rename index tiddler to original SOURCE tiddler name
# remove the TOC tiddler from the index tiddler, add any created section head for the first tiddler, and add the index tiddler so it open as part of the story as a TOC.
# tag the index tiddler with "chapter story excludeOrphans" and bblisa if needed

Use the sequence:
{{{#chapter -#story -#InstructorOnly}}}
in the search box to list tiddlers tagged with chapter that are not tagged with stories or InstructorOnly. This should be the empty set if everything is done.

Now you need to view the missing tiddlers sequence since the names have changed and previously valid links may not longer be.
<<slideShow  theme:InstructorSlideShowStyleSheet noClicks tod:headers footer:"copyright&copy; 2010<br />John Rouillard" clock:+ label:"Instructor" tooltip:"Start slideshow in instructor projection mode"' tiddler:SingleTiddlerSlideshowTest single>>
/***
|Name|StorySaverPlugin|
|Source|http://www.TiddlyTools.com/#StorySaverPlugin|
|Documentation|http://www.TiddlyTools.com/#StorySaverPluginInfo|
|Version|1.8.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|MarkupPostBody|
|Description|save/restore current tiddler view between browser sessions|
Automatically save a list of currently viewed tiddlers (the 'story') in a local cookie, {{{txtSavedStory}}} and then open those tiddlers when the document is reloaded, so you can resume working from the same place you left off!!  Also, use {{{<<saveStory>>}}} and {{{<<openStory>>}}} macros to quickly save/re-display stories stored in tiddlers, using a command link, droplist, or popup display.
!!!!!Documentation
>see [[StorySaverPluginInfo]]
!!!!!Configuration
<<<
<<option chkSaveStory>> use automatic story cookie (reopens tiddlers on startup)
<<option chkStoryAllowAdd>>include 'add a story' command in droplist/popup
<<option chkStoryFold>>fold story tiddlers when opening a story (see [[CollapseTiddlersPlugin]])
<<option chkStoryClose>>close other tiddlers when opening a story
<<option chkStoryTop>>open story tiddlers at top of column
<<option chkStoryBottom>>open story tiddlers at bottom of column
<<<
!!!!!Revisions
<<<
2009.10.20 1.8.3 fix handling for 'add' item in popup menu
|please see [[StorySaverPluginInfo]] for additional revision details|
2007.10.05 1.0.0 initial release. Moved [[SetDefaultTiddlers]] inline script and rewrote as a {{{<<saveStory>>}}} macro.
<<<
!!!!!Code
***/
//{{{
version.extensions.StorySaverPlugin= {major: 1, minor: 8, revision: 3, date: new Date(2009,10,20)};

var defaults={
	chkSaveStory:		false,
	chkStoryFold:		true,
	chkStoryClose:		true,
	chkStoryAllowAdd:	true,
	chkStoryTop:		true,
	chkStoryBottom:		false
};
for (var id in defaults) if (config.options[id]===undefined)
	config.options[id]=defaults[id];

// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
	window.removeCookie=function(name) {
		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;'; 
	}
}

// save or clear story cookie on exit
if (window.coreTweaks_confirmExit==undefined) {
	window.coreTweaks_confirmExit=window.confirmExit;
	window.confirmExit=function() {
		if (config.options.chkSaveStory) { // save cookie
			var links=[];
			story.forEachTiddler(function(title,element){links.push('[['+title+']]');});
			config.options.txtSavedStory=links.join(' ');
			saveOptionCookie('txtSavedStory');
		} else removeCookie('txtSavedStory');
		return window.coreTweaks_confirmExit.apply(this,arguments);
	}
}
//}}}
/***
''apply saved story on startup:'' //important note: the following code is actually located in [[MarkupPostBody]].  This is because it needs to supercede the core's getParameters() function, which is called BEFORE plugins are loaded, preventing the normal plugin-based hijack method from working, while code loaded into [[MarkupPostBody]] will be processed as soon as the document is read, even before the TW main() function is invoked.//
<<tiddler MarkupPostBody>>
***/
//{{{
config.macros.saveStory = {
	label: 'set default tiddlers',
	defaultTiddler: 'DefaultTiddlers',
	prompt: 'store a list of currently displayed tiddlers in another tiddler',
	askMsg: 'Enter the name of a tiddler in which to save the current story:',
	tag: 'story',
	excludeTag: 'excludeStory',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var tid=params.shift()||'DefaultTiddlers';
		var label=params.shift()||this.label;
		var tip=params.shift()||this.prompt;
		var btn=createTiddlyButton(place,label,tip,this.setTiddler,'button');
		btn.setAttribute('tid',tid);
		btn.setAttribute('extratags','[['+params.join(']] [[')+']]');
	},
	setTiddler: function() {
		var cms=config.macros.saveStory; // abbrev
		// get list of current open tiddlers
		var tids=[];
		story.forEachTiddler(function(title,element){
			var t=store.getTiddler(title);
			if (!t || !t.isTagged(cms.excludeTag)) tids.push('[['+title+']]');
		});
		// get target tiddler
		var tid=this.getAttribute('tid');
		if (!tid || tid=='ask') {
			tid=prompt(cms.askMsg,cms.defaultTiddler);
			if (!tid || !tid.length) return false; // cancelled by user
		}
		if(store.tiddlerExists(tid) && !confirm(config.messages.overwriteWarning.format([tid])))
			return false;
		tids=tids.join('\n');
		var t=store.getTiddler(tid); var tags=t?t.tags:[];
		var extratags=(this.getAttribute('extratags')||'').readBracketedList();
		for (var i=0; i<extratags.length; i++) tags.pushUnique(extratags[i]);
		tags.pushUnique(cms.tag);
		store.saveTiddler(tid,tid,tids,config.options.txtUserName,new Date(),tags,t?t.fields:null);
		story.displayTiddler(null,tid);
		story.refreshTiddler(tid,null,true);
		displayMessage(tid+' has been '+(t?'updated':'created'));
		return false;
	}
}
//}}}
//{{{
config.macros.openStory = {
	label: 'open story: %0',
	prompt: 'open the set of tiddlers listed in: %0',
	popuplabel: 'stories',
	popupprompt: 'view a set of tiddlers',
	tag: 'story',
	selectprompt: 'select a story...',
	optionsprompt: 'viewing options...',
	foldcmd: '[%0] fold story',
	foldprompt: 'fold story tiddlers when opening a story',
	closecmd: '[%0] close others',
	closeprompt: 'close other tiddlers when opening a story',
	topcmd: '[%0] open at top',
	topprompt: 'open story tiddlers at top of column',
	bottomcmd: '[%0] open at bottom',
	bottomprompt: 'open story tiddlers at bottom of column',
	addcmd: 'add a story...',
	addprompt: 'create a new story',
	excludeTag: 'excludeStory',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		if (params[0].toLowerCase()=='list') return this.createList(place,params);
		else if (params[0].toLowerCase()=='popup') return this.createPopup(place,params);
		else this.createButton(place,params);
	},
	showStory: function(tid,fold) {
		var co=config.options; // abbrev
		var tids=[];
		var t=store.getTiddler(tid);
		var tagged=store.getTaggedTiddlers(tid,'title');
		if (tagged.length) // if tiddler IS a tag, use tagged tiddlers as story
			for (var i=0; i<tagged.length; i++) tids.push(tagged[i].title);
		else if (t) { // get tiddler list from content
			if (!t.linksUpdated) t.changed();
			for (var i=0; i<t.links.length; i++) {
				var tid=store.getTiddler(t.links[i]);
				if (tid && !tid.isTagged(this.excludeTag))
					tids.push(t.links[i]);
			}
		}
		var template=null;
		if (fold||co.chkStoryFold) template='CollapsedTemplate'; // see [[CollapseTiddlersPlugin]]
		if (!store.tiddlerExists('CollapsedTemplate')) template=null;
		if (co.chkStoryClose) story.closeAllTiddlers();
		var pos='top'; var first=tids[0];
		if (!story.isEmpty() && co.chkStoryBottom) { pos='bottom'; tids=tids.reverse(); }
		story.displayTiddlers(pos,tids,template);
		var cmd='var t=story.getTiddler("'+first+'");if(t)window.scrollTo(0,t.offsetTop);';
		var delay=config.options.chkAnimate?config.animDuration+100:0;
		setTimeout(cmd,delay);
	},
	createButton: function(place,params) {
		var tid=params[0]||'';
		var label=params[1]||this.label; label=label.format([tid]);
		var tip=params[2]||this.prompt; tip=tip.format([tid]);
		var fold=(params[3]&&(params[3].toLowerCase()=='fold'))||config.options.chkStoryFold;
		var fn=function(){config.macros.openStory.showStory(this.getAttribute('tid'),this.getAttribute('fold')); return false; };
		var btn=createTiddlyButton(place,label,tip,fn,'button');
		btn.setAttribute('tid',tid);
		if (fold) btn.setAttribute('fold',fold);
	},
	createPopup: function(place,params) {
		params.shift(); // discard 'popup' keyword
		var label=params.shift()||this.popuplabel;
		var tip=params.shift()||this.popupprompt;
		var btn=createTiddlyButton(place,label,tip,this.showPopup,'button');
		btn.setAttribute('filter',params.shift()||config.macros.openStory.tag);
	},
	showPopup: function(ev) { var e=ev||window.event;
		var co=config.options; // abbrev
		var cmo=config.macros.openStory; // abbrev
		var indent='\xa0\xa0';
		var p=Popup.create(this); if (!p) return false;
		createTiddlyText(createTiddlyElement(p,'li'),cmo.selectprompt);
		var stories=store.filterTiddlers('[tag['+this.getAttribute('filter')+']]');
		for (var s=0; s<stories.length; s++) {
			var label=indent+stories[s].title;
			var tip=cmo.prompt.format([stories[s].title]);
			var fn=function(){config.macros.openStory.showStory(this.getAttribute('tid'));return false;};
			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
			btn.setAttribute('tid',stories[s].title);
		}
		createTiddlyText(createTiddlyElement(p,'li'),cmo.optionsprompt);
		if (store.tiddlerExists('CollapsedTemplate')) {
			var label=indent+cmo.foldcmd.format([co.chkStoryFold?'x':'\xa0\xa0']);
			var tip=cmo.foldprompt;
			var fn=function(){ config.macros.option.propagateOption(
				'chkStoryFold','checked',!config.options.chkStoryFold,'input'); return false; };
			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
		}
		var label=indent+cmo.closecmd.format([co.chkStoryClose?'x':'\xa0\xa0']);
		var tip=indent+cmo.closeprompt;
		var fn=function(){ config.macros.option.propagateOption(
			'chkStoryClose','checked',!config.options.chkStoryClose,'input'); return false; };
		var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
		if (!co.chkStoryClose) {
			var label=indent+cmo.topcmd.format([co.chkStoryTop?'x':'\xa0\xa0']);
			var tip=indent+cmo.topprompt;
			var fn=function(){
				config.macros.option.propagateOption(
					'chkStoryTop','checked',!config.options.chkStoryTop,'input');
				config.macros.option.propagateOption(
					'chkStoryBottom','checked',!config.options.chkStoryTop,'input');
				return false;
			};
			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
			var label=indent+cmo.bottomcmd.format([co.chkStoryBottom?'x':'\xa0\xa0']);
			var tip=indent+cmo.botprompt;
			var fn=function(){
				config.macros.option.propagateOption(
					'chkStoryBottom','checked',!config.options.chkStoryBottom,'input');
				config.macros.option.propagateOption(
					'chkStoryTop','checked',!config.options.chkStoryBottom,'input');
				return false;
			};
			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
		}
		if (!readOnly && co.chkStoryAllowAdd) {
			var label=cmo.addcmd;
			var tip=cmo.addprompt;
			var fn=config.macros.saveStory.setTiddler;
			createTiddlyElement(createTiddlyElement(p,'li'),'hr');
			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
		}
		Popup.show();
		e.cancelBubble=true;if(e.stopPropagation)e.stopPropagation();
		return false;
	},
	createList: function(place,params) {
		var cmo=config.macros.openStory; // abbrev
		var s=createTiddlyElement(place,'select',null,'storyListbox');
		s.size=1;
		s.onchange=function() {
			if (this.value=='_fold') {
				config.macros.option.propagateOption('chkStoryFold','checked',
					!config.options.chkStoryFold,'input');
				cmo.refreshList();
			} else if (this.value=='_close') {
				config.macros.option.propagateOption('chkStoryClose','checked',
					!config.options.chkStoryClose,'input');
				cmo.refreshList();
			} else if (this.value=='_top') {
				config.macros.option.propagateOption('chkStoryTop','checked',
					!config.options.chkStoryTop,'input');
				cmo.refreshList();
			} else if (this.value=='_bottom') {
				config.macros.option.propagateOption('chkStoryBottom','checked',
					!config.options.chkStoryBottom,'input');
				cmo.refreshList();
			} else if (this.value=='_add')
				config.macros.saveStory.setTiddler.apply(this,arguments);
			else cmo.showStory(this.value);
		}
		params.shift(); // discard 'list' keyword
		s.setAttribute('filter',params.shift()||cmo.tag);
		setStylesheet('.storyListbox { width:100%; }', 'StorySaverStyles');
		store.addNotification(null,this.refreshList); this.refreshList();
		return;
	},
	refreshList: function() {
		var cmo=config.macros.openStory; // abbrev
		var indent='\xa0\xa0\xa0\xa0';
		var lists=document.getElementsByTagName('select');
		for (var i=0; i<lists.length; i++) { if (lists[i].className!='storyListbox') continue;
			var here=lists[i];
			var stories=store.filterTiddlers('[tag['+here.getAttribute('filter')+']]');
			while (here.length) here.options[0]=null; // remove current list items
			here.options[here.length]=new Option(cmo.selectprompt,'',true,true);
			for (var s=0; s<stories.length; s++)
				here.options[here.length]=new Option(indent+stories[s].title,stories[s].title);
			if (!readOnly && config.options.chkStoryAllowAdd)
				here.options[here.length]=new Option(cmo.addcmd,'_add');
			here.options[here.length]=new Option(cmo.optionsprompt,'');
			if (store.tiddlerExists('CollapsedTemplate')) {
				var msg=cmo.foldcmd.format([config.options.chkStoryFold?'x':'\xa0\xa0']);
				here.options[here.length]=new Option(indent+msg,'_fold');
			}
			var msg=cmo.closecmd.format([config.options.chkStoryClose?'x':'\xa0\xa0']);
			here.options[here.length]=new Option(indent+msg,'_close',false,false);
			if (!config.options.chkStoryClose) {
				var msg=cmo.topcmd.format([config.options.chkStoryTop?'x':'\xa0\xa0']);
				here.options[here.length]=new Option(indent+msg,'_top',false,false);
				var msg=cmo.bottomcmd.format([config.options.chkStoryBottom?'x':'\xa0\xa0']);
				here.options[here.length]=new Option(indent+msg,'_bottom',false,false);
			}
		}
	}
}
//}}}
/***
! StorySaverPlugin

Try to override text for the popup. Remove the word story add section.
***/
//{{{
config.macros.openStory.label = "open: %0";
config.macros.openStory.popuplabel = "section";
config.macros.openStory.selectprompt = "select a section...";
config.macros.openStory.foldprompt = "fold story tiddlers when opening a section";
config.macros.openStory.closeprompt = "close other tiddlers when opening a section";

config.options.chkStoryAllowAdd = false;
//}}}
/***
|Name|StorySaverPlugin|
|Source|http://www.TiddlyTools.com/#StorySaverPlugin|
|Documentation|http://www.TiddlyTools.com/#StorySaverPluginInfo|
|Version|1.8.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires|MarkupPostBody|
|Description|documentation for [[StorySaverPlugin]]|
Automatically saves a list of currently viewed tiddlers (the "story") in a local cookie, {{{txtSavedStory}}} and then opens those tiddlers when the document is subsequently reloaded, allowing you to quickly resume working with the document from the same place you left off!! The plugin also defines {{{<<saveStory>>}}} and {{{<<openStory>>}}} macros that allow you to quickly save/re-display stories stored in tiddlers, using simple, one-click command links or droplists.
!!!!!Usage
<<<
If a document URL does not contain a paramifier (i.e., a "#..." suffix), then the saved story cookie (if any) will be used //as if// it had been entered as a permaview (e.g., a "#tiddler tiddler tiddler..." suffix on the URL), bypassing the [[DefaultTiddlers]] definition.  This behavior is automatically applied whenever the plugin is installed in your document.  You can enable/disable the automatic cookie-based StorySaver feature by using the checkbox below:
><<option chkSaveStory>> enable StorySaverPlugin
>//usage:// {{{<<option chkSaveStory>>}}}
You can also temporarily //bypass// the redisplay of a saved story ''without disabling the StorySaver cookie'' by including a trailing "#" at the end of the document URL.  This will cause your document to be loaded into the browser without displaying //any// initial tiddlers at all.  Alternatively, you can enter {{{#story:storyname}}} on the end of the URL (e.g., {{{#story:DefaultTiddlers}}}) to display any specific saved story, regardless of the value of the cookie-based saved story.

__''saveStory macro:''__
The {{{<<saveStory>>}}} macro lets you write the list of currently viewed tiddlers to a specified tiddler name (e.g., DefaultTiddlers, MyFavorites, etc.).  Tiddlers containing saved stories are automatically tagged with <<tag story>>, so that they can be recognized by the {{{<<storyViewer>>}}} macro (see [[StoryViewerPlugin]]).  The syntax for the {{{<<saveStory>>}}} macro is:
{{{
<<saveStory storyname label tooltip tag tag tag...>>
}}}
*''storyname''<br>is the target tiddler in which to save the current story.  If you use the keyword, ''ask'', in place of the tiddlername, you will be prompted to enter a tiddler title when saving the story (default: DefaultTiddlers).
*''label'' and ''tooltip''<br>are the link text and mouseover guide-text
*''tag tag tag...'' (optional)<br>are extra tags that are added when saving a story tiddler (in addition to the default<<tag story>>tag).

__''openStory macro:''__
To redisplay a saved story, the {{{<<openStory>>}}} macro can be used to embed either a droplist of all saved stories, or a link for a specified story.  Selecting from the droplist or clicking the link opens the corresponding set of tiddlers.  
{{{
<<openStory list tagValue>>
<<openStory popup label tooltip tagValue>>
<<openStory storyname label tooltip fold>>
}}}
*''list''<br>shows a droplist of all saved stories, plus additional commands/viewing options.  Selecting a story opens the corresponding tiddlers.
*''popup''<br>shows a popup display containing a list of all saved stories, plus additional commands/viewing options.  Selecting a story opens the corresponding tiddlers.  ''label'' and ''tooltip'' are optional and provide alternative display text and mouseover help text, respectively.
*''storyname''<br>is a tiddler containing a saved story.  //Note: You can also use a tag value as a storyname, in which case the story view will be composed of all tiddlers tagged with the specified tag value.//
*''label''<br>is the command link text (default: "open story: %0", where %0 is replaced by the storyname).
*''tooltip''<br>is the command mouseover guide-text (default: "open the set of tiddlers listed in: '%0'"),
*''tagValue'' (optional, default='story')<br>specifies an alternative tag value to match when listing story tiddlers.  Note: if MatchTagsPlugin is installed, you can also use a compound //boolean tag expression//, enclosed within doubled square brackets.
*''fold''<br>If this optional keyword is present, the story tiddlers are initially 'folded' using [[CollapsedTemplate]] instead of the usual [[ViewTemplate]] (see [[CollapseTiddlersPlugin]]).

__''excludeStory tag:''__
Any tiddlers tagged with<<tag excludeStory>>will be automatically omitted when creating new story tiddlers with {{{<<saveStory>>}}}.  Similarly, if a tiddler that is part of a saved story is tagged with<<tag excludeStory>>, it will not be displayed when that story is opened via {{{<<openStory>>}}}.

__''PermaView command link enhancement:''__
In order to further aide in saving/restoring the list of tiddlers currently being viewed, the core {{{<<permaview>>}}} command has been enhanced, so its link value always includes the current story view tiddler list as a paramifier in the URL.  This let you quickly use the browser's right-click menu directly on the permalink command text to "bookmark this link...".  Depending upon your system, you may also be able to drag the 'permaview' link directly from the page and drop it onto your desktop to create an instant permaview-bearing URL shortcut icon.
<<<
!!!!!Examples
<<<
*{{{<<saveStory TestStory "save a test story">>}}}<br>{{smallform{<<saveStory TestStory "save a test story">>}}}
*{{{<<openStory TestStory>>}}}<br><<openStory TestStory>>
*{{{<<openStory list>>}}}<br>{{smallform{<<openStory list>>}}}
*{{{<<openStory popup label tooltip>>}}}<br>{{smallform{<<openStory popup>>}}}
<<<
!!!!!Configuration
<<<
<<option chkSaveStory>> use automatic story cookie (reopens tiddlers on startup)
<<option chkStoryAllowAdd>>include 'add a story' command in droplist/popup
<<option chkStoryFold>>fold story tiddlers when opening a story (see [[CollapseTiddlersPlugin]])
<<option chkStoryClose>>close other tiddlers when opening a story
<<option chkStoryTop>>open story tiddlers at top of column
<<option chkStoryBottom>>open story tiddlers at bottom of column
<<<
!!!!!Revisions
<<<
2009.10.20 1.8.3 fix handling for 'add' item in popup menu
2009.08.29 1.8.2 added 'return false' to all button handlers to fix IE page-transition error
2009.08.23 1.8.1 fixed 'excludeStory' handling for links to missing tiddlers
2009.08.20 1.8.0 added 'excludeStory' tag handling
2009.07.27 1.7.1 corrected test for {{{chkStoryAllowAdd}}} when rendering //list// output
2009.07.27 1.7.0 added options: {{{chkStoryAllowAdd=true}}}, {{{chkStoryTop=true}}}, and {{{chkStoryBottom=false}}}.  Also, autoscroll to first tiddler in story
2009.07.26 1.6.0 added optional 'extratags' param to {{{<<saveStory>>}}} and 'tagfilter' to {{{<<openStory>>}}}
2009.07.06 1.5.1 in setTiddler(), use pushUnique() to avoid double 'story' tag
2009.04.24 1.5.0 added optional 'fold' param to {{{<<openStory StoryName ...>>}}} macro
2008.09.07 1.4.3 added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.07.11 1.4.2 in confirmExit(), corrected bracketing for titles containing spaces
2008.03.10 [*.*.*] plugin size reduction: documentation moved to [[StorySaverPluginInfo]]
2008.01.01 1.4.1 sort list of stories alphabetically
2008.01.01 1.4.0 added popup option
2007.12.31 1.3.1 instead of readBracketedList(), use internal tiddler.links[] to retrieve story list from tiddler content. Allows more flexible formatting of story tiddler content: anything content that is not a tiddler link is automatically filtered out of the list.
2007.10.23 1.3.0 split {{{<<storyViewer>>}}} macro definition into stand-alone [[StoryViewerPlugin]] to allow separate installation of story saving vs. story viewing features.
2007.10.21 1.2.0 added {{{<<openStory>>}}} and {{{<<storyViewer>>}}} macros.
2007.10.20 1.1.0 in setTiddler(), automatically add "story" tag to saved story tiddlers
2007.10.18 1.0.1 added default initialization for chkSaveStory option value.  Also, in setTiddler(), call displayTiddler() after saving story to ensure that altered tiddler is shown to the user.
2007.10.05 1.0.0 initial release.   Moved [[SetDefaultTiddlers]] inline script and rewrote as a {{{<<saveStory>>}}} macro.  Moved permaview "mouseover HREF" enhancement from [[CoreTweaks]].
<<<
* Only notes are easy to edit:
** double-clicking on the notebook
** using the @@edit notes@@ button
* Content editing must be invoked by a menu, double clicking on a tiddler doesn't work
* This extra barrier inhibits student changes to content which can be overwritten during sync
/*{{{*/

body {background-image: none }

/* Make the main menu fill from the left */
#mainMenu {text-align: left}
#mainMenu ul{margin-left: 0em; padding-left: 0.5em;}

/* insert a scroll bar in the message area if it gets too long say from loadTiddlers output */
#messageArea { max-height:25em; overflow:auto; }

/* custom styles for two parallel columns. Classes cola and colb */
.col2a {width:45%; float:left; margin-left:0.5em;}
.col2b {width:45%; float:left; margin-left:1.5em;}

/* custom syles for three column layout */
.col3a {width:30%; float:left; margin-left:0.5em;}
.col3b {width:30%; float:left; margin-left:1.5em;}
.col3c {width:30%; float:left; margin-left:1.5em;}

/* reset any column style */
.nocol{clear:both;display: block;}

/* used for slides with multicolumn where I don't want unordered list indented
    usually used with col2a/col2b */
.liflushleft ul{margin-left:0em !important;padding-left:0.5em !important;}

/* diagram support styles */
/* borderless tables for diagrams */
.viewer table.diagram, .viewer table.diagram * {
	border: 0;
        margin-left:auto;
        margin-right:auto;
}

/* some resizing of elements: reduce header size and space on main menu headers */
.headerForeground, .headerShadow{padding:2.5em 0 1em 1em} 
#mainMenu h1 {
margin-top: 5px;
}

/* increase width of annotation plugin popups */
.anno{max-width: 45%;}

@media print {
/* disable the stuff that is useful only online */
  /* opentiddlers index div across top of story */
#openTiddlers {display: none}

  /* remove: last changed by whom, list of tags on tiddler, table of contents,
     openstorybutton controls*/
.subtitle, .tagged, .sectionTOC, .openStoryButton {display: none}

  /* hide certain images when printing. Be nice to the environment with non-content images */
.noprintimage { display: none !important }

 /* hide empty notes when printing. With rouilj's patch to TiddlerNotesPlugin if the notes tiddler
     exists (indicating a non-empty note) the notes box also gets the TiddlerNotesExists class
     which is used to turn on printing for notes with contents while leaving empty notes blocks
     undisplayed. Controls of the box are undisplayed and for printing make the background of the
     notes box go away (transparent). Don't hide the .notes class as that also hides footnotes
     which are supposed to be printed. */
 .TiddlerNotes {display: none; background: transparent; }
 .editNotesButton {display: none}
 .TiddlerNotesExists {display: block}

/* when printing slides with comments use these styles */
div.comment {
 border: 1pt dashed;
 padding: 0.5em;
}

/* putting a box around comment spans doesn't work,
    it boxes every line so change color */
span.comment {
background: #efefef;
}

 /* slideViewTemplate is used for slides which are defined by having the slide tag as the first tag on the tiddler
     so this css rule makes every slide tiddler start on a new page. */

*[template="slideViewTemplate"] {page-break-after: always}

/* try to prevent terms from being orphaned at the bottom of a page */
dt {page-break-after: avoid}

.breakhere {page-break-before:always}
}

/* Put the included style sheet here. If the style sheet doesn't exist and this include
   occurs before the @media print... above, then the print styles are used for video
   display when running IE 8 in IE 7 compatibility mode. */

[[InstructorStyleSheet]]

/*}}}*/
<script label="$1">
  /*
 > This script is called with three arguments and copies the tiddler named by the
 > second argument to the tiddler named by the third argument. The first argument
 > is the name of the displayed button. This can be used to change tiddlers for
 > different purposes. E.G. you may want to have two different copies of the
 > student book. So you can use an instance of this to change the DefaultTidders
 > tiddler before saving the student book.
 >
  > To use this inline 'onclick' script, embed the following in your
  > tiddler content:
  >    <<tiddler SwitchContent with:
  >       "instructor mode"
  >       "InstructorSlideShowViewTemplate"
  >       "SlideShowViewTemplate">>
  */
  if ( "$2" === "" ) { // allow shadow or other tiddler to come through
      store.deleteTiddler("$3");
  } else {
      var txt=store.getTiddlerText("$2");
      if (!txt) {displayMessage('"$2" not found'); return false; }
      var t=store.getTiddler('$3');
      if (!t) {displayMessage('"$3" not found, creating'); t = store.getTiddler('$2');}
      var who=config.options.txtUserName;
      var when=new Date();
      store.saveTiddler("$3","$3",txt,who,when,t.tags,t.fields);
      displayMessage('"$2" copied to "$3"');
   }
</script>
/***
|''Name:''|SyncFromSourcePlugin|
|''Description:''|Synchronizes plugins from their original source (issued from plugin info) instead of imported url. So, plugins can be imported from any existing tiddlywiki and still be synchronized with their original source.|
|''Version:''|1.0.0|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.2.0|
|''Browser:''|Firefox 1.5; InternetExplorer 6.0|
!Usage
#import the plugin, save and reload.
#a new column (source) is available in ''sync task'' from the ''backstage button''. If the plugin's source mismatches the plugin server.host (the place from which is was last imported), the source value is displayed.
#a new button is also available : ''reset source''. Click on this button applies plugin's ''source'' as server.host for the checked lines.
Look at this [[example|SyncFromSourceDemo]] on plugin [[homepage|http://visualtw.ouvaton.org/VisualTW.html]].
!Patch required for TiddlyWiki 2.3.0
A bug in TW2.3.0 requires [[SyncPatch]].
!Code
***/
//{{{
config.macros.sync.getSyncableTiddlersWithoutSource = config.macros.sync.getSyncableTiddlersWithoutSource ? config.macros.sync.getSyncableTiddlersWithoutSource : config.macros.sync.getSyncableTiddlers;

config.macros.sync.startSyncWithoutSource = config.macros.sync.startSyncWithoutSource ? config.macros.sync.startSyncWithoutSource : config.macros.sync.startSync;

config.macros.sync.getSyncableTiddlers = function(){
	var syncs = config.macros.sync.getSyncableTiddlersWithoutSource();
	for(var cpt=0;cpt<syncs.length;cpt++){
		var s= getPluginInfo(syncs[cpt].tiddler).Source;
		if (s) {
			var source = AdaptorBase.minHostName(s);
			source = source.replace(/#[^#]*$/,"").replace(/\/*$/,"");
			syncs[cpt].source = (source==syncs[cpt].tiddler.fields["server.host"]) ? "": source;
		}
		else syncs[cpt].source = "";
	}
	return syncs;
}

config.macros.sync.startSync = function(place) {
	config.macros.sync.startSyncWithoutSource(place);
	var w = new Wizard(place.getElementsByTagName("form")[0]);
	w.setButtons([
			{caption: this.syncLabel, tooltip: this.syncPrompt, onClick: this.doSync},
			{caption: this.syncSourceLabel, tooltip: this.syncSourcePrompt, onClick: this.doSyncSource}
		]);
}

merge(config.macros.sync,{
	syncSourceLabel : "reset source",
	syncSourcePrompt : "reset synchronization to plugin source, if available"
})

config.macros.sync.doSyncSource = function(e)
{
	var rowNames = ListView.getSelectedRows(currSync.listView);
	for(var t=0; t<currSync.syncList.length; t++) {
		var si = currSync.syncList[t];
		if((rowNames.indexOf(si.title) != -1)&&si.source) {
			si.tiddler.fields["server.host"]=si.source;
			si.tiddler.fields["server.type"]="file";
			store.setDirty(true);
		}
	}
	backstage.switchTab(null);
	return false;
};

config.macros.sync.listViewTemplate.columns.push({name: 'Source', field: 'source', title: "Source", type: 'Link'});

//}}}
<<timeline "" 50>>
/***
|''Name:''|TableSortingPlugin|
|''Description:''|Dynamically sort tables by clicking on column headers|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#TableSortingPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.02|
|''Date:''|25-01-2008|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|
!!Usage:
* Make sure your table has a header row
** {{{|Name|Phone Number|Address|h}}}<br> Note the /h/ that denote a header row 
* Give the table a class of 'sortable'
** {{{
|sortable|k }}}<br />{{{
|Name|Phone Number|Address|h
}}}<br />Note the /k/ that denotes a class name being assigned to the table.
* To disallow sorting by a column, place {{{<<nosort>>}}} in it's header
* To automatically sort a table by a column, place {{{<<autosort>>}}} in the header for that column
** Or to sort automatically but in reverse order, use {{{<<autosort reverse>>}}}

!!Example:
|sortable|k
|Name |Salary |Extension |Performance |File Size |Start date |h
|ZBloggs, Fred |$12000.00 |1353 |+1.2 |74.2Kb |Aug 19, 2003 21:34:00 |
|ABloggs, Fred |$12000.00 |1353 |1.2 |3350b |09/18/2003 |
|CBloggs, Fred |$12000 |1353 |1.200 |55.2Kb |August 18, 2003 |
|DBloggs, Fred |$12000.00 |1353 |1.2 |2100b |07/18/2003 |
|Bloggs, Fred |$12000.00 |1353 |01.20 |6.156Mb |08/17/2003 05:43 |
|Turvey, Kevin |$191200.00 |2342 |-33 |1b |02/05/1979 |
|Mbogo, Arnold |$32010.12 |2755 |-21.673 |1.2Gb |09/08/1998 |
|Shakespeare, Bill |£122000.00|3211 |6 |33.22Gb |12/11/1961 |
|Shakespeare, Hamlet |£9000 |9005 |-8 |3Gb |01/01/2002 |
|Fitz, Marvin |€3300.30 |5554 |+5 |4Kb |05/22/1995 |

***/
// /%
//!BEGIN-PLUGIN-CODE
config.tableSorting = {
	
	darrow: "\u2193",
	
	uarrow: "\u2191",
	
	getText : function (o) {
		var p = o.cells[SORT_INDEX];
		return p.innerText || p.textContent || '';
	},
	
	sortTable : function (o,rev) {
		SORT_INDEX = o.getAttribute("index");
		var c = config.tableSorting;
		var T = findRelated(o.parentNode,"TABLE");
		if(T.tBodies[0].rows.length<=1) 
			return;
		var itm = "";
		var i = 0;
		while (itm == "" && i < T.tBodies[0].rows.length) {
			itm = c.getText(T.tBodies[0].rows[i]).trim();
			i++;
		}
		if (itm == "") 
			return; 	
		var r = [];
		var S = o.getElementsByTagName("span")[0];		
		c.fn = c.sortAlpha; 
		if(!isNaN(Date.parse(itm)))
			c.fn = c.sortDate; 
		else if(itm.match(/^[$|£|€|\+|\-]{0,1}\d*\.{0,1}\d+$/)) 
			c.fn = c.sortNumber; 
		else if(itm.match(/^\d*\.{0,1}\d+[K|M|G]{0,1}b$/)) 
			c.fn = c.sortFile; 
		for(i=0; i<T.tBodies[0].rows.length; i++) {
			 r[i]=T.tBodies[0].rows[i]; 
		} 
		r.sort(c.reSort);
		if(S.firstChild.nodeValue==c.darrow || rev) {
			r.reverse();
			S.firstChild.nodeValue=c.uarrow;
		} 
		else 
			S.firstChild.nodeValue=c.darrow;
		var thead = T.getElementsByTagName('thead')[0]; 
		var headers = thead.rows[thead.rows.length-1].cells;
		for(var k=0; k<headers.length; k++) {
			if(!hasClass(headers[k],"nosort"))
				addClass(headers[k].getElementsByTagName("span")[0],"hidden");
		}
		removeClass(S,"hidden");
		for(i=0; i<r.length; i++) { 
			T.tBodies[0].appendChild(r[i]);
			c.stripe(r[i],i);
			for(var j=0; j<r[i].cells.length;j++){
				removeClass(r[i].cells[j],"sortedCol");
			}
			addClass(r[i].cells[SORT_INDEX],"sortedCol");
		}
	},
	
	stripe : function (e,i){
		var cl = ["oddRow","evenRow"];
		i&1? cl.reverse() : cl;
		removeClass(e,cl[1]);
		addClass(e,cl[0]);
	},
	
	sortNumber : function(v) {
		var x = parseFloat(this.getText(v).replace(/[^0-9.-]/g,''));
		return isNaN(x)? 0: x;
	},
	
	sortDate : function(v) {
		return Date.parse(this.getText(v));
	},

	sortAlpha : function(v) {
		return this.getText(v).toLowerCase();
	},
	
	sortFile : function(v) { 		
		var j, q = config.messages.sizeTemplates, s = this.getText(v);
		for (var i=0; i<q.length; i++) {
			if ((j = s.toLowerCase().indexOf(q[i].template.replace("%0\u00a0","").toLowerCase())) != -1)
				return q[i].unit * s.substr(0,j);
		}
		return parseFloat(s);
	},
	
	reSort : function(a,b){
		var c = config.tableSorting;
		var aa = c.fn(a);
		var bb = c.fn(b);
		return ((aa==bb)? 0 : ((aa<bb)? -1:1));
	}
};

Story.prototype.tSort_refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function(title,template,force,customFields,defaultText){
	var elem = this.tSort_refreshTiddler.apply(this,arguments);
	if(elem){
		var tables = elem.getElementsByTagName("TABLE");
		var c = config.tableSorting;
		for(var i=0; i<tables.length; i++){
			if(hasClass(tables[i],"sortable")){
				var x = null, rev, table = tables[i], thead = table.getElementsByTagName('thead')[0], headers = thead.rows[thead.rows.length-1].cells;
				for (var j=0; j<headers.length; j++){
					var h = headers[j];
					if (hasClass(h,"nosort"))
						continue;
					h.setAttribute("index",j);
					h.onclick = function(){c.sortTable(this); return false;};
					h.ondblclick = stopEvent;
					if(h.getElementsByTagName("span").length == 0)
						createTiddlyElement(h,"span",null,"hidden",c.uarrow); 
					if(x==null && hasClass(h,"autosort")) {
						x = j;
						rev = hasClass(h,"reverse");
					}
				}
				if(x!=null)
					c.sortTable(headers[x],rev);		
			}
		}
	}
	return elem; 
};

setStylesheet("table.sortable span.hidden {visibility:hidden;}\n"+
	"table.sortable thead {cursor:pointer;}\n"+
	"table.sortable .nosort {cursor:default;}\n"+
	"table.sortable td.sortedCol {background:#ffc;}","TableSortingPluginStyles");

function stopEvent(e){
	var ev = e? e : window.event;
	ev.cancelBubble = true;
	if (ev.stopPropagation) ev.stopPropagation();
	return false;	
}	

config.macros.nosort={
	handler : function(place){
		addClass(place,"nosort");
	}	
};

config.macros.autosort={
	handler : function(place,m,p,w,pS){
		addClass(place,"autosort"+" "+pS);		
	}	
};
//!END-PLUGIN-CODE
// %/
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
|Version|1.6.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for specific tiddlers|
This plugin extends the core function, story.chooseTemplateForTiddler(), so that any given tiddler can be viewed and/or edited using alternatives to the standard tiddler templates.
!!!!!Documentation
>see [[TaggedTemplateTweakInfo]]
!!!!!Revisions
<<<
2009.09.02 [1.6.1] apply field-based template (if any) *before* tag-based template
| please see [[TaggedTemplateTweakInfo]] for previous revision details |
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TaggedTemplateTweak= {major: 1, minor: 6, revision: 1, date: new Date(2009,9,2)};

if (!config.options.txtTemplateTweakFieldname)	
	config.options.txtTemplateTweakFieldname='template';

Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
	// get core template and split into theme and template name
	var coreTemplate=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);
	var theme=""; var template=coreTemplate;
	var parts=template.split(config.textPrimitives.sectionSeparator);
	if (parts[1]) { theme=parts[0]; template=parts[1]; }
	else theme=config.options.txtTheme||""; // if theme is not specified
	theme+=config.textPrimitives.sectionSeparator;

	// look for template using title as prefix
	if (!store.getTaggedTiddlers(title).length) { // if tiddler is not a tag
		if (store.getTiddlerText(theme+title+template))
			{ return theme+title+template; } // theme##TitleTemplate
		if (store.getTiddlerText(title+template))
			{ return title+template; }	 // TitleTemplate
	}

	// look for templates using custom field value as prefix
	var v=store.getValue(title,config.options.txtTemplateTweakFieldname);
	if (store.getTiddlerText(theme+v+template))
		{ return theme+v+template; }	// theme##valueTemplate
	if (store.getTiddlerText(v+template))
		{ return v+template; }		// valueTemplate

	// look for template using tags as prefix
	var tiddler=store.getTiddler(title);
	if (!tiddler) return coreTemplate; // tiddler doesn't exist... use core result
	for (i=0; i<tiddler.tags.length; i++) {
		var t=tiddler.tags[i]+template; // add tag prefix to template
		var c=t.substr(0,1).toUpperCase()+t.substr(1); // capitalized for WikiWord title
		if (store.getTiddlerText(theme+t))	{ return theme+t; } // theme##tagTemplate
		if (store.getTiddlerText(theme+c))	{ return theme+c; } // theme##TagTemplate
		if (store.getTiddlerText(t)) 		{ return t; }	    // tagTemplate
		if (store.getTiddlerText(c))		{ return c; }	    // TagTemplate
	}
	
	// no match... use core result
	return coreTemplate;
}
//}}}
/***
|Name|TaggedTemplateTweakInfo|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
|Version|1.6.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for TaggedTemplateTweak|
This plugin extends the core function, story.chooseTemplateForTiddler(), so that any given tiddler can be viewed and/or edited using alternatives to the standard tiddler templates.  To select alternative templates, a 'template prefix' is determined by using the tiddler's title or matching a tag value or using a value stored in a custom tiddler field.  
!!!!!Usage
<<<
The plugin first attempts to use the tiddler's //title// as a prefix added to the standard TiddlyWiki template titles, [[ViewTemplate]] and [[EditTemplate]] (i.e., ''TiddlerNameViewTemplate'' and ''TiddlerNameEditTemplate'').  This allows you to associate a custom template with a specific tiddler, without needing to add any special tags or custom field values to that individual tiddler.  

You can also define a tiddler's template prefix by using a //custom tiddler field// named 'template'.  If no corresponding template was found using the tiddler's title, then the tiddler's 'template' field value, if present, will be used as a prefix (e.g., if template='SomeThing', then [[SomeThingViewTemplate]] will be applied).
*You can redefine the //name// of the custom field used to store the template prefix.  For example, to use the name of a TiddlyWeb server-side 'bag' as a prefix (so that tiddlers from separate bags can have different appearances), add the following to a tiddler tagged with<<tag systemConfig>>:

If no template is found using the either the title or 'template' field, then each of the tiddler's tags is tried as a template prefix, until a corresponding template, if any, is found.  For example, any tiddlers that are tagged with ''<<tag media>>'' could find alternative templates named [[mediaViewTemplate]] and [[mediaEditTemplate]].
*To permit use of templates that have proper WikiWord tiddler titles (e.g., [[MediaViewTemplate]] and [[MediaEditTemplate]]), the plugin also attempts to use a capitalized form of the tag value (e.g., ''Media'') as a prefix.  //This capitalization is for comparison purposes only and will not alter the actual tag values that are stored in the tiddler.//
*If you are applying a systemTheme definition, the plugin also tries prepending the currently selected theme (specified by {{{config.options.txtTheme}}}) plus the 'section separator' (##) to the template name (e.g. ''[[SomeTheme##MediaViewTemplate]]'') so that the alternative template definitions can be contained as //sections// within a single systemTheme tiddler.
{{{
config.options.txtTemplateTweakFieldname='server.bag'; // use TiddlyWeb bag name as prefix
}}}
Lastly, if no alternative template is found at all, the standard [[ViewTemplate]] or [[EditTemplate]] definition as determined by the TiddlyWiki core handler is used.

''To add your own custom templates:''
>First, decide upon a suitable tag keyword to uniquely identify your custom templates and create custom view and/or edit templates using that keyword as a prefix (e.g., "KeywordViewTemplate" and "KeywordEditTemplate").  Then, simply create a tiddler and tag it with your chosen keyword... that's it!  As long as the tiddler is tagged with your keyword, it will be displayed using the corresponding alternative templates.  If you remove the tag or rename/delete the alternative templates, the tiddler will revert to using the standard viewing and editing templates.
<<<
!!!!!Examples
<<<
|Sample tiddler| tag | view template | edit template |
|[[MediaSample - QuickTime]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[MediaSample - Windows]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[CDSample]]| <<tag CD>> | [[CDViewTemplate]] | [[CDEditTemplate]] |
|<<newTiddler label:"create new task..." title:SampleTask tag:task text:"Type some text and then press DONE to view the task controls">> | <<tag task>> | [[TaskViewTemplate]] | [[EditTemplate]] |

//(note: if these samples are not present in your document, please visit// http://www.TiddlyTools.com/ //to view these sample tiddlers on-line)//
<<<
!!!!!Revisions
<<<
2009.09.02 [1.6.1] apply field-based template (if any) *before* tag-based template
2009.07.31 [1.6.0] added support for using custom field value as prefix
2009.05.04 [1.5.2] check for tiddler exist *after* title-as-prefix (allows shadow tiddlers to use custom templates)
2009.01.06 [1.5.1] reversed logic so that title-as-prefix takes precedence over tag-matched prefix
2008.12.18 [1.5.0] added handling for using tiddler //title// as prefix (e.g., {{{SomeTiddlerViewTemplate}}}) 
2008.08.29 [1.4.1] corrected handling for tiddlers with no matching tagged template when non-default theme is in effect (e.g., use "MyTheme##ViewTemplate").
2008.05.15 [1.4.0] support use of *shadow* tagged templates (e.g., [[DiscussionViewTemplate]] created by [[DiscussionPlugin]])
2008.05.10 [1.3.0] corrected handling for determining core template when using theme with sections
2008.05.01 [1.2.5] added support for tagged templates stored as sections in a theme
2008.04.01 [1.2.0] added support for using systemTheme section-based template definitions (requested by Phil Hawksworth)
2008.01.22 [*.*.*] plugin size reduction - documentation moved to [[TaggedTemplateTweakInfo]]
2007.06.23 [1.1.0] re-written to use automatic 'tag prefix' search instead of hard coded check for each tag.  Allows new custom tags to be used without requiring code changes to this plugin.
2007.06.11 [1.0.0] initial release
<<<
This is a slightly more technical discussion of how tiddlers involved in a chapter are set up.

!! Chapter control tiddler
Every [[chapter control tiddler|Glossary/chapterControlTiddler]] must have @@chapter@@ as its first tag so that it is recognized (and properly displayed) as a control tiddler. The tag @@story@@ must also be included so the chapter can be displayed in the story column by selecting it from the drop down select box.

!! Content in a chapter
Every tiddler in a chapter must be tagged with content so that it will be exported to the student copy of the coursebook.

!! Preventing Tiddlers from Being Published
If any tiddler is tagged with ~InstructorOnly, it will not be published in the student coursebook.
This is a slightly more technical discussion of how tiddlers involved in a presentations are set up.

!! Presentation control tiddler
Every presentation control tiddler must have @@presentation@@ as its first tag so that it is recognized (and properly displayed) as a control tiddler.

!! A slide in a presentation
Every slide must have @@slide@@ as it's first tag so it is displayed as a slide during a presentation.

!! The second tag

In addition to the slide/presentation tags your tiddler must have one of:
;~InstructorOnly
:slide/presentation tiddler is never exported to the student coursebook
;content
: slide/presentation is exported to the student book (if ~InstructorOnly is not present)
to be properly published.

!! The third tag

Also you can append the @@story@@ tag to a presentation tiddler to allow the drop down selection box to open all the tiddlers in the presentation for quick review, editing or printing.
/***
|Name|TemporaryTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#TemporaryTiddlersPlugin|
|Version|1.1.2|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|SaverBase.prototype.externalize()|
|Options|##Configuration|
|Description|blocks tiddlers tagged with "temporary" from being saved into the TW file|
!!!!!Usage
<<<
When the TW document is saved (either to local disk or remote URL), any tiddlers tagged with "temporary" will be skipped over, so that they are not written to the file.  To keep a temporary tiddler, simply edit it and remove the tag before saving the file.  This feature can be combined with various plugins that can automatically create new tiddlers, such as [[SearchOptionsPlugin]] ([[SearchResults]]) and [[ImportTiddlersPlugin]] ([[ImportedTiddlers]]) so that these transient results are not retained when you save you document.

You can also use this tag with the {{{<<loadTiddlers>>}}} macro and the //auto-tagging// features provided by [[ImportTiddlersPlugin]], so that each time you open your document, you can automatically retrieve an up-to-date set of common tiddlers that are stored in another document (either local or via remote URL), without those tiddlers being retained when you save your document.
<<<
!!!!!Configuration
<<<
When saving the document:
<<option chkTemporaryQuiet>> Suppress reporting of individual temporary tiddlers that have not been saved
<<option chkTemporaryKeep>> Keep temporary tiddlers (i.e., ignore the 'temporary' tag)
Enter a tag value to use when marking tiddlers as temporary: <<option txtTemporaryTag>>
<<<
!!!!!Revisions
<<<
2008.11.14 [1.1.2] added "nnn temporary tiddlers not saved" summary message
2008.04.08 [1.1.1] don't automatically add configuration options to AdvancedOptions tiddler
2008.03.01 [1.1.0] added support for recognizing 'temporary' flag stored as a tiddler *field* (as an optional alternative to using a tag)
2007.02.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TemporaryTiddlersPlugin= {major: 1, minor: 1, revision: 2, date: new Date(2008,11,14)};

// configuration defaults
if (config.options.chkTemporaryKeep ==undefined) config.options.chkTemporaryKeep =false;
if (config.options.chkTemporaryQuiet==undefined) config.options.chkTemporaryQuiet=true;
if (config.options.txtTemporaryTag==undefined) config.options.txtTemporaryTag="temporary";
// lingo
config.messages.TemporaryWarning = "'%0' ...temporary tiddler";
config.messages.TemporarySummary = "%0 temporary tiddlers will not be saved";
// core override
SaverBase.prototype.externalize = function(store) 
{
	var results=[]; var totaltemps=0;
	var tiddlers=store.getTiddlers("title");
	for (var t=0; t<tiddlers.length; t++) {
		if (config.options.chkTemporaryKeep||!(tiddlers[t].fields['temporary']||tiddlers[t].isTagged(config.options.txtTemporaryTag)))
			results.push(this.externalizeTiddler(store, tiddlers[t]));
		else {
			if (!config.options.chkTemporaryQuiet) // notify user that tiddler won't be saved
				displayMessage(config.messages.TemporaryWarning.format([tiddlers[t].title]));
			totaltemps++;
		}
	}
	if (totaltemps) displayMessage(config.messages.TemporarySummary.format([totaltemps]));
	return results.join("\n");
}
//}}}
<<tabs tabID
"Tab A" "tooltip A" [[TestOpenOtherTab##ContentsA]]
"Tab B" "tooltip B" TestOpenOtherTab##ContentsB
"Tab C" "tooltip C" TestOpenOtherTab##ContentsC 
>>
/%
!ContentsA
Consider this format for display of some information.
E.G. multiple examples, glossary popdowns ... However printing all tabs is a problem.

See [[orig thread|http://groups.google.com/group/TiddlyWiki/browse_thread/thread/4f7b952f69b523a2?pli=1]]
and [[Azlandela|http://groups.google.dk/group/tiddlywiki/browse_thread/thread/bbb7a36edea4b6e7?hl=da]]
<html><a href='javascript:;' onclick='config.options.tabID="Tab B"; story.refreshTiddler("TestOpenOtherTab", null, true) '>link</a></html> to Tab B <html><a href='javascript:;' onclick='config.options.tabID="Tab C";
story.refreshTiddler("TestOpenOtherTab", null, true) '>link</a></html> to Tab C 
!ContentsB
<html><a href='javascript:;' onclick='config.options.tabID="Tab A"; story.refreshTiddler("TestOpenOtherTab", null, true) '>link</a></html> to Tab A <html><a href='javascript:;' onclick='config.options.tabID="Tab C"; story.refreshTiddler("TestOpenOtherTab", null, true) '>link</a></html> to Tab C 
!ContentsC 
<html><a href='javascript:;' onclick='config.options.tabID="Tab A";
story.refreshTiddler("TestOpenOtherTab", null, true) '>link</a></html> to Tab A <html><a href='javascript:;' onclick='config.options.tabID="Tab B"; story.refreshTiddler("TestOpenOtherTab", null, true) '>link</a></html> to Tab B 
!end
%/
<<tiddler SlideSubstyle##levelOne with: url("textbooks.gif")>> 

{{comment{
* Provide a standard textbook serial learning mechanism
**  Story (aka chapter) is a series of tiddlers presented serially at one shot.
* ~Non-Linear textbook
**  search is a must have. Search by tiddler title, content or tags.  Return tiddlers w/ hits like google.
}}}
<<tiddler SlideSubstyle##levelTwo>>
{{adiv{
@@font-size:x-large;text-align:center;margin-left:auto;margin-right:auto;FINI@@
}}}
<<tiddler Welcome/tiddlerclass >>
{{comment{
There are also structural and operational tiddlers that provide major portions of coursebook functionality, set the display styles etc. Consider these fixed content that you don't have to worry about. They just sort of hang out in the background.
}}}
/***
|''Name:''|TiddlerNotesPlugin|
|''Description:''|Add notes to tiddlers without modifying the original content|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#TiddlerNotesPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.1|
|''Date:''|26/10/07|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|

!!Concept:
*The TiddlerNotesPlugin allows you to add notes to tiddlers, without needing to edit the original tiddler. This means that your original content will remain unaltered, and if you update it in the future, you won’t lose your notes. Notes are stored in separate tiddlers, but can be viewed and edited from within the original tiddler.
*For a tiddler titled "~MySlide", the notes are by default saved in a tiddler titled "~MySlide-Notes" and is given a tag of "Notes". The suffix and tags of the notes tiddlers are customizable. You can have one or multiple notes per tiddlers. So it is possible to have for example, teacher's notes and student's notes in the same file.
*Notes can be configured to start off blank, or pre-filled with the contents of the original tiddler.

!!Usage:
*{{{<<notes>>}}} is the simplest usage form.
* additional optional parameters include:
**{{{heading:}}} the heading to use for the notes box
**{{{tag:}}} the tag to be given to the notes tiddler
**{{{suffix:}}} the suffix to be used when naming the notes tiddler
* a full macro call could look like: {{{<<notes heading:"My Notes" tag:"NoteTiddlers" suffix:"Comments">>}}}
* To avoid adding {{{<<notes>>}}} to each tiddler you want notes for, you could add the macro call to the ViewTemplate
** below the line {{{<div class='viewer' macro='view text wikified'></div>}}} add the following line: <br> {{{<div class='viewer' macro='notes'></div>}}}
** Used in combination with the ~HideWhenPlugin or ~PublisherPlugin, you could have notes be shown only for tiddlers with specific tags. The ~PublisherPlugin would allow you for instance to only have the ~TeachersNotes visible to the teacher, and the ~StudentsNotes for the same tiddler visible to the Student.

!!Configuration
*<<option chkPrefillNotes>> Enable to pre-fill notes with the original tiddler's contents

!!Demo:
* [[MySlide]]

***/
// /%
//!BEGIN-PLUGIN-CODE

if (!config.options.chkPrefillNotes)
	config.options.chkPrefillNotes = false;
	
function createTiddlyElement(theParent,theElement,theID,theClass,theText,attribs)
{
	var e = document.createElement(theElement);
	if(theClass != null)
		e.className = theClass;
	if(theID != null)
		e.setAttribute("id",theID);
	if(theText != null)
		e.appendChild(document.createTextNode(theText));
	if(attribs){
		for(var n in attribs){
			e.setAttribute(n,attribs[n]);
		}
	}
	if(theParent != null)
		theParent.appendChild(e);
	return e;
}

function createTiddlyButton(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey,attribs)
{
	var theButton = document.createElement("a");
	if(theAction) {
		theButton.onclick = theAction;
		theButton.setAttribute("href","javascript:;");
	}
	if(theTooltip)
		theButton.setAttribute("title",theTooltip);
	if(theText)
		theButton.appendChild(document.createTextNode(theText));
	if(theClass)
		theButton.className = theClass;
	else
		theButton.className = "button";
	if(theId)
		theButton.id = theId;
	if(attribs){
		for(var n in attribs){
			theButton.setAttribute(n,attribs[n]);
		}
	}
	if(theParent)
		theParent.appendChild(theButton);
	if(theAccessKey)
		theButton.setAttribute("accessKey",theAccessKey);
	return theButton;
}

config.macros.notes={
	
	cancelWarning: "Are you sure you want to abandon changes to your notes for '%0'?",
	editLabel: "edit notes",
	editTitle: "double click to edit",
	saveLabel: "save notes",
	saveTitle: "double click to save",
	cancelLabel: "cancel",
	heading: "Notes",
	suffix: "Notes",
	tag: "Notes",
	
	saveNotes: function(ev){
		e = ev? ev : window.event;
		var theTarget = resolveTarget(e);
		if (theTarget.nodeName.toLowerCase() == "textarea")
			return false;
		var title = story.findContainingTiddler(theTarget).getAttribute("tiddler");
		story.setDirty(title,false);
		var box = document.getElementById("notesContainer"+title);
		var textarea = document.getElementById("notesTextArea"+title);
		if(textarea.getAttribute("oldText")!=textarea.value && !hasClass(theTarget,"cancelNotesButton")){
			var suffix = box.getAttribute("suffix");
			var t = store.getTiddler(title+"-"+suffix);
			store.saveTiddler(title+"-"+suffix,title+"-"+suffix,textarea.value,config.options.txtUserName,new Date(),t?t.tags:box.getAttribute("tag"),t?t.fields:{});
		}
		story.refreshTiddler(title,1,true);
		autoSaveChanges(true);
		return false;
	},
	
	editNotes: function(box,tiddler){
		removeChildren(box);
		story.setDirty(tiddler,true);
		box.title = this.saveTitle;
		box.ondblclick = this.saveNotes;
		createTiddlyButton(box,this.cancelLabel,this.cancelLabel,this.saveNotes,"cancelNotesButton");
		createTiddlyButton(box,this.saveLabel,this.saveLabel,this.saveNotes,"saveNotesButton");
		wikify("!!"+box.getAttribute("heading")+"\n",box);
		addClass(box,"editor");
		var wrapper1 = createTiddlyElement(null,"fieldset",null,"fieldsetFix");
		var wrapper2 = createTiddlyElement(wrapper1,"div");
		var e = createTiddlyElement(wrapper2,"textarea","notesTextArea"+tiddler);
		var v = store.getValue(tiddler+"-"+box.getAttribute("suffix"),"text");
		if(!v) 
			v = config.options.chkPrefillNotes? store.getValue(tiddler,"text"):'';
		e.value = v;
		e.setAttribute("oldText",v);
		var rows = 10;
		var lines = v.match(/\n/mg);
		var maxLines = Math.max(parseInt(config.options.txtMaxEditRows),5);
		if(lines != null && lines.length > rows)
			rows = lines.length + 5;
		rows = Math.min(rows,maxLines);
		e.setAttribute("rows",rows);
		box.appendChild(wrapper1);
	},
	
	editNotesButtonOnclick: function(e){
		var title = story.findContainingTiddler(this).getAttribute("tiddler");
		var box = document.getElementById("notesContainer"+title);
		config.macros.notes.editNotes(box,title);
		return false;
	},
	
	ondblclick : function(ev){
		e = ev? ev : window.event;
		var theTarget = resolveTarget(e);
		var title = story.findContainingTiddler(theTarget).getAttribute("tiddler");
		var box = document.getElementById("notesContainer"+title);
		config.macros.notes.editNotes(box,title);
		e.cancelBubble = true;
		if(e.stopPropagation) e.stopPropagation();
		return false;
	},
	
	handler : function(place,macroName,params,wikifier,paramString,tiddler){
		
		params = paramString.parseParams("anon",null,true,false,false);
		var heading = getParam(params,"heading",this.heading);
		var tag = getParam(params,"tag",this.tag);
		var suffix = getParam(params,"suffix",this.suffix);
                // rouilj add a class for notes that have contents in a tiddler.
                var notesTiddlerExists = store.tiddlerExists(tiddler.title+"-"+suffix);
		var box = createTiddlyElement(place,"div","notesContainer"+tiddler.title,"TiddlerNotes"  + (notesTiddlerExists?" TiddlerNotesExists":""),null,{"source":tiddler.title,params:paramString,heading:heading,tag:tag,suffix:suffix});
		// var box = createTiddlyElement(place,"div","notesContainer"+tiddler.title,"TiddlerNotes",null,{"source":tiddler.title,params:paramString,heading:heading,tag:tag,suffix:suffix});
		createTiddlyButton(box,this.editLabel,this.editLabel,this.editNotesButtonOnclick,"editNotesButton");
		wikify("!!"+heading+"\n",box);
		box.title=this.editTitle;
		box.ondblclick = this.ondblclick;
		wikify("<<tiddler [["+tiddler.title+"-"+suffix+"]]>>",box);
	}		
};

Story.prototype.old_notes_closeTiddler = Story.prototype.closeTiddler;
Story.prototype.closeTiddler = function(title,animate,unused){
	if(story.isDirty(title)) {
            if(!confirm(config.macros.notes.cancelWarning.format([title])))
    		    return false;
         }
	return this.old_notes_closeTiddler.apply(this,arguments);
}

setStylesheet(".TiddlerNotes {\n"+ " background:#eee;\n"+ " border:1px solid #ccc;\n"+ " padding:10px;\n"+ " margin:15px;\n"+ "}\n"+ "\n"+ ".cancelNotesButton,.editNotesButton, .saveNotesButton {\n"+ " float:right;\n"+ " border:1px solid #ccc;\n"+ " padding:2px 5px;\n"+ "}\n"+ "\n"+ ".saveNotesButton{\n"+ " margin-right:0.5em;\n"+ "}\n"+ "\n"+ ".TiddlerNotes.editor textarea{\n"+ " border:1px solid #ccc;\n"+ "}","NotesPluginStyles");
//!END-PLUGIN-CODE
// %/
/***
|Name|TiddlerTweakerPlugin|
|Source|http://www.TiddlyTools.com/#TiddlerTweakerPlugin|
|Version|2.4.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|select multiple tiddlers and modify author, created, modified and/or tag values|
~TiddlerTweaker is a 'power tool' for TiddlyWiki authors.  Select multiple tiddlers from a listbox and 'bulk modify' the creator, author, created, modified and/or tag values of those tiddlers using a compact set of form fields.  The values you enter into the fields simultaneously overwrite the existing values in all tiddlers you have selected.
!!!!!Usage
<<<
{{{<<tiddlerTweaker>>}}}
{{smallform{<<tiddlerTweaker>>}}}
By default, any tags you enter into the TiddlerTweaker will //replace// the existing tags in all the tiddlers you have selected.  However, you can also use TiddlerTweaker to quickly filter specified tags from the selected tiddlers, while leaving any other tags assigned to those tiddlers unchanged:
>Any tag preceded by a '+' (plus) or '-' (minus), will be added or removed from the existing tags //instead of replacing the entire tag definition// of each tiddler (e.g., enter '-excludeLists' to remove that tag from all selected tiddlers.  When using this syntax, care should be taken to ensure that //every// tag is preceded by '+' or '-', to avoid inadvertently overwriting any other existing tags on the selected tiddlers.  (note: the '+' or '-' prefix on each tag value is NOT part of the tag value, and is only used by TiddlerTweaker to control how that tag value is processed)
Important Notes:
* TiddlerTweaker is a 'power user' tool that can make changes to many tiddlers at once.  ''You should always have a recent backup of your document (or 'save changes' just *before* tweaking the tiddlers), just in case you accidentally 'shoot yourself in the foot'.''
* The date and author information on any tiddlers you tweak will ONLY be updated if the corresponding checkboxes have been selected.  As a general rule, after using TiddlerTweaker, always ''//remember to save your document//'' when you are done, even though the tiddler timeline tab may not show any recently modified tiddlers.
* Selecting and updating all tiddlers in a document can take a while.  Your browser may warn about an 'unresponsive script'.  Usually, if you allow it to continue, it should complete the processing... eventually.  Nonetheless, be sure to save your work before you begin tweaking lots of tiddlers, just in case something does get stuck.
<<<
!!!!!Revisions
<<<
2009.09.15 2.4.4 added 'edit' button. moved html definition to separate section
2009.09.13 2.4.3 in settiddlers(), convert backslashed chars (\n\b\s\t) in replacement text
2009.06.26 2.4.2 only add brackets around tags containing spaces
2009.06.22 2.4.1 in setFields(), add brackets around all tags shown tweaker edit field
2009.03.30 2.4.0 added 'sort by modifier'
2009.01.22 2.3.0 added support for text pattern find/replace
2008.10.27 2.2.3 in setTiddlers(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
2008.09.07 2.2.2 added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.05.12 2.2.1 replace built-in backstage tweak task with tiddler tweaker control panel (moved from BackstageTweaks)
2008.01.13 2.2.0 added 'auto-selection' links: all, changed, tags, title, text
2007.12.26 2.1.0 added support for managing 'creator' custom field (see [[CoreTweaks]])
2007.11.01 2.0.3 added config.options.txtTweakerSortBy for cookie-based persistence of list display order preference setting.
2007.09.28 2.0.2 in settiddlers() and deltiddlers(), added suspend/resume notification handling (improves performance when operating on multiple tiddlers)
2007.08.03 2.0.1 added shadow definition for [[TiddlerTweaker]] tiddler for use as parameter references with {{{<<tiddler>>, <<slider>> or <<tabs>>}}} macros.
2007.08.03 2.0.0 converted from inline script
2006.01.01 1.0.0 initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TiddlerTweakerPlugin= {major: 2, minor: 4, revision: 4, date: new Date(2009,9,15)};

// shadow tiddler
config.shadowTiddlers.TiddlerTweaker='<<tiddlerTweaker>>';

// defaults
if (config.options.txtTweakerSortBy==undefined) config.options.txtTweakerSortBy='modified';

// backstage task
if (config.tasks) { // for TW2.2b3 or above
	config.tasks.tweak.tooltip='review/modify tiddler internals: dates, authors, tags, etc.';
	config.tasks.tweak.content='{{smallform small groupbox{<<tiddlerTweaker>>}}}';
}

// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
	window.removeCookie=function(name) {
		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;'; 
	}
}

config.macros.tiddlerTweaker = {
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var span=createTiddlyElement(place,'span');
		span.innerHTML=store.getTiddlerText('TiddlerTweakerPlugin##html');
		this.init(span.getElementsByTagName('form')[0],config.options.txtTweakerSortBy);
	},
	init: function(f,sortby) { // initialize form controls
		if (!f) return; // form might not be rendered yet...
		while (f.list.options[0]) f.list.options[0]=null; // empty current list content
		var tids=store.getTiddlers(sortby);
		if (sortby=='size') // descending order
			tids.sort(function(a,b) {return a.text.length > b.text.length ? -1 : (a.text.length == b.text.length ? 0 : +1);});
		var who='';
		for (i=0; i<tids.length; i++) { var t=tids[i];
			var label=t.title; var value=t.title;
			switch (sortby) {
				case 'modified':
				case 'created':
					var t=tids[tids.length-i-1]; // reverse order
					var when=t[sortby].formatString('YY.0MM.0DD 0hh:0mm ');
					label=when+t.title;
					value=t.title;
					break;
				case 'size':
					label='['+t.text.length+'] '+label;
					break;
				case 'modifier':
				case 'creator':
					if (who!=t[sortby]) {
						who=t[sortby];
						f.list.options[f.list.length]=new Option('by '+who+':','',false,false);
					}
					label='\xa0\xa0\xa0'+label; // indent
					break;
			}
			f.list.options[f.list.length]=new Option(label,value,false,false);
		}
		f.title.value=f.who.value=f.creator.value=f.tags.value='';
		f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value='';
		f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value='';
		f.stats.disabled=f.set.disabled=f.del.disabled=f.edit.disabled=f.display.disabled=true;
		f.settitle.disabled=false;
		config.options.txtTweakerSortBy=sortby;
		f.sortby.value=sortby; // sync droplist
		if (sortby!='modified') saveOptionCookie('txtTweakerSortBy');
		else removeCookie('txtTweakerSortBy');
	},
	selecttiddlers: function(here) { // enables/disables inputs based on #items selected
		var f=here.form; var list=f.list;
		var c=0; for (i=0;i<list.length;i++) if (list.options[i].selected) c++;
		if (c>1) f.title.disabled=true;
		if (c>1) f.settitle.checked=false;
		f.set.disabled=(c==0);
		f.del.disabled=(c==0);
		f.edit.disabled=(c==0);
		f.display.disabled=(c==0);
		f.settitle.disabled=(c>1);
		f.stats.disabled=(c==0);
		var msg=(c==0)?'select tiddlers':(c+' tiddler'+(c!=1?'s':'')+' selected');
		here.previousSibling.firstChild.firstChild.nextSibling.innerHTML=msg;
		if (c) clearMessage(); else displayMessage('no tiddlers selected');
	},
	setfields: function(here) { // set fields from first selected tiddler
		var f=here.form;
		if (!here.value.length) {
			f.title.value=f.who.value=f.creator.value=f.tags.value='';
			f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value='';
			f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value='';
			return;
		}
		var tid=store.getTiddler(here.value); if (!tid) return;
		f.title.value=tid.title;
		f.who.value=tid.modifier;
		f.creator.value=tid.fields['creator']||''; // custom field - might not exist
		f.tags.value=tid.tags.map(function(t){return String.encodeTiddlyLink(t)}).join(' ');
		var c=tid.created; var m=tid.modified;
		f.cm.value=c.getMonth()+1;
		f.cd.value=c.getDate();
		f.cy.value=c.getFullYear();
		f.ch.value=c.getHours();
		f.cn.value=c.getMinutes();
		f.mm.value=m.getMonth()+1;
		f.md.value=m.getDate();
		f.my.value=m.getFullYear();
		f.mh.value=m.getHours();
		f.mn.value=m.getMinutes();
	},
	settiddlers: function(here) {
		var f=here.form; var list=f.list;
		var tids=[];
		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert('please select at least one tiddler'); return; }
		var cdate=new Date(f.cy.value,f.cm.value-1,f.cd.value,f.ch.value,f.cn.value);
		var mdate=new Date(f.my.value,f.mm.value-1,f.md.value,f.mh.value,f.mn.value);
		if (tids.length>1 && !confirm('Are you sure you want to update these tiddlers:\n\n'+tids.join(', '))) return;
		store.suspendNotifications();
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			var title=!f.settitle.checked?tid.title:f.title.value;
			var who=!f.setwho.checked?tid.modifier:f.who.value;
			var text=tid.text;
			if (f.replacetext.checked) {
				var r=f.replacement.value.replace(/\\t/mg,'\t').unescapeLineBreaks();
				text=text.replace(new RegExp(f.pattern.value,'mg'),r);
			}				
			var tags=tid.tags;
			if (f.settags.checked) { 
				var intags=f.tags.value.readBracketedList();
				var addtags=[]; var deltags=[]; var reptags=[];
				for (i=0;i<intags.length;i++) {
					if (intags[i].substr(0,1)=='+')
						addtags.push(intags[i].substr(1));
					else if (intags[i].substr(0,1)=='-')
						deltags.push(intags[i].substr(1));
					else
						reptags.push(intags[i]);
				}
				if (reptags.length)
					tags=reptags;
				if (addtags.length)
					tags=new Array().concat(tags,addtags);
				if (deltags.length)
					for (i=0;i<deltags.length;i++)
						{ var pos=tags.indexOf(deltags[i]); if (pos!=-1) tags.splice(pos,1); }
			}
			if (!f.setcdate.checked) cdate=tid.created;
			if (!f.setmdate.checked) mdate=tid.modified;
			store.saveTiddler(tid.title,title,text,who,mdate,tags,tid.fields);
			if (f.setcreator.checked) store.setValue(tid.title,'creator',f.creator.value); // set creator
			if (f.setcdate.checked) tid.assign(null,null,null,null,null,cdate); // set create date
		}
		store.resumeNotifications();
		this.init(f,f.sortby.value);
	},
	displaytiddlers: function(here,edit) {
		var f=here.form; var list=f.list;
		var tids=[];
		for (i=0; i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert('please select at least one tiddler'); return; }
		story.displayTiddlers(story.findContainingTiddler(f),tids,edit?DEFAULT_EDIT_TEMPLATE:null);
	},
	deltiddlers: function(here) {
		var f=here.form; var list=f.list;
		var tids=[];
		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert('please select at least one tiddler'); return; }
		if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
		store.suspendNotifications();
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			if (tid.tags.contains('systemConfig')) {
				var msg=tid.title+' is tagged with systemConfig.'
					+'\n\nRemoving this tiddler may cause unexpected results.  Are you sure?';
				if (!confirm(msg)) continue;
			}
			store.removeTiddler(tid.title);
			story.closeTiddler(tid.title);
		}
		store.resumeNotifications();
		this.init(f,f.sortby.value);
	},
	stats: function(here) {
		var f=here.form; var list=f.list; var tids=[]; var out=''; var tot=0;
		var target=f.nextSibling;
		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert('please select at least one tiddler'); return; }
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			out+='[['+tid.title+']] '+tid.text.length+'\n'; tot+=tid.text.length;
		}
		var avg=tot/tids.length;
		out=tot+' bytes in '+tids.length+' selected tiddlers ('+avg+' bytes/tiddler)\n<<<\n'+out+'<<<\n';
		removeChildren(target);
		target.innerHTML="<hr><font size=-2><a href='javascript:;' style='float:right' "
			+"onclick='this.parentNode.parentNode.style.display=\"none\"'>close</a></font>";
		wikify(out,target);
		target.style.display='block';
	}
};
//}}}
/***
//{{{
!html
<style>
.tiddlerTweaker table,
.tiddlerTweaker table tr,
.tiddlerTweaker table td
	{ padding:0;margin:0;border:0;white-space:nowrap; }
</style><form class='tiddlerTweaker'><!--
--><table style="width:100%"><tr valign="top"><!--
--><td style="text-align:center;width:99%;"><!--
	--><font size=-2><div style="text-align:left;"><span style="float:right"><!--
	-->&nbsp; <a href="javascript:;" 
		title="select all tiddlers"
		onclick="
		var f=this; while (f&&f.nodeName.toLowerCase()!='form')f=f.parentNode;
		for (var t=0; t<f.list.options.length; t++)
			if (f.list.options[t].value.length) f.list.options[t].selected=true;
		config.macros.tiddlerTweaker.selecttiddlers(f.list);
		return false">all</a><!--
	-->&nbsp; <a href="javascript:;" 
		title="select tiddlers that are new/changed since the last file save"
		onclick="
		var lastmod=new Date(document.lastModified);
		var f=this; while (f&&f.nodeName.toLowerCase()!='form')f=f.parentNode;
		for (var t=0; t<f.list.options.length; t++) {
			var tid=store.getTiddler(f.list.options[t].value);
			f.list.options[t].selected=tid&&tid.modified>lastmod;
		}
		config.macros.tiddlerTweaker.selecttiddlers(f.list);
		return false">changed</a><!--
	-->&nbsp; <a href="javascript:;" 
		title="select tiddlers with at least one matching tag"
		onclick="
		var t=prompt('Enter space-separated tags (match ONE)');
		if (!t||!t.length) return false;
		var tags=t.readBracketedList();
		var f=this; while (f&&f.nodeName.toLowerCase()!='form')f=f.parentNode;
		for (var t=0; t<f.list.options.length; t++) {
			f.list.options[t].selected=false;
			var tid=store.getTiddler(f.list.options[t].value);
			if (tid&&tid.tags.containsAny(tags)) f.list.options[t].selected=true;
		}
		config.macros.tiddlerTweaker.selecttiddlers(f.list);
		return false">tags</a><!--
	-->&nbsp; <a href="javascript:;" 
		title="select tiddlers whose titles include matching text"
		onclick="
		var txt=prompt('Enter a title (or portion of a title) to match');
		if (!txt||!txt.length) return false;
		var f=this; while (f&&f.nodeName.toLowerCase()!='form')f=f.parentNode;
		for (var t=0; t<f.list.options.length; t++) {
			f.list.options[t].selected=f.list.options[t].value.indexOf(txt)!=-1;
		}
		config.macros.tiddlerTweaker.selecttiddlers(f.list);
		return false">titles</a><!--
	-->&nbsp; <a href="javascript:;" 
		title="select tiddlers containing matching text"
		onclick="
		var txt=prompt('Enter tiddler text (content) to match');
		if (!txt||!txt.length) return false;
		var f=this; while (f&&f.nodeName.toLowerCase()!='form')f=f.parentNode;
		for (var t=0; t<f.list.options.length; t++) {
			var tt=store.getTiddlerText(f.list.options[t].value,'');
			f.list.options[t].selected=(tt.indexOf(txt)!=-1);
		}
		config.macros.tiddlerTweaker.selecttiddlers(f.list);
		return false">text</a> &nbsp;<!--
	--></span><span>select tiddlers</span><!--
	--></div><!--
	--></font><select multiple name=list size="11" style="width:99.99%" 
		title="use click, shift-click and/or ctrl-click to select multiple tiddler titles" 
		onclick="config.macros.tiddlerTweaker.selecttiddlers(this)" 
		onchange="config.macros.tiddlerTweaker.setfields(this)"><!--
	--></select><br><!--
	-->show<input type=text size=1 value="11" 
		onchange="this.form.list.size=this.value; this.form.list.multiple=(this.value>1);"><!--
	-->by<!--
	--><select name=sortby size=1 
		onchange="config.macros.tiddlerTweaker.init(this.form,this.value)"><!--
	--><option value="title">title</option><!--
	--><option value="size">size</option><!--
	--><option value="modified">modified</option><!--
	--><option value="created">created</option><!--
	--><option value="modifier">modifier</option><!--
	--></select><!--
	--><input type="button" value="refresh" 
		onclick="config.macros.tiddlerTweaker.init(this.form,this.form.sortby.value)"<!--
	--> <input type="button" name="stats" disabled value="totals..." 
		onclick="config.macros.tiddlerTweaker.stats(this)"><!--
--></td><td style="width:1%"><!--
	--><div style="text-align:left"><font size=-2>&nbsp;modify values</font></div><!--
	--><table style="width:100%;"><tr><!--
	--><td style="padding:1px"><!--
		--><input type=checkbox name=settitle unchecked 
			title="allow changes to tiddler title (rename tiddler)" 
			onclick="this.form.title.disabled=!this.checked">title<!--
	--></td><td style="padding:1px"><!--
		--><input type=text name=title size=35 style="width:98%" disabled><!--
	--></td></tr><tr><td style="padding:1px"><!--
		--><input type=checkbox name=setcreator unchecked 
			title="allow changes to tiddler creator" 
			onclick="this.form.creator.disabled=!this.checked">created by<!--
	--></td><td style="padding:1px;"><!--
		--><input type=text name=creator size=35 style="width:98%" disabled><!--
	--></td></tr><tr><td style="padding:1px"><!--
		--><input type=checkbox name=setwho unchecked 
			title="allow changes to tiddler author" 
			onclick="this.form.who.disabled=!this.checked">modified by<!--
	--></td><td style="padding:1px"><!--
		--><input type=text name=who size=35 style="width:98%" disabled><!--
	--></td></tr><tr><td style="padding:1px"><!--
		--><input type=checkbox name=setcdate unchecked 
			title="allow changes to created date" 
			onclick="var f=this.form;
				f.cm.disabled=f.cd.disabled=f.cy.disabled=f.ch.disabled=f.cn.disabled=!this.checked"><!--
		-->created on<!--
	--></td><td style="padding:1px"><!--
		--><input type=text name=cm size=2 style="width:2em;padding:0;text-align:center" disabled><!--
		--> / <input type=text name=cd size=2 style="width:2em;padding:0;text-align:center" disabled><!--
		--> / <input type=text name=cy size=4 style="width:3em;padding:0;text-align:center" disabled><!--
		--> at <input type=text name=ch size=2 style="width:2em;padding:0;text-align:center" disabled><!--
		--> : <input type=text name=cn size=2 style="width:2em;padding:0;text-align:center" disabled><!--
	--></td></tr><tr><td style="padding:1px"><!--
		--><input type=checkbox name=setmdate unchecked 
			title="allow changes to modified date" 
			onclick="var f=this.form;
				f.mm.disabled=f.md.disabled=f.my.disabled=f.mh.disabled=f.mn.disabled=!this.checked"><!--
		-->modified on<!--
	--></td><td style="padding:1px"><!--
		--><input type=text name=mm size=2 style="width:2em;padding:0;text-align:center" disabled><!--
		--> / <input type=text name=md size=2 style="width:2em;padding:0;text-align:center" disabled><!--
		--> / <input type=text name=my size=4 style="width:3em;padding:0;text-align:center" disabled><!--
		--> at <input type=text name=mh size=2 style="width:2em;padding:0;text-align:center" disabled><!--
		--> : <input type=text name=mn size=2 style="width:2em;padding:0;text-align:center" disabled><!--
	--></td></tr><tr><td style="padding:1px"><!--
		--><input type=checkbox name=replacetext unchecked
			title="find/replace matching text" 
			onclick="this.form.pattern.disabled=this.form.replacement.disabled=!this.checked">replace text<!--
	--></td><td style="padding:1px"><!--
		--><input type=text name=pattern size=15 value="" style="width:40%" disabled 
			title="enter TEXT PATTERN (regular expression)"> with<!--
		--><input type=text name=replacement size=15 value="" style="width:40%" disabled 
			title="enter REPLACEMENT TEXT"><!--
	--></td></tr><tr><td style="padding:1px"><!--
		--><input type=checkbox name=settags checked 
			title="allow changes to tiddler tags" 
			onclick="this.form.tags.disabled=!this.checked">tags<!--
	--></td><td style="padding:1px"><!--
		--><input type=text name=tags size=35 value="" style="width:98%" 
			title="enter new tags or use '+tag' and '-tag' to add/remove tags from existing tags"><!--
	--></td></tr></table><!--
	--><div style="text-align:center"><!--
	--><nobr><input type=button name=display disabled style="width:24%" value="display" 
		title="show selected tiddlers"
		onclick="config.macros.tiddlerTweaker.displaytiddlers(this,false)"><!--
	--> <input type=button name=edit disabled style="width:23%" value="edit" 
		title="edit selected tiddlers"
		onclick="config.macros.tiddlerTweaker.displaytiddlers(this,true)"><!--
	--> <input type=button name=del disabled style="width:24%" value="delete" 
		title="remove selected tiddlers"
		onclick="config.macros.tiddlerTweaker.deltiddlers(this)"><!--
	--> <input type=button name=set disabled style="width:24%" value="update" 
		title="update selected tiddlers"
		onclick="config.macros.tiddlerTweaker.settiddlers(this)"></nobr><!--
	--></div><!--
--></td></tr></table><!--
--></form><span style="display:none"><!--content replaced by tiddler "stats"--></span>
!end
//}}}
***/
 
/***
|Name|TiddlyLockPlugin|
|Source|http://www.minormania.com/tiddlylock/tiddlylock.html|
|Version|1.2|
|Author|Richard Hobbis|
|License|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|Type|plugin|
|Overrides|config.macros.newTiddler.onClickNewTiddler()<br>config.commands.cancelTiddler.handler()<br>config.commands.deleteTiddler.handler<br>config.commands.editTiddler.handler()<br>config.commands.saveTiddler.handler()<br>saveChanges()<br>checkUnsavedChanges()|
|Description|Automatically locks and unlocks the TiddlyWiki as required, allowing multiple users to edit the TiddlyWiki without fear of overwriting other users' changes.|
!!!Usage
<<<
Simply import TiddlyLockPlugin into your TiddlyWiki!
<<<
!!!Installation
<<<
Import (or copy/paste) ''this tiddler'' into your TiddlyWiki and make sure it's tagged with <<tag systemConfig>>. Reload your TiddlyWiki to enable TiddlyLock.
<<<
!!!Configuration
<<<
None required!
<<<
!!!Revision History
<<<
''2010.07.06 [1.2.0]'' Allow the location of the Lock File to be specified by the user, instead of defaulting to the location of the TiddlyWiki file. The default location is the same folder as the TiddlyWiki file itself, however this can be changed by editing ''//this html file//'' in a text editor and search for {{{TiddlyLock.LockPath = '';}}} The folder will be created if it doesn't exist.
''2010.07.06 [1.2.0]'' Upgraded this TiddlyWiki to core version 2.6
''2008.05.15 [1.1.0]'' Upgraded source TiddlyWiki to use core version 2.4. Tested and verified TiddlyLock under version 2.4.
''2007.06.22 [1.0.4]'' Added locking on 'new tiddler' which also traps 'new journal'. Tweaked messages.
''2007.06.20 [1.0.3]'' Fixed an issue that occurred when a user navigated away from the TiddlyWiki without saving outstanding changes.
''2007.05.10 [1.0.2]'' Implemented a timestamp to track the last update time. This fixes the multi-browser edit issue and also removes the need for a password.
''2007.05.08 [1.0.1]'' Function overrides are now done using apply() ensuring clean upgrades (thanks Martin!)
''2007.05.01 [1.0.0]'' Initial Release
<<<
!!!Known Issues
<<<
*Monkey Pirate TiddlyWiki (MPTW) adds a ''disable'' button to the toolbar for systemConfig tiddlers. This button is available even when the TW is marked as readOnly and therefore it's possible for two users to disable/enable plugins at the same time. In this case, whoever saves the TW last will 'win' and their changes will be saved. Note that this is only an issue if there are no other unsaved changes in both browsers - TiddlyLock still handles all other changes.
<<<
!!!Credits
<<<
This feature was developed by Richard Hobbis (rhobbis [at] hotmail [dot] com).
<<<
!!!Code
***/

//{{{
// Convert a date to UTC YYYYMMDDHHMMSSMMM string format
// This is the same as the builtin function convertToYYYYMMDDHHMMSSMMM() but
// without the '.' in the middle - this allows simple date comparisons
Date.prototype.TLConvertToYYYYMMDDHHMMSSMMM = function()
{
  return(String.zeroPad(this.getUTCFullYear(),4)
    + String.zeroPad(this.getUTCMonth()+1,2)
    + String.zeroPad(this.getUTCDate(),2)
    + String.zeroPad(this.getUTCHours(),2)
    + String.zeroPad(this.getUTCMinutes(),2)
    + String.zeroPad(this.getUTCSeconds(),2)
    + String.zeroPad(this.getUTCMilliseconds(),4));
}

// namespace for TiddlyLock
TiddlyLock = {};

// Load/Last Update timestamp
TiddlyLock.TimeStamp = new Date().TLConvertToYYYYMMDDHHMMSSMMM();

// Lockfile
TiddlyLock.LockPath = ''; // custom values *must* include trailing '\\'
TiddlyLock.OldLockData = '';
TiddlyLock.LockData = '';
TiddlyLock.LockFile = TLLockPath();
// define messages
TiddlyLock.Msg = {
  Locked: 'File locked',
  Unlocked: 'File unlocked',
  LockFailed: 'Failed to lock file',
  UnlockFailed: 'Failed to unlock file',
  ReadOnly: 'Now in Read-Only mode.',
  Changed: 'This file has been changed by someone else.',
  Reload: 'Reload this file before editing.'};

// create/update the lock file
function TLSave(timeStamp,lockedBy)
{
  var lockedText='';
  if (lockedBy!='')
  {
    lockedText=timeStamp+'##'+lockedBy;
  }
  else lockedText=timeStamp+'##';
    var lockSave=saveFile(TiddlyLock.LockFile,lockedText);
  TiddlyLock.TimeStamp = timeStamp;
  return false;
}


// Create/update the lock file to prevent other users from editing the TW
function TLLock()
{
  clearMessage();
  lockSave = TLSave(new Date().TLConvertToYYYYMMDDHHMMSSMMM(),config.options.txtUserName);
  displayMessage(TiddlyLock.Msg.Locked,'');
  return false;
}


// Clear the lock file if necessary, but only if I have it locked, setting the
// timestamp in the lockfile to the specified value
function TLUnlock(timeStamp)
{
  if ((store && store.isDirty && !store.isDirty())
    && (story && story.areAnyDirty && !story.areAnyDirty())
    && TLIsLocked()
    && TLIsLockedByMe())
  {
    lockSave=TLSave(timeStamp,'','');
    displayMessage(TiddlyLock.Msg.Unlocked,'');
    TiddlyLock.OldLockData = TiddlyLock.LockData;
  }
  return false;
}

// Get the contents of the lock file, if it exists
function TLLockPath()
{
  var lockPath,pathRoot,p,fileName;
  var fullPath=document.location.toString();
  if(TiddlyLock.LockPath!='') pathRoot=TiddlyLock.LockPath; // location of lock file is defined by TiddlyLock.LockPath
  else pathRoot=getLocalPath(fullPath); // location of lock file is derived from the wiki filename
  if((p=pathRoot.lastIndexOf('\\'))!=-1) pathRoot=pathRoot.substr(0,p+1); // truncate any trailing filename (derived paths only)
  fileName=getLocalPath(fullPath); // full wiki file name, including path
  if((p=fileName.lastIndexOf('\\'))!=-1) fileName=fileName.substr(p+1); // truncate everything up to the last slash
  if((p=fileName.lastIndexOf('.'))!=-1) fileName=fileName.substr(0,p); // remove any existing extension
  fileName=fileName+'.lck'; // add new extension
  return pathRoot+fileName;
}

// Get the contents of the lock file, if it exists
function TLLockData()
{
  return loadFile(TiddlyLock.LockFile);
}

// Get the contents of the lock file, if it exists
function TLIsLocked()
{
  TiddlyLock.LockData = TLLockData();
  if (TiddlyLock.LockData
      && ( TLLockedBy(TiddlyLock.LockData)!='' // someone has it locked
         || TiddlyLock.TimeStamp < TLLockedTimeStamp(TiddlyLock.LockData) // changed by someone else but not currently locked
         )
     )
    return true;
  else
    return false;
}


// check if locked by me
function TLIsLockedByMe()
{
  if(TiddlyLock.LockData == TiddlyLock.TimeStamp+'##' + config.options.txtUserName)
    return true;
  else
    return false;
}


// returns just the timestamp portion of the supplied lock file contents
function TLLockedTimeStamp(lockData)
{
  if(lockData)
    return lockData.split('##')[0];
  else
    return '';
}


// returns just the username portion of the supplied lock file contents
function TLLockedBy(lockData)
{
  if(lockData)
    return lockData.split('##')[1];
  else
    return '';
}

// display a message if locked or changed
function TLChangesAllowed()
{
  if(TLIsLocked() && !TLIsLockedByMe())
  {
    readOnly=true;
    if(TLLockedBy(TiddlyLock.LockData))
    {
      displayMessage(TiddlyLock.Msg.Locked+' by '+TLLockedBy(TiddlyLock.LockData));
      alert(TiddlyLock.Msg.Locked+' by '+TLLockedBy(TiddlyLock.LockData)+'. '+TiddlyLock.Msg.ReadOnly);
    }
    else
    {
      displayMessage(TiddlyLock.Msg.Changed+' '+TiddlyLock.Msg.Reload);
      alert(TiddlyLock.Msg.Changed+' '+TiddlyLock.Msg.Reload);
    }
    return false;
  }
  else
    return true;
}


//*********************************************
// OVERRIDE STANDARD FUNCTIONS
//*********************************************

//
// OVERRIDE onClickNewTiddler()
//
TiddlyLock.onClickNewTiddler = config.macros.newTiddler.onClickNewTiddler;
config.macros.newTiddler.onClickNewTiddler = function(event,src,title)
{
  if (TLChangesAllowed())
  {
    TiddlyLock.OldLockData = TiddlyLock.LockData;
    TLLock();
    var ret = TiddlyLock.onClickNewTiddler.apply(this,arguments);
    return ret;
  }
}

//
// OVERRIDE checkUnsavedChanges()
//
TiddlyLock.checkUnsavedChanges = checkUnsavedChanges;
checkUnsavedChanges = function(event,src,title)
{
  var ret = TiddlyLock.checkUnsavedChanges.apply(this,arguments);
  if(TLIsLocked() && TLIsLockedByMe())
    lockSave=TLSave(TLLockedTimeStamp(TiddlyLock.OldLockData),'','');
  return ret;
}


//
// OVERRIDE cancelTiddler()
//
TiddlyLock.cancelTiddler = config.commands.cancelTiddler.handler;
config.commands.cancelTiddler.handler = function(event,src,title)
{
  var ret = TiddlyLock.cancelTiddler.apply(this,arguments);
  TLUnlock(TLLockedTimeStamp(TiddlyLock.OldLockData));
  return ret;
}

//
// OVERRIDE deleteTiddler()
//
TiddlyLock.deleteTiddler = config.commands.deleteTiddler.handler;
config.commands.deleteTiddler.handler = function(event,src,title)
{
  if (TLChangesAllowed())
  {
    TiddlyLock.OldLockData = TiddlyLock.LockData;
    TLLock();
    var ret = TiddlyLock.deleteTiddler.apply(this,arguments);
    return ret;
  }
}

//
// OVERRIDE editTiddler()
//
TiddlyLock.editTiddler = config.commands.editTiddler.handler;
config.commands.editTiddler.handler = function(event,src,title)
{
  if (TLChangesAllowed())
  {
    TiddlyLock.OldLockData = TiddlyLock.LockData;
    TLLock();
  }
  var ret = TiddlyLock.editTiddler.apply(this,arguments);
  return ret;
}

//
// OVERRIDE saveChanges()
//
TiddlyLock.saveChanges = saveChanges;
saveChanges = function(onlyIfDirty)
{
  if(TLChangesAllowed())
  {
    var ret = TiddlyLock.saveChanges.apply(this,arguments);
    TLUnlock(new Date().TLConvertToYYYYMMDDHHMMSSMMM());
    return ret;
  }
  else
    return false;
}

//
// OVERRIDE saveTiddler()
//
TiddlyLock.saveTiddler= config.commands.saveTiddler.handler;
config.commands.saveTiddler.handler=function(event,src,title)
{
  var ret = TiddlyLock.saveTiddler.apply(this,arguments);
  TLUnlock(new Date().TLConvertToYYYYMMDDHHMMSSMMM());
  return ret;
}

//}}}
<<tiddler Glossary/tiddlyWiki>> See http://www.tiddlywiki.org.
This page includes instructor only info for the [[Reference Appendix 1 - TiddlyWiki Page Layout]] content tiddler.

!mainMenu

All of the links above are present in both the instructor and student coursebooks. The following links are present only in the instructor coursebook and are supplied by the inclusion of the InstructorMainMenu tiddler (which is intentionally missing from the student coursebook).
;Toggle Fullscreen
:This goes one step further and makes the main menu, side bar and title disappear so the story column take over the entire display. When activated a small button at the top right of the page allows you to switch back into normal display mode.
;Defined Tags
:When clicked on this pops up a list of the important tags for tiddlers to make the coursebook work.
;[[Bugs And Feature Requests]]
:This is a place to see what is on the todo list for the coursebook. If you want to add your own, I suggest creating new tiddlers say LocalBugsFeatures and adding: {{{<<tiddler LocalBugsFeatures>>}}} to the bottom of the [[Bugs And Feature Requests]] tiddler. This way you can sync against a new version of the coursebook and not lose your local modifications.
;[[Content Bugs]]
:The bugs and features request relates to issues with the courebook itself, that is the html and javascript code and key structure tiddlers that make the coursebook work. In comparison, this tiddler records issues with the content: missing tiddlers, missing images sections that need to be added to a tiddler etc.

!newTiddlers

The following entries are only present in the instructor version of the coursebook. They are defined in a hidden section of the [[InstructorSidebarFunctions|InstructorSidebarFunctions##newTiddlers]] that is intentionally not exported to the student coursebook.
;new chapter tiddler
:creates a new [[chapter control tiddler|Glossary/chapterControlTiddler]] with a template for the title and appropriate tags.
;new content tiddler
:creates a new tiddler tagged with {{{content}}}.
;new presentation tiddler
:creates a new [[presentation control tiddler|Glossary/presentationControlTiddler]] with a template for the title and appropriate tags.
;new slide tiddler
:creates a new tiddler meant to be used as a slide in a presentation with appropriate tags.

! saveChanges
Using the Tweak tool in the [[backstage|Using the Backstage Link]] menu will not modify the state of the tiddlers, but it will change them, so using this link is the proper way to save the changes.
! instructorMenu
; instructor »
:<<tiddler [[ReadMe##Publishing for Students and others.]]>>
!end
/%
!info
|Name|ToggleFullScreen|
|Source|http://www.TiddlyTools.com/#ToggleFullScreen|
|Version|2.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|Create a link that shows/hides sidebars and page headers|
Usage
<<<
{{{
<<tiddler ToggleFullScreen>>
<<tiddler ToggleFullScreen with: label altlabel>>
}}}
<<<
Example
<<<
{{{<<tiddler ToggleFullScreen with: fullscreen restore>>}}}
<<tiddler ToggleFullScreen##show with: fullscreen restore>>
<<<
!end

!show
<html><nowiki><a href='javascript:;' title="FULLSCREEN: toggle sidebars and page header"
onmouseover="
	this.href='javascript:void(eval(decodeURIComponent(%22(function(){try{('
	+encodeURIComponent(encodeURIComponent(this.onclick))
	+')()}catch(e){alert(e.description?e.description:e.toString())}})()%22)))';"
onclick="
	var co=config.options;
	co.chkFullScreen=!co.chkFullScreen;
	var showmm=!co.chkFullScreen && co.chkShowLeftSidebar!==false;
	var showsb=!co.chkFullScreen && co.chkShowRightSidebar!==false;
	var showcrumbs=!co.chkFullScreen && co.chkShowBreadcrumbs!==false
		&& config.macros.breadcrumbs && config.macros.breadcrumbs.crumbs.length;
	var cw=document.getElementById('contentWrapper');
	var da=document.getElementById('displayArea');
	var mm=document.getElementById('mainMenu');
	var sb=document.getElementById('sidebar');
	var sm=document.getElementById('storyMenu');
	var bc=document.getElementById('breadCrumbs');
	if (cw){
		var elems=cw.getElementsByTagName('*');
		for (var i=0; i<elems.length; i++) if (hasClass(elems[i],'header')) 
			{ elems[i].style.display=co.chkFullScreen?'none':'block'; break; }
	}
	if (mm) {
		mm.style.display=showmm?'block':'none';
		da.style.marginLeft=showmm?(co.txtDisplayAreaLeftMargin||''):'1em';
	}
	if (sb) {
		sb.style.display=showsb?'block':'none';
		da.style.marginRight=showsb?(co.txtDisplayAreaRightMargin||''):'1em';
	}
	if (sm) sm.style.display=!co.chkFullScreen ?'block':'none';
	if (bc) bc.style.display=showcrumbs?'block':'none';

	this.innerHTML=!co.chkFullScreen?'$1':'$2';
	var b=document.getElementById('restoreFromFullscreenButton');
	if (b) removeNode(b);
	else { 
		setStylesheet(store.getTiddlerText('ToggleFullScreen##styles'),'fullScreenStyles');
		var b=createTiddlyElement(null,'span','restoreFromFullscreenButton','selected');
		b.innerHTML='&loz;';
		b.title='RESTORE: redisplay page header, menu and sidebar';
		b.onclick=this.onclick;
		document.body.insertBefore(b,null);
	}
	return false;
">$1</a></html>
!styles
#restoreFromFullscreenButton {
	position:fixed; top:.3em; right:.3em; z-index:10001;
	cursor:pointer; font-size:8pt; color:ButtonText !important;
	border:2px outset ButtonFace; padding:0px 3px;
	background-color:ButtonFace; -moz-appearance:button;
}
!end
%/<<tiddler {{var src='ToggleFullScreen'; src+(tiddler&&tiddler.title==src?'##info':'##show');}}
with:	{{'$'+'1'!='$1'?'$1':'fullscreen'}}
	{{'$'+'2'!='$2'?'$2':'restore'}}>>
/***

|Name|ToggleSideBarMacro|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#ToggleSideBarMacro|
|Version|1.0|
|Requires|~TW2.x|
!Description:
Provides a button for toggling visibility of the SideBar. You can choose whether the SideBar should initially be hidden or displayed.

!Demo
<<toggleSideBar "Toggle Sidebar">>

!Usage:
{{{<<toggleSideBar>>}}} <<toggleSideBar>>
additional options:
{{{<<toggleSideBar label tooltip show/hide>>}}} where:
label = custom label for the button,
tooltip = custom tooltip for the button,
show/hide = use one or the other, determines whether the sidebar is shown at first or not.
(default is to show the sidebar)

You can add it to your tiddler toolbar, your MainMenu, or where you like really.
If you are using a horizontal MainMenu and want the button to be right aligned, put the following in your StyleSheet:
{{{ .HideSideBarButton {float:right;} }}}

!History
*23-07-06: version 1.0: completely rewritten, now works with custom stylesheets too, and easier to customize start behaviour. 
*20-07-06: version 0.11
*27-04-06: version 0.1: working.

!Code
***/
//{{{
config.macros.toggleSideBar={};

config.macros.toggleSideBar.settings={
         styleHide :  "#sidebar { display: none;}\n"+"#contentWrapper #displayArea { margin-right: 1em;}\n"+"",
         styleShow : " ",
         arrow1: "«",
         arrow2: "»"
};

config.macros.toggleSideBar.handler=function (place,macroName,params,wikifier,paramString,tiddler)
{
          var tooltip= params[1]||'toggle sidebar';
          var mode = (params[2] && params[2]=="hide")? "hide":"show";
          var arrow = (mode == "hide")? this.settings.arrow1:this.settings.arrow2;
          var label= (params[0]&&params[0]!='.')?params[0]+" "+arrow:arrow;
          var theBtn = createTiddlyButton(place,label,tooltip,this.onToggleSideBar,"button HideSideBarButton");
          if (mode == "hide")
             { 
             (document.getElementById("sidebar")).setAttribute("toggle","hide");
              setStylesheet(this.settings.styleHide,"ToggleSideBarStyles");
             }
};

config.macros.toggleSideBar.onToggleSideBar = function(){
          var sidebar = document.getElementById("sidebar");
          var settings = config.macros.toggleSideBar.settings;
          if (sidebar.getAttribute("toggle")=='hide')
             {
              setStylesheet(settings.styleShow,"ToggleSideBarStyles");
              sidebar.setAttribute("toggle","show");
              this.firstChild.data= (this.firstChild.data).replace(settings.arrow1,settings.arrow2);
              }
          else
              {    
               setStylesheet(settings.styleHide,"ToggleSideBarStyles");
               sidebar.setAttribute("toggle","hide");
               this.firstChild.data= (this.firstChild.data).replace(settings.arrow2,settings.arrow1);
              }

     return false;
}

setStylesheet(".HideSideBarButton .button {font-weight:bold; padding: 0 5px;}\n","ToggleSideBarButtonStyles");

//}}}
|~ViewToolbar|closeTiddler closeOthers +editTiddler deleteTiddler > fields syncing permalink references revisions jump|
|~EditToolbar|+saveTiddler -cancelTiddler copyTiddler deleteTiddler|
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{

// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'coursebook';

// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too

// disable autosave in d3
if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false;

// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}

// create some shadow tiddler content
merge(config.shadowTiddlers,{

'TspotOptions':[
 "tiddlyspot password:",
 "<<option pasUploadPassword>>",
 ""
].join("\n"),

'TspotControls':[
 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),

'WelcomeToTiddlyspot':[
 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),

'TspotSidebar':[
 "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n")

});
//}}}
You can create two types of presentations:
# Single tiddler presentations
# Multi-tiddler presentations

!! Single Tiddler Presentations
As the name "Single tiddler" implies, the presentation tiddler is divided into multiple segments and each segment is displayed as a slide in the presentation. This method has a few advantages:
* editing is easier as only one tiddler need to be modified,
* useful for "administrative presentations". For example:
** a looping slide show at the beginning of a class welcoming the students and displaying info they need to know about the class. 
** a looping slide show during a class break with a countdown timer till class resumes.
However it comes with some drawbacks:
* Slide titles are generic ~TempSlide1, ~TempSlide2 etc. So you have to use a style/theme that doesn't display the tiddler title.
* Students can't annotate a slide as there is no actual tiddler associated with each slide.
* You have to hide certain control elements when using a single tiddler, but these elements aren't hidden if exported to the student copy.

!! Multi-tiddler Presentations
As the name "Multi-tiddler" implies, a single tiddler links to multiple slide tiddlers and each slide tiddler is displayed as a slide in the presentation. This method has a few advantages:
* Student's can't annotate single tiddler shows as there is no actual tiddler associated with each slide.
* The tiddler title is used as a slide title to provide a useful description of the slide content.
* A single tiddler can be used in multiple presentations
However it comes with some drawbacks:
* Revising multiple slides requires editing multiple tiddlers. (If you are doing text substitution consider using the TiddlerTweakerPlugin to do batch editing of content.)
* More tiddlers makes tiddlywiki somewhat slower
* The addition of slide tiddlers can make it more difficult to find the specific tiddler you are interested in.
/***
|Name|UnsavedChangesPlugin|
|Source|http://www.TiddlyTools.com/#UnsavedChangesPlugin|
|Version|3.3.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|TiddlyWiki.prototype.setDirty,store.saveTiddler,store.removeTiddler|
|Description|show droplist of tiddlers that have changed since the last time the document was saved|
Display a list of tiddlers that have been changed since the last time the document was saved.  The list includes all new/modified tiddlers as well as those changed with "minor edits" enabled and any tiddlers that you import during the session, regardless of their modification date.
!!!!!Usage
<<<
{{{
<<unsavedChanges panel>> or <<unsavedChanges>>
}}}
{{indent{
the ''panel'' keyword displays a 'control panel' interface containing a droplist of unsaved tiddlers and a 'goto' button, along with a command link to 'save changes'.  Depending upon what other plugins are installed, several additional elements will also be displayed: When [[NestedSlidersPlugin]] is installed, the entire control panel is contained within a ''SLIDER''.  When [[LoadTiddlersPlugin]] is installed, a ''REVERT'' button is added.  When [[SaveAsPlugin]] is installed, a ''SAVE AS'' link is added.  When [[UploadPlugin]] is installed, an ''UPLOAD'' (or ''save to web'') link is added.  When [[TrashPlugin]] is installed and there are tiddlers tagged with<<tag Trash>>, an ''EMPTY TRASH'' link is added.
}}}
{{{
<<unsavedChanges list separator>>
}}}
{{indent{
the ''list'' keyword displays a simple space-separated list of unsaved tiddlers without any other command links.  You can specify an optional ''separator'' value that can be used in place of the default space character.  For example, you can specify {{{"<br>"}}} as the separator in order to display each link, one per line.
}}}
{{{
<<unsavedChanges command label tip>>
}}}
{{indent{
the ''command'' keyword displays a single 'command link' that, when clicked, displays a ~TiddlyWiki popup containing the list of unsaved tiddlers, the 'save changes' command and, depending upon what other plugins are installed, additional commands for 'save as', 'upload', and 'empty trash' (similar to the panel display described above).

You can specify optional ''label'' and ''tip'' parameters in the macro to customize the command link text and tooltip.  The default label for the command link is: "There %1 %0 unsaved tiddler%2...", where:
* %0 is automatically replaced with the number of unsaved changes
* %1 is either "is" (if changes=1) or "are" (if changes>1)
* %2 is either blank (if changes=1) or "s" (if changes>1)
resulting in the text: //"There is 1 unsaved tiddler...", "There are 2 unsaved tiddlers...", etc.//
}}}
<<<
!!!!!Examples
<<<
^^//note: the following examples will not display any output unless you have already created/modified tiddlers in the current document.//^^
{{{<<unsavedChanges>>}}}
<<unsavedChanges>>
----
{{{<<unsavedChanges command>>}}}
<<unsavedChanges command>>
----
{{{<<unsavedChanges list>>}}}
<<unsavedChanges list>>
----
{{{<<unsavedChanges list "<br>">>}}}
<<unsavedChanges list "<br>">>
<<<
!!!!!Revisions
<<<
2009.03.02 [3.3.3] fix handling for titles that contain HTML special chars (lt,gt,quot,amp)
2008.09.02 [3.3.2] cleanup popup list output generation and added timestamps/sizes to popup display
2008.08.23 [3.3.1] added optional custom 'label' and 'tip' params to 'command' mode and defined default values for mode, label, tip, and separator as object properties for I18N/L10N-readiness.
2008.08.21 [3.3.0] complete re-write of rendering and refresh processing to support multiple instances and automatic self-refresh (no longer depends upon core refresh notifications)
2008.08.21 [3.2.0] added 'command' option for link+popup as alternative to 'control panel' interface
2008.04.22 [3.1.2] use SaveAsPlugin instead of obsolete NewDocumentPlugin to add "save as" link
2007.12.22 [3.1.1] hijack removeTiddler() instead of low-level deleteTiddler() to correct tracking and refresh handling issues.  in saveTiddler(), check for 'tiddler rename' (title!=newtitle) and adjust list accordingly.
2007.12.21 [3.1.0] added support for {{{<<unsavedChanges list separator>>}}} usage to unsaved tiddlers as a simple list of links, embedded in tiddler content (e.g., [[MainMenu]])
2007.12.20 [3.0.0] rewrite to track ALL changed tiddlers, including imports and minor edits, regardless of saved modification dates.  Also, rewrote display logic to directly refresh macro output instead of triggering a page refresh.  The entire process is MUCH more efficient now.
2007.08.02 [2.0.0] converted from inline script
2007.01.01 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.UnsavedChangesPlugin= {major: 3, minor: 3, revision: 3, date: new Date(2009,3,2)};

config.macros.unsavedChanges = {
	changed: [], // list of currently unsaved tiddler titles
	defMode: "panel",
	defSep: " ",
	defLabel: "There %1 %0 unsaved tiddler%2...",
	defTip: "view a list of unsaved tiddler changes",
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var wrapper=createTiddlyElement(place,"span",null,"unsavedChanges");
		wrapper.setAttribute("mode",params[0]||this.defMode);
		wrapper.setAttribute("sep",params[1]||this.defSep); // for 'list' mode
		wrapper.setAttribute("label",params[1]||this.defLabel); // for 'command' mode
		wrapper.setAttribute("tip",params[2]||this.defTip); // for 'command' mode
		this.render(wrapper);
	},
	render: function(wrapper) {
		removeChildren(wrapper); // make sure its empty
		if (!this.changed.length) return; // no changes = no output
		switch (wrapper.getAttribute("mode")) {
			case "command": this.command(wrapper); break;
			case "list": this.list(wrapper); break;
			case "panel": default: this.panel(wrapper); break;
		}
	},
	refresh: function() {
		var wrappers=document.getElementsByTagName("span");
		for (var w=0; w<wrappers.length; w++)
			if (hasClass(wrappers[w],"unsavedChanges"))
				this.render(wrappers[w]);
	},
	list: function(place) { // show simple list of unsaved tiddlers
		wikify("[["+this.changed.join("]]"+place.getAttribute("sep")+"[[")+"]]",place);
	},
	command: function(place) { // show command link with popup list
		var c=this.changed.length;
		var txt=place.getAttribute("label").format([c,c==1?'is':'are',c==1?'':'s']);
		var tip=place.getAttribute("tip");
		var action=function(ev) { if (!ev) var ev=window.event;
			var p=Popup.create(this); if (!p) return false;
			var d=createTiddlyElement(p,"div");
			d.style.whiteSpace="normal"; d.style.width="auto"; d.style.padding="2px";
			// gather pretty links for changed tiddlers
			var list=[]; var item=" &nbsp;[[%1 - %0 (%2 bytes)|%0]]&nbsp; ";
			for (var i=config.macros.unsavedChanges.changed.length-1; i>=0; i--) {
				var tid=store.getTiddler(config.macros.unsavedChanges.changed[i]);
				if (!tid) continue;
				var when=tid.modified.formatString('YYYY.0MM.0DD 0hh:0mm:0ss');
				list.push(item.format([tid.title,when,tid.text.length]));
			}
			wikify("@@white-space:nowrap;"+list.join("<br>")+"@@",d);
			if (!readOnly) {
				var t="\n----\n";
				t+="@@white-space:nowrap;display:block;text-align:center; &nbsp;";
				t+="<<saveChanges>>";
				t+=config.macros.saveAs?" | <<saveAs>>":"";
				t+=config.macros.upload?" | <<upload>>":"";
				t+=(config.macros.emptyTrash&&store.getTaggedTiddlers("Trash").length)?" | <<emptyTrash>>":"";
				t+="&nbsp; @@";
				wikify(t,d);
			}
			Popup.show();
			ev.cancelBubble=true; if(ev.stopPropagation)ev.stopPropagation();
			return(false);
		}
		createTiddlyButton(place,txt,tip,action,"button");
	},
	panel: function(place) { // show composite droplist+buttons+commands
		// gather changed tiddlers (in reverse order by date - most recent first)
		var tids=[]; for (var i=this.changed.length-1; i>=0; i--)
			{ var t=store.getTiddler(this.changed[i]); if (t) tids.push(t); }
		tids.sort(function(a,b){return a.modified<b.modified?-1:(a.modified==b.modified?0:1);});
		// generate droplist items
 		var list=[]; var item='<option value="%0">%1 - %0 (%2 bytes)</option>';
		for (var i=tids.length-1; i>=0; i--) {
			var when=tids[i].modified.formatString('YYYY.0MM.0DD 0hh:0mm:0ss');
			list.push(item.format([tids[i].title.htmlEncode(),when,tids[i].text.length]));
		}
		// display droplist, buttons, and command links
		var out=''; var c=this.changed.length;
		var NSP=config.formatters.findByField("name","nestedSliders");
		var summary=this.defLabel.format([c,c==1?'is':'are',c==1?'':'s'])
		out+=NSP?'+++(unsaved)['+summary+'|'+this.defTip+']...':(summary+"\n");
		out+='<html><form style="display:inline"><!--\
			--><select size="1" name="list" \
				title="select a tiddler to view" \
				onchange="var v=this.value; if (v.length) story.displayTiddler(null,v);"><!--\
			-->'+list.join('')+'<!--\
			--></select><!--\
			--><input type="button" value="goto" onclick="this.form.list.onchange();">';
		if (config.macros.loadTiddlers)  {
			out+='<input type="button" value="revert" \
				title="import the last saved version of this tiddler" \
				onclick="var v=this.form.list.value; if (!v.length) return; \
					var t=\'<\'+\'<loadTiddlers [[tiddler:\'+v+\']] \'; \
					t+=document.location.href; \
					t+=\' confirm force noreport>\'+\'>\'; \
					var e=document.getElementById(\'executeRevert\'); \
					if (e) e.parentNode.removeChild(e); \
					e=document.createElement(\'span\'); \
					e.id=\'executeRevert\'; \
					wikify(t,e);">';
		}
		out+='</form></html>';
		if (!readOnly) {
			out+='\n{{small nowrap{';
			out+="<<saveChanges>>";
			out+=config.macros.saveAs?" | <<saveAs>>":"";
			out+=config.macros.upload?" | <<upload>>":"";
			out+=(config.macros.emptyTrash&&store.getTaggedTiddlers("Trash").length)?" | <<emptyTrash>>":"";
			out+='}}}';
		}
		out+=NSP?'===':'';
		wikify(out,place);
	}
};

// hijack store.saveTiddler() to track changes to tiddlers
if (store.showUnsaved_saveTiddler==undefined) {
	store.showUnsaved_saveTiddler=store.saveTiddler;
	store.saveTiddler=function(title,newtitle) {
		if (title!=newtitle) {
			var i=config.macros.unsavedChanges.changed.indexOf(title);
			if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove old from list
		} 
		var i=config.macros.unsavedChanges.changed.indexOf(newtitle);
		if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove new title from list
		config.macros.unsavedChanges.changed.push(newtitle); // add new title to END of list
		var t=this.showUnsaved_saveTiddler.apply(this,arguments);
		if (!this.notificationLevel) config.macros.unsavedChanges.refresh();
		return t;
	}
}

// hijack store.removeTiddler() to track changes to tiddlers
if (store.showUnsaved_removeTiddler==undefined) {
	store.showUnsaved_removeTiddler=store.removeTiddler;
	store.removeTiddler=function(title) {
		var i=config.macros.unsavedChanges.changed.indexOf(title);
		if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove from list
		this.showUnsaved_removeTiddler.apply(this,arguments);
		if (!this.notificationLevel) config.macros.unsavedChanges.refresh();
	}
}

// hijack store.setDirty() function to reset change list after file save
// note: do NOT hijack the prototype function.  This hijack should only be applied to
// the main 'store' instance only (i.e., don't refresh when loading temporary store
// as part of ImportTiddlers processing)
if (store.showUnsaved_setDirty==undefined) {
	store.showUnsaved_setDirty=store.setDirty;
	store.setDirty = function(flag) {
		var refresh=this.isDirty() && !flag; // 'dirty' to 'clean', force a refresh...
		this.showUnsaved_setDirty.apply(this,arguments); // but change the flag first.
		if (refresh) {
			config.macros.unsavedChanges.changed=[]; // clear changed list
			config.macros.unsavedChanges.refresh();
		}
	}
}
//}}}
After your coursebook is open, please update your coursebook:
# Go to the "sync" tiddler (all lower case) by typing ''sync'' into the Goto box on the top right and hitting enter.
# Click on the @@Import new content from <<tiddler [[GettingStarted::courseHomeContent]]>>@@ button (this usually takes 15-30 seconds to complete).
# You should see it import some tiddlers.
# Save the coursebook ''using the @@save changes@@ link in the right hand column''. You ''MUST NOT'' use the save menu item in your browser, it will break the coursebook.
# Refresh/reopen the coursebook
# Your coursebook is ready for class
/% these overlays keep the instructions on screen longer %/
{{overlay1{}}}
{{overlay2{}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 31/07/2010 02:58:18 | JohnRouillard | [[coursebook_spot.html|file:///C:/Documents%20and%20Settings/rouilj/My%20Documents/coursebook/coursebook_spot.html]] | [[store.cgi|http://coursebook.tiddlyspot.com/store.cgi]] | . | [[index.html | http://coursebook.tiddlyspot.com/index.html]] | . | ok |
| 31/07/2010 03:29:43 | JohnRouillard | [[coursebook_spot.html|file:///C:/Documents%20and%20Settings/rouilj/My%20Documents/coursebook/coursebook_spot.html]] | [[store.cgi|http://coursebook.tiddlyspot.com/store.cgi]] | . | [[index.html | http://coursebook.tiddlyspot.com/index.html]] | . |
| 08/08/2010 15:29:37 | JohnRouillard | [[tscoursebook.html|file:///C:/Users/rouilj/Downloads/tscoursebook.html]] | [[store.cgi|http://coursebook.tiddlyspot.com/store.cgi]] | . | [[index.html | http://coursebook.tiddlyspot.com/index.html]] | . |
| 08/08/2010 15:32:05 | JohnRouillard | [[tscoursebook.html|file:///C:/Users/rouilj/Downloads/tscoursebook.html]] | [[store.cgi|http://coursebook.tiddlyspot.com/store.cgi]] | . | [[index.html | http://coursebook.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 3,
	date: new Date("Feb 24, 2008"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

//
// Environment
//

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

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

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

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

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

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

//
// uploadOptions Macro
//

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

//
// upload functions
//

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

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

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

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

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

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

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

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

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

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

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

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

//
// Utilities
// 

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

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

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

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

//
// Initializations
//

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

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

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

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


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


//}}}

! Chapters are listed in the MainMenu
* A  chapter is composed of multiple tiddlers.
* A pulldown listing of all the chapters is provided in the MainMenu
* Viewing options allow you to replace the story column with the chapter or add it to the open tiddlers.
* Use the index of open tiddlers at the top of the story column to skip to a section
* Alternatively use a tiddler's more/jump menu item to jump to a specific open tiddler
* A notebook is provided after each tiddler
{{comment{
There are two mechanisms for accessing chapters:
# A pull down menu
# A traditional set of links to the "control topic"/table of contents (TOC) for the chapter

The pull down menu allows you to control where the tiddlers making up the chapter are opened:
* At the beginning of the story column
* At the end of the story column
* Replacing the story column (closing all tiddlers open for viewing)

The traditional set of links allows users with browsers that cut off the chapter titles to navigate the chapters.
If you click on a link to go to the chapter "control topic" tiddler, a button at the bottom along with some check boxes will allow you to open the chapter similar to the pull down mechanism.
}}}
Notebook blocks are:
* placed at the end of each content tiddler
* colored gray
* edited with doubleclick or {{{edit notes}}} button
* saved by clicking on {{{save notes}}}
{{comment{
Save your notes before moving on to the next slide when in slide view mode.
If you don't the notes and it's tiddler will still be shown when you move to the next slide.
}}}
The left hand menu contains the presentations:
* Click on the link to display the control tiddler for the show.
* Start the show use the Student button at the top of the control tiddler
* Take notes using the notes block (don't forget to save)
* Use the navigation controls at the top right to: move forward [>], move back [<], exit [x], jump to a slide (click on slide number and select).<br /><br />
* Print the slide show (including instructor but not student notes) use the Print button at the top of the control tiddler. (Press any key to exit print mode.)

{{comment{
The print mode does not show the student's notes. To print the slides and student notes, open the slides in the story column using the drop down select box at the top of the presentation list in the MainMenu, then use the browsers print function.}}}
! Using this Tiddlywiki
For those of you who are used to tiddlywiki's this one has a few changes. It is based on version <<version>> of tiddlywiki with a number of plugins and customizations. The most obvious of these changes is the inability to edit tiddlers tagged with {{{content}}} by double clicking on them. As a result you can use double or triple clicks to select text from content tiddlers for pasting in the notebook or elsewhere. Because content tiddlers can be updated from the instructors copy (deleting your changes) of the coursebook, it is not recommended that you edit content tiddlers using the edit menu item.You must use the edit menu to edit content tiddlers. This prevents inadvertent changes that will be destroyed on your next synchronization from the source. Use the notebook block to record your changes/notes.

!! Editing Notebook
You will see below every content tiddler a notebook tiddler block. Double click on the gray notes block, or use the edit notes button to add your own notes and observations to the content tiddler. The notes are not overwritten by a [[sync]] operation and provides you with a way to annotate the pages even if newer pages are released with corrected errors or more explanatory material.

You can use ~TiddlyWiki formatting markup which is summarized in the FormattingCheatSheet tiddler.

More information on using tiddlers in this TiddlyWiki can be found in [[Working with Tiddlers]].
Also [[Reference Appendix 1 - Working with a TiddlyWiki]] provides more information, the highlights are summarized below to get you started
quickly. However reading appendix 1 is recommended to get the most from this coursebook.

!! Presentations
Presentations are accessed from the MainMenu on the left hand side of the page.

!!! View Presentations in student mode
Running a slide show presentation in student form allows you to follow along with the instructor's slide display. The student mode display presents the same material but in a different style from the instructor.

To start the student mode display:
* click on the title of the  presentation in the MainMenu, this will start the presentation.

The student display mode creates a slide show right on your desktop. The student mode allows you to:
* view each slide without the clutter of the normal tiddlywiki display
* move between slides using the controls at the top right
* view instructor comments on the slide (highlighted in yellow)
* add your notes to the slide using the notebook

!!! Other Presentation modes
To print the slides or interact in other ways, see [[Opening a Presentation]], [[Display a Presentation]] [[Printing Slide Set]].

/%
If you want to print the slides, click on the {{{open}}} link next to the presentation title. On the control tiddler is a print button. This creates a display of the slides including the instructor comments (but not including your notes) where each slide is printed on a seperate page which can be used for manual note taking if you can't bring your computer to the lecture. You can use your browser's print function to print them off.

If you use the pulldown select box right below the Presentation header in the MainMenu, all of the slides for that presentation will open in the center column. In this mode, you can print the ((slide contents, instructor comments and your notes(With every slide on a new page))) using your browser's print function.
%/

!! Chapters
Chapters provide a structured presentation for the non-structured wiki format material. They are composed of multiple tiddlers. You can display them using the title link under the Chapters header in the MainMenu. See [[Opening a Chapter]] and [[Printing Chapters]] for more ways to interact with chapters.

!! Searching
The search box on the upper right allows you to search for tiddlers that match the keywords that your type in. Try it now to look for the words: "presentation searching". It searches as you type (once you have entered three characters, use enter to trigger searching for fewer characters) so you can see the list of tiddlers being refined. <<tiddler [[Reference Appendix 1 - TiddlyWiki Page Layout##search]]>> It displays a list of tiddlers that match the terms along with the list of tags and a synopsis of the content in the tiddler. You can refine the search operation by changing the settings on [[YourSearch Options]]. For full details of the search functionality see: [[YourSearch Help]]

!! Getting updates and errata
Books and manuals have errors and need to be updated. Image having a book that updates and corrects itself while preserving the notes you write in the margins. Using tiddlywiki you can gather these updates into your tiddlywiki from the author's web site. Also there is an rss reader located on the ContentChanges page to notify you with the latest changes.

All tiddlers marked with the tags {{{content}}} or {{{structure}}} are sourced from the author's tiddlywiki. See the [[sync]] page for instructions on updating these tiddlers with current copies.

!! Emergency recovery
In the event you have made changes to the coursebook that you want to save and something is preventing you from saving it, you can click on <<tiddler SaveToClipboard with: "Emergency Save TiddlyWiki"l>> to get a copy of the coursebook content that can be copied and then hand edited into the coursebook. See SaveToClipboard for detailed instructions on using the results of the emergency save. This should rarely if ever be needed, but can be useful on occasion.
The backstage link displayed in the upper right hand side of the page is used to perform administrative functions on the TiddlyWiki. Normal day to day use of the Coursebook should not require you to use this.

Clicking on backstage will display a menu of options:
;save
:saves the tiddlywiki just like the @@save changes@@ link in the sidebar.
;saveAs
:allows you to save the Coursebook under a different name. This is useful for manually saving a backup or starting another Coursebook.
;sync
: synchronizes the current plugins against the original site from which they were downloaded. Don't confuse this with [[sync]] which syncs the Coursebook content. The sync mechanism can seriously screw things up, so forget that it exists.
;attach
:if present it allows you to attach files to the tiddlywiki. Special [[attachment]] tiddlers are created that can be references in the tiddlywiki and allow you to access the attached file from: encoded data enclosed in the attachment tiddler, a local file reference, a remote url reference to the file. See AttachFilePluginInfo for details.
;import
:allows you to import tiddlers from another tiddlywiki. This can be used to import plugins or normal tiddlers. The import menu does not use the default import mechanism supplied with an un-enhanced tiddlywiki. See ImportTiddlersPluginInfo for information on using the http://www.tiddlytools.com enhanced version of the import tool included in this Coursebook. Also see [[Importing a new plugin|here##Importing a new plugin]].
;export
: allows you to export tiddlers to another file on local disk. This can be used to export unused plugins, create backups of particular tiddlers, reduce the size of the Coursebook by exporting tiddlers and then loading them on demand using the [[IncludePlugin|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D%20IncludePlugin]] or the [[ExernalTiddlersPlugin|http://www.tiddlytools.com/#ExternalTiddlersPluginInfo%20ExternalTiddlersPlugin]]. The export menu does not use the default export mechanism supplied with an un-enhanced tiddlywiki. See ExportTiddlersPluginInfo for information on using the http://www.tiddlytools.com enhanced version of the export tool included in this Coursebook.
;tweak
:allows mass editing/changes to multiple tiddlers. When it changes the tiddlers, it does not mark them as dirty, so any list of unsaved tiddlers will not show these tiddlers. See TiddlerTweakerPlugin for direction on how to use this tool.
;upgrade
:this link upgrades the core javascript code that makes a tiddlywiki work. Unless you have a bug that is fixed in a newer release, you probably don't want to do this as some plugins may not work after the upgrade. If you do choose to upgrade, make sure you have a copy of the original coursebook (maybe using the saveAs backstage menu item) so you can recover..
;plugins
:this shows all the plugins in the tiddlywiki and their state. If a plugin fails to initialize properly because of a syntax or other error, it is reported here.

!! Importing a new plugin
Importing plugins seems to be a topic that beginners have problems with. In this example we will import the [[ExernalTiddlersPlugin|http://www.tiddlytools.com/#ExternalTiddlersPluginInfo%20ExternalTiddlersPlugin]] from http://www.tidlytools.com.
* Click on the import menu item in the backstage menu
* select the @@import from@@ @@web server@@ radio button
* type http://www.tiddlytools.com into the input box under @@enter a URL...@@
* click on the open button, a message box should pop up on the right indicating it is loading the site (this may take a minute or so at slow speeds)
** when it is done it will say how many tiddlers were found
* since I loaded www.tiddlytools.com earlier and read what tiddlers are needed to import the ~ExternalTiddlersPlugin, scroll down the alphabetically sorted list of tiddlers to the ~ExternalTiddlersPlugin and
** left click on it to select it. A message box pops up on the right to indicate I have selected one tiddler
** then control-left click (apple users may need to use cmd click) to select the ~ExternalTiddlersPluginInfo tiddler as well. The message box tells me I have two tiddlers selected for import.
* I don't wish to select any options, so I click on the import button.
* after 10 seconds, the message box is display telling me it  {{Imported 2 of 449 tiddlers from http://www.tiddlytools.com}}.
* Click on the gray semi-transparent background to dismiss the import screen and the ImportedTiddlers tiddler is displayed. You can see the two new imported tiddlers recorded there.
* check to make sure you aren't editing any tiddlers. If you are click on done so that they are stored.
* choose @@save changes@@ from the sidebar to save the imported tiddlers
* use your browsers refresh button to reload the saved Coursebook. This will activate the newly imported plugin.

This concludes the steps needed to import a plugin or other tiddler.
This tiddler describes using the presentation, chapter ... section in the main menu. Using the other links is described in [[The Main Menu|Reference Appendix 1 - TiddlyWiki Page Layout##The Main Menu column]].

The content links are arranged into 4 sections:
# Presentations
# Chapters
# References
# Quizzes

! Presentations
The presentation section consists of the selection pulldown, start title links and display links. Use of the display links and start title links is described in [[Display a Presentation]].

The selection pulldown opens all the tiddlers associated with a [[multi-tidder presentation|Glossary/multiTiddlerPresentation]] in the story column. Depending on the [[configuration options|StorySaverPluginInfo##Configuration]] it may close all tiddlers in view mode. The section pulldown will not list [[single tidder presentation|Glossary/singleTiddlerPresentation]]. See [[Opening a Presentation]] for more details.

! Chapters
The chapter section consists of the same three parts as the presentation section. See [[Opening a Chapter]] for details on using these sections.

! References and Quizzes
These sections just list links to tiddlers. Clicking on the link opens the corresponding tiddler.

Welcome to the Coursebook on using the Coursebook.

This coursebook was created by [[John Rouillard|JohnRouillard]] to support a class he was teaching.

{{sectionTOC{}}}

<part coursebook>
This coursebook is based on version <<version>> of [[tiddlywiki|http://www.tiddlywiki.org]] and serves as:
* A textbook for the class (including quizzes)
* A notebook during the class
* A presentation tool for the class
</part>
<part tiddlerclass>
It has two main types of entries called tiddlers:
# Content tiddlers are can be updated from the main website for this class
# Note tiddlers are used to store your notes for each tiddler
Content tiddlers are overwritten when you choose to [[sync]] your Coursebook to the updated contents from the master Coursebook.

Your notes are safely preserved across updates.

Identify content tiddlers by looking for {{{content}}} in the gray "tags" block on the upper right side of a tiddler.
</part>

You can click on the content tag in the tag box on the upper right and see all the tiddlers tagged with content.

You can search for particular keywords using the search box at the upper right.

A list of chapters is shown below:
<<matchTags inline "* %0" "\n" sort:title chapter>>
<<tiddler [[Using This Tiddlywiki]]>>

! Credits

<<tiddler [[Credits]]>>

+++(welcomelegal)![Legal stuff <sub>click to display</sub>|Click to display legal information]...
<<tiddler [[Copyright and Legal Stuff]]>>
===
{{exclude comment{<<slideShow single  theme:InstructorSlideShowStyleSheet3 toc:header  footer:"copyright&copy; 2010<br />John Rouillard"  label:"Start autoplay" tooltip:"Autoplay show in instructor projection mode" cycle auto:5>>}}}
<<tiddler WelcomeSlide>>
-s-
! The ~TiddlyWiki Coursebook provides:
* Presentation tool
* Textbook
* Quizzes
* Student notebook
{{overlay1{all in a single html file.}}}
-s-
! The coursebook was developed ...
{{overlay1{as a tool for teaching a workshop on event correlation at a conference of system administrators.}}}
-s-
<<tiddler [[Opening the Coursebook]]>>
-s-
<<tiddler [[Update Your Coursebook]]>>
-s-
! You can take it home with you
Download from:
   FIXME
-s-
<<tiddler [[Random Factoid]]>>
@@display:block;text-align:center;font-weight:bold;font-size:150%;Welcome to the ~TiddlyWiki Coursebook@@
@@display:block;text-align:center;font-weight:bold;font-size:120%;with John Rouillard@@
{{image{
@@left:0%;position:relative;top:0px;[img[main_lk.png]]@@@@left:-10%;position:relative;top:0px;z-index:500;[img[stu_slide_nk.png]]@@@@left:0%;position:relative;top:0px;z-index:1;[img[ins_slide_rk.png]]@@
}}}
{{overlay1{Please come in, have a seat, set up your laptop and get ready to update your coursebook. <br>If you don't have a computer make friends with somebody in the class who does.}}}
A [[TiddlyWiki|http://www.tiddlywiki.org]] is:

* An html file that uses javascript to create a wiki (like Wikipedia)
* You edit not pages, but pieces of micro content called tiddlers
/***
|Name|WikifyPlugin|
|Source|http://www.TiddlyTools.com/#WikifyPlugin|
|Documentation|http://www.TiddlyTools.com/#WikifyPluginInfo|
|Version|1.1.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|substitute fields, slices, or computed values into a wiki-syntax format string and render results dynamically|
The {{{<<wikify>>}}} macro allows you to easily retrieve values from custom tiddler fields, tiddler slices, computed values (using javascript) or just plain old literals, and assemble them into small bits of generated wiki-syntax text content that can be rendered directly into a tiddler, or used in the ViewTemplate or EditTemplate to add dynamically-generated content to each tiddler.

The {{{<<wikiCalc>>}}} macro performs the same processing as {{{<<wikify>>}}} and, in addition, passes the assembled text content through javascript's {{{eval()}}} function before rendering the results.  This allows you to, for example, construct and compute mathematical expressions that use input values extracted from tiddler fields or slices.
!!!!!Documentation
> see [[WikifyPluginInfo]]
!!!!!Revisions
<<<
2009.03.29 [1.1.4] in handler(), pass 'tiddler' value to wikify() to fix macro errors in rendered content
|please see [[WikifyPluginInfo]] for additional revision details|
2007.06.22 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.WikifyPlugin= {major: 1, minor: 1, revision: 4, date: new Date(2009,3,29)};

config.macros.wikify={
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var fmt=params.shift();
		var values=[];
		var out="";
		if (!fmt.match(/\%[0-9]/g) && params.length) // format has no markers, just join all params with spaces
			out=fmt+" "+params.join(" ");
		else { // format param has markers, get values and perform substitution
			while (p=params.shift()) values.push(this.getFieldReference(place,p));
			out=fmt.format(values);
		}
		if (macroName=="wikiCalc") out=eval(out).toString();
		wikify(out.unescapeLineBreaks(),place,null,tiddler);
	},
	getFieldReference: function(place,p) { // "slicename::tiddlername" or "fieldname@tiddlername" or "fieldname"
		if (typeof p != "string") return p; // literal non-string value... just return it...
		var parts=p.split(config.textPrimitives.sliceSeparator);
		if (parts.length==2) {// maybe a slice reference?
			var tid=parts[0]; var slice=parts[1];
			if (!tid || !tid.length || tid=="here") { // no target (or "here"), use containing tiddler
				tid=story.findContainingTiddler(place);
				if (tid) tid=tid.getAttribute("tiddler")
				else tid="SiteSlices"; // fallback for 'non-tiddler' areas (e.g, header, sidebar, etc.)
			}
			var val=store.getTiddlerSlice(tid,slice);  // get tiddler slice value
		}
		if (val==undefined) {// not a slice, or slice not found, maybe a field reference?
			var parts=p.split("@");
			var field=parts[0];
			if (!field || !field.length) field="checked"; // missing fieldname, fallback: checked@tiddlername
			var tid=parts[1];
			if (!tid || !tid.length || tid=="here") { // no target (or "here"), use containing tiddler
				tid=story.findContainingTiddler(place);
				if (tid) tid=tid.getAttribute("tiddler")
				else tid="SiteFields"; // fallback for 'non-tiddler' areas (e.g, header, sidebar, etc.)
			}
			var val=store.getValue(tid,field);
		}
		// not a slice or field, or slice/field not found... return value unchanged
		return val===undefined?p:val;
	}
}
//}}}
//{{{
// define alternative macroName for triggering pre-rendering call to eval()
config.macros.wikiCalc=config.macros.wikify;
//}}}
/***
|Name|WikifyPlugin|
|Source|http://www.TiddlyTools.com/#WikifyPlugin|
|Documentation|http://www.TiddlyTools.com/#WikifyPluginInfo|
|Version|1.1.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for WikifyPlugin|
The {{{<<wikify>>}}} macro allows you to easily retrieve values from custom tiddler fields, tiddler slices, computed values (using javascript) or just plain old literals, and assemble them into small bits of generated wiki-syntax text content that can be rendered directly into a tiddler, or used in the ViewTemplate or EditTemplate to add dynamically-generated content to each tiddler.

The {{{<<wikiCalc>>}}} macro performs the same processing as {{{<<wikify>>}}} and, in addition, passes the assembled text content through javascript's {{{eval()}}} function before rendering the results.  This allows you to, for example, construct and compute mathematical expressions that use input values extracted from tiddler fields or slices.
!!!!!Usage
<<<
The syntax for use in tiddlers:
{{{
<<wikify format value value value value ...>>
<<wikiCalc format value value value value ...>>
}}}
The syntax for use in templates:
{{{
<span macro='wikify format value value value value ...'></span>
<span macro='wikiCalc format value value value value ...'></span>
}}}
where:
* ''format'' specifies the format of the wiki-syntax content (or javascript expression, if using {{{<<wikiCalc>>}}}) that will be rendered
* ''value'' parameters (space-separated), specified using any of:
** ''"tiddlername::slicename"'' - a tiddler slice reference
** ''"fieldname@tiddlername"'' - a tiddler custom field reference
** ''"""{{config.options.txtUserName}}"""'' - evaluated javascript parameter
** ''"none of the above"'' - literal text
When the ''format'' parameter contains //substitution markers// (using "%0" through "%9" character sequences), each value parameter is retrieved and embedded into the formatted content, replacing its corresponding marker.  If the ''format'' parameter does //not// contain any substitution markers, then all parameters are simply joined together for output.  Once the values have been formatted (and, if {{{<<wikiCalc>>}}} is used, evaluated as a javascript expression), the resulting content is then passed to the core wikify() parser to render and display it.

Notes:
* If a parameter is not recognized as fitting any of the above syntax, or if the slice/field referred to cannot be located, the reference will be inserted as literal text into the output
* When working with custom tiddler fields or tiddler slices, you can enter a special psuedo-tiddler name, ''@here'' (e.g., "fieldname@here") or ''here::'' (e.g., "here::slicename") to access custom fields and slices associated with the //current// tiddler.  This //relative// reference syntax can be particularly helpful when placed directly into a ViewTemplate and/or EditTemplate definition, where it can be applied automatically to each tiddler that is displayed.   Note: if you omit the ''@here'' portion of a field reference (e.g., just using "fieldname"), it is assumed to be a reference to a field in the current tiddler (i.e., it is treated as if you specified ''fieldname@here'').
<<<
!!!!!Examples
<<<
{{{
<<wikify [[This tiddler is: %0 using %1 bytes (last author: %2)]] title {{tiddler.text.length}} modifier>>
<<wikify [[The source URL for this plugin is: %0]] 'here::Source'>>
<<wikify [[The tiddler has been changed %0 times]] changecount@here>>
<<wikify [[The Primary Mid color is: @@background:%0;%0@@]] 'ColorPalette::PrimaryMid'>>
<<wikify [[This current user is: %0]] {{config.options.txtUserName}}>>
}}}
<<wikify [[This tiddler is: %0 using %1 bytes (last author: %2)]] title {{tiddler.text.length}} modifier>>
<<wikify [[The source URL for this plugin is: %0]] 'here::Source'>>
<<wikify [[The tiddler has been changed %0 times]] changecount@here>>
<<wikify [[The Primary Mid color is: @@background:%0;%0@@]] 'ColorPalette::PrimaryMid'>>
<<wikify [[This current user is: %0]] {{config.options.txtUserName}}>>
<<<
!!!!!Revisions
<<<
2009.03.29 1.1.4 in handler(), pass 'tiddler' value to wikify() to fix macro errors in rendered content
2009.03.26 1.1.3 unescape output before wikify so that \n can be used in formatting string
2008.11.16 1.1.2 in getFieldReference(), if not a field/slice reference (or field/slice is not found), return string input unchanged instead of returning a blank string.
2008.03.08 1.1.1 size reduction: documentation moved to [[WikifyPluginInfo]]
2008.03.07 1.1.0 added {{{<<wikicalc>>}}} variant for evaluating assembled output as javascript before rendering the result
2007.11.11 1.0.1 in handler(), fixed problem where a trailing space was created when no substitution markers were present in the format param.
2007.06.22 1.0.0 initial release
<<<
Tiddlers are display in the story column of a tiddlywiki. They are shown in two modes:
# View Mode
# Edit Mode

!! View Mode
[img[viewModeTiddler.png]]

A viewed tiddler has the following elements:
;<html><a name="title"></html> title
:The name of the tiddler. This is used to create  a link to the tiddler by surrounding the title with double square brackets. E.G. {{{[[Working with Tiddlers]]}}} produces [[Working with Tiddlers]]. It also can be used to incorporate the contents of the tiddler into another tiddler using the [[tiddler macro|http://tiddlywiki.org/wiki/Tiddler_%28macro%29]]. Note that spaces in titles are collapsed, so two spaces in a title shows up as a single space when displayed. However references to the tiddler by title must include two spaces. This is important since chapters and presentation titles are often padded so that it will be [[properly sorted in the MainMenu|How to Create a Chapter]]. <html></a></html>
;tool bar
:<<tiddler [[Working with Tiddlers##toolBar]]>>
;change information
:displays the user who last changed the tiddler and the date on which the tiddler was changed.
; content
:This makes up the body of the tiddler and is formatted using [[tiddlywiki markup|FormattingCheatSheet]] that provides easily typed shortcuts to make headers, lists, tables etc in the body of the tiddler.
; tags
:Are a mechanism for organizing and grouping tiddlers. For example tiddlers tagged with content are meant to be content displayed to the student. Other tags also have special meanings for the coursebook or the tiddlywiki. They are also useful for finding relationships between tiddlers if the instructor has developed a tagging style. E.G. there may be an examples tag that groups all the tiddlers that contain class examples. The @@[edit]@@ link at the bottom of the tag box is discussed below.  <html><a name="notebook"></html>
;notebook
:This is an addition to the coursebook compared to a normal tiddlywiki. Double clicking on the notebook will provide you a place to store your notes on the tiddler. As in the content of a tiddler,  [[tiddlywiki markup|FormattingCheatSheet]] can be used to format the notes. Notes are preserved across coursebook [[syncs|sync]].

!!! Tagging in view mode
the @@[edit]@@ link at the bottom of the tags box allows the student to add tags to tiddlers to create a unique system for accessing/grouping content. Clicking on the edit link will open and jump to a tag editing box below the tiddler. Typing will produce a list of matching tags that can be selected or a new tag can be added. Using this mechanism helps prevent typos that prevents tiddlers from being mistagged due to case or mispelling. See [[IntelliTaggerPlugin Documentation]] for full instructions on using this.

!! Edit Mode
[img[editModeTiddler.png]]

The components of a tiddler in edit mode are:
; original title
: the current title of the tiddler
; tool bar
: <<tiddler [[Working with Tiddlers##editToolbar]]>>
; edit title
: if you want to change the title, make you change in this box. It will be changed when you click on done. Changing the title does not change any references to the original title. So you must go through the document to find these obsolete references. Also the [[missing tab|Reference Appendix 1 - TiddlyWiki Page Layout/missingTab]] in the sidebar will show you what tiddlers are referencing the tiddler with the old name.
; edit content
: edit the content of the tiddler using [[tiddlywiki markup|FormattingCheatSheet]] as described in the FormattingCheatSheet.
; edit tags
: allows adding or removing tags from the tiddler. Typing will produce a list of matching tags that can be selected or a new tag can be added. Using this mechanism helps prevent typos that prevents tiddlers from being mistagged due to case or mispelling. See [[IntelliTaggerPlugin Documentation]] for full instructions on using this.

/%

|asdf|ghjk|lmno|

!outline
        View Mode
            Image needed w/ callouts
            title
            content
            tags
            notebook
        Edit Mode
            Image needed w/ callouts
            Title editing
            Content editing
                Mention FormattingCheatSheet
            Tag editing
            Tag editing from ViewMode
                edit link at bottom of tag bar

!toolBar
The toolbar provides functions for operating on the tiddler.
; bookmark
: adds a link to this tidder to the BookmarkList that is accessible from the Bookmarks link in the main menu.
; close
: closes this tiddler removing it from being displayed in the story column. It does not delete it.
; close others
: closes all the other tiddlers in the story column. It keeps the tidder its accoiated with open.
; edit
: opens the tiddler in edit mode. If you have a student copy of the coursebook you shouldn't edit any tiddlers tagged with {{{content}}} as they are replaced when you do a sync to get updated course content. Because of this, the normal tiddlywiki shortcut to edit a tiddler (double click on the tiddler) is disabled in the student coursebook.
;refresh
:refresh the display of this tiddler. Because tiddler contents can be dynamically constructed when they are displayed a refresh is sometimes needed to display the most up to date content.
;jump
: move to another open tiddler. This link displays a menu for you to select the tiddler to jump to.
;moreâ–¼
: when clicked on displays some less used tools.
;;fields
:: tiddlers can have addition information associated with them in fields. This item provides a way to change those values. It is unlikely that you will need this.
;;permalink
:: like the permalink link on the sidebar, this changes the url displayed in the browser so that it will open this tiddler when used. You can bookmark the url using you browsers standad bookmark function, and when the bookmark is clicked on it will open the tiddlywiki with this tiddler displayed.
;;references
::show what tiddlers have links to (point to) this tiddler.
;;â—„less
:: when clicked on hides the display of less used tools.
! NOTE
consider adding deletetiddler here in an instructors only setup?? fixme
!editToolbar
This controls editing actions on the tiddler:
;done
: saves changes to the tiddler and returns to view mode. The keystroke control-enter (or control-return) is a shortcut for the done function.
; cancel
:discards changes to the tiddler and returns to view mode. The escape key is a shortcut for this command.
;copy
:copies the current tiddler and creates a new editing instance of the copied tiddler
; delete
: deletes the tiddler. If you save the tiddywiki, the tidder is gone and only recoverable if you saved backups.
; convert
: converts data in a comma separated value list (as exported from a spreadsheet) into a tiddlywiki table.. E.G. type: {{{asdf,bghi,lmno}}} select it and choose convert to table. It will replace the text with {{{|asdf | bghi | lmno |}}}.
!end
%/
/***
|''Name:''|YourSearchPlugin|
|''Version:''|2.1.4 (2009-09-04)|
|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2009 [[abego Software|http://www.abego-software.de]]|
|''~CoreVersion:''|2.1.0|
|''Community:''|[[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23YourSearchPlugin]]|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; ~InternetExplorer 6.0|
!About YourSearch
YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!

For more information see [[Help|YourSearch Help]].
!Compatibility
This plugin requires TiddlyWiki 2.1. 
Check the [[archive|http://tiddlywiki.abego-software.de/archive]] for ~YourSearchPlugins supporting older versions of TiddlyWiki.
!Source Code
***/
/***
This plugin's source code is compressed (and hidden). Use this [[link|http://tiddlywiki.abego-software.de/archive/YourSearchPlugin/Plugin-YourSearch-src.2.1.4.js]] to get the readable source code.
***/
///%
if(!version.extensions.YourSearchPlugin){version.extensions.YourSearchPlugin={major:2,minor:1,revision:4,source:"http://tiddlywiki.abego-software.de/#YourSearchPlugin",licence:"[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",copyright:"Copyright (c) abego Software GmbH, 2005-2009 (www.abego-software.de)"};if(!window.abego){window.abego={};}if(!Array.forEach){Array.forEach=function(_1,_2,_3){for(var i=0,_4=_1.length;i<_4;i++){_2.call(_3,_1[i],i,_1);}};Array.prototype.forEach=function(_5,_6){for(var i=0,_7=this.length;i<_7;i++){_5.call(_6,this[i],i,this);}};}abego.toInt=function(s,_8){if(!s){return _8;}var n=parseInt(s);return (n==NaN)?_8:n;};abego.createEllipsis=function(_9){var e=createTiddlyElement(_9,"span");e.innerHTML="&hellip;";};abego.shallowCopy=function(_a){if(!_a){return _a;}var _b={};for(var n in _a){_b[n]=_a[n];}return _b;};abego.copyOptions=function(_c){return !_c?{}:abego.shallowCopy(_c);};abego.countStrings=function(_d,s){if(!s){return 0;}var _e=s.length;var n=0;var _f=0;while(1){var i=_d.indexOf(s,_f);if(i<0){return n;}n++;_f=i+_e;}return n;};abego.getBracedText=function(_10,_11,_12){if(!_11){_11=0;}var re=/\{([^\}]*)\}/gm;re.lastIndex=_11;var m=re.exec(_10);if(m){var s=m[1];var _13=abego.countStrings(s,"{");if(!_13){if(_12){_12.lastIndex=re.lastIndex;}return s;}var len=_10.length;for(var i=re.lastIndex;i<len&&_13;i++){var c=_10.charAt(i);if(c=="{"){_13++;}else{if(c=="}"){_13--;}}}if(!_13){if(_12){_12.lastIndex=i-1;}return _10.substring(m.index+1,i-1);}}};abego.select=function(_14,_15,_16,_17){if(!_17){_17=[];}_14.forEach(function(t){if(_15.call(_16,t)){_17.push(t);}});return _17;};abego.consumeEvent=function(e){if(e.stopPropagation){e.stopPropagation();}if(e.preventDefault){e.preventDefault();}e.cancelBubble=true;e.returnValue=true;};abego.TiddlerFilterTerm=function(_18,_19){if(!_19){_19={};}var _1a=_18;if(!_19.textIsRegExp){_1a=_18.escapeRegExp();if(_19.fullWordMatch){_1a="\\b"+_1a+"\\b";}}var _1b=new RegExp(_1a,"m"+(_19.caseSensitive?"":"i"));this.tester=new abego.MultiFieldRegExpTester(_1b,_19.fields,_19.withExtendedFields);};abego.TiddlerFilterTerm.prototype.test=function(_1c){return this.tester.test(_1c);};abego.parseNewTiddlerCommandLine=function(s){var m=/(.*?)\.(?:\s+|$)([^#]*)(#.*)?/.exec(s);if(!m){m=/([^#]*)()(#.*)?/.exec(s);}if(m){var r;if(m[3]){var s2=m[3].replace(/#/g,"");r=s2.parseParams("tag");}else{r=[[]];}var _1d=m[2]?m[2].trim():"";r.push({name:"text",value:_1d});r[0].text=[_1d];return {title:m[1].trim(),params:r};}else{return {title:s.trim(),params:[[]]};}};abego.parseTiddlerFilterTerm=function(_1e,_1f,_20){var re=/\s*(?:(?:\{([^\}]*)\})|(?:(=)|([#%!])|(?:(\w+)\s*\:(?!\/\/))|(?:(?:("(?:(?:\\")|[^"])+")|(?:\/((?:(?:\\\/)|[^\/])+)\/)|(\w+\:\/\/[^\s]+)|([^\s\)\-\"]+)))))/mg;var _21={"!":"title","%":"text","#":"tags"};var _22={};var _23;re.lastIndex=_1f;while(1){var i=re.lastIndex;var m=re.exec(_1e);if(!m||m.index!=i){throw "Word or String literal expected";}if(m[1]){var _24={};var _25=abego.getBracedText(_1e,0,_24);if(!_25){throw "Invalid {...} syntax";}var f=Function("tiddler","return ("+_25+");");return {func:f,lastIndex:_24.lastIndex,markRE:null};}if(m[2]){_23=true;}else{if(m[3]){_22[_21[m[3]]]=1;}else{if(m[4]){_22[m[4]]=1;}else{var _26=m[6];var _27=m[5]?window.eval(m[5]):m[6]?m[6]:m[7]?m[7]:m[8];var _20=abego.copyOptions(_20);_20.fullWordMatch=_23;_20.textIsRegExp=_26;var _28=[];for(var n in _22){_28.push(n);}if(_28.length==0){_20.fields=_20.defaultFields;}else{_20.fields=_28;_20.withExtendedFields=false;}var _29=new abego.TiddlerFilterTerm(_27,_20);var _2a=_26?_27:_27.escapeRegExp();if(_2a&&_23){_2a="\\b"+_2a+"\\b";}return {func:function(_2b){return _29.test(_2b);},lastIndex:re.lastIndex,markRE:_2a?"(?:"+_2a+")":null};}}}}};abego.BoolExp=function(s,_2c,_2d){this.s=s;var _2e=_2d&&_2d.defaultOperationIs_OR;var _2f=/\s*(?:(\-|not)|(\())/gi;var _30=/\s*\)/g;var _31=/\s*(?:(and|\&\&)|(or|\|\|))/gi;var _32=/\s*[^\)\s]/g;var _33=/\s*(\-|not)?(\s*\()?/gi;var _34;var _35=function(_36){_33.lastIndex=_36;var m=_33.exec(s);var _37;var _38;if(m&&m.index==_36){_36+=m[0].length;_37=m[1];if(m[2]){var e=_34(_36);_30.lastIndex=e.lastIndex;if(!_30.exec(s)){throw "Missing ')'";}_38={func:e.func,lastIndex:_30.lastIndex,markRE:e.markRE};}}if(!_38){_38=_2c(s,_36,_2d);}if(_37){_38.func=(function(f){return function(_39){return !f(_39);};})(_38.func);_38.markRE=null;}return _38;};_34=function(_3a){var _3b=_35(_3a);while(1){var l=_3b.lastIndex;_31.lastIndex=l;var m=_31.exec(s);var _3c;var _3d;if(m&&m.index==l){_3c=!m[1];_3d=_35(_31.lastIndex);}else{try{_3d=_35(l);}catch(e){return _3b;}_3c=_2e;}_3b.func=(function(_3e,_3f,_40){return _40?function(_41){return _3e(_41)||_3f(_41);}:function(_42){return _3e(_42)&&_3f(_42);};})(_3b.func,_3d.func,_3c);_3b.lastIndex=_3d.lastIndex;if(!_3b.markRE){_3b.markRE=_3d.markRE;}else{if(_3d.markRE){_3b.markRE=_3b.markRE+"|"+_3d.markRE;}}}};var _43=_34(0);this.evalFunc=_43.func;if(_43.markRE){this.markRegExp=new RegExp(_43.markRE,_2d.caseSensitive?"mg":"img");}};abego.BoolExp.prototype.exec=function(){return this.evalFunc.apply(this,arguments);};abego.BoolExp.prototype.getMarkRegExp=function(){return this.markRegExp;};abego.BoolExp.prototype.toString=function(){return this.s;};abego.MultiFieldRegExpTester=function(re,_44,_45){this.re=re;this.fields=_44?_44:["title","text","tags"];this.withExtendedFields=_45;};abego.MultiFieldRegExpTester.prototype.test=function(_46){var re=this.re;for(var i=0;i<this.fields.length;i++){var s=store.getValue(_46,this.fields[i]);if(typeof s=="string"&&re.test(s)){return this.fields[i];}}if(this.withExtendedFields){return store.forEachField(_46,function(_47,_48,_49){return typeof _49=="string"&&re.test(_49)?_48:null;},true);}return null;};abego.TiddlerQuery=function(_4a,_4b,_4c,_4d,_4e){if(_4c){this.regExp=new RegExp(_4a,_4b?"mg":"img");this.tester=new abego.MultiFieldRegExpTester(this.regExp,_4d,_4e);}else{this.expr=new abego.BoolExp(_4a,abego.parseTiddlerFilterTerm,{defaultFields:_4d,caseSensitive:_4b,withExtendedFields:_4e});}this.getQueryText=function(){return _4a;};this.getUseRegExp=function(){return _4c;};this.getCaseSensitive=function(){return _4b;};this.getDefaultFields=function(){return _4d;};this.getWithExtendedFields=function(){return _4e;};};abego.TiddlerQuery.prototype.test=function(_4f){if(!_4f){return false;}if(this.regExp){return this.tester.test(_4f);}return this.expr.exec(_4f);};abego.TiddlerQuery.prototype.filter=function(_50){return abego.select(_50,this.test,this);};abego.TiddlerQuery.prototype.getMarkRegExp=function(){if(this.regExp){return "".search(this.regExp)>=0?null:this.regExp;}return this.expr.getMarkRegExp();};abego.TiddlerQuery.prototype.toString=function(){return (this.regExp?this.regExp:this.expr).toString();};abego.PageWiseRenderer=function(){this.firstIndexOnPage=0;};merge(abego.PageWiseRenderer.prototype,{setItems:function(_51){this.items=_51;this.setFirstIndexOnPage(0);},getMaxPagesInNavigation:function(){return 10;},getItemsCount:function(_52){return this.items?this.items.length:0;},getCurrentPageIndex:function(){return Math.floor(this.firstIndexOnPage/this.getItemsPerPage());},getLastPageIndex:function(){return Math.floor((this.getItemsCount()-1)/this.getItemsPerPage());},setFirstIndexOnPage:function(_53){this.firstIndexOnPage=Math.min(Math.max(0,_53),this.getItemsCount()-1);},getFirstIndexOnPage:function(){this.firstIndexOnPage=Math.floor(this.firstIndexOnPage/this.getItemsPerPage())*this.getItemsPerPage();return this.firstIndexOnPage;},getLastIndexOnPage:function(){return Math.min(this.getFirstIndexOnPage()+this.getItemsPerPage()-1,this.getItemsCount()-1);},onPageChanged:function(_54,_55){},renderPage:function(_56){if(_56.beginRendering){_56.beginRendering(this);}try{if(this.getItemsCount()){var _57=this.getLastIndexOnPage();var _58=-1;for(var i=this.getFirstIndexOnPage();i<=_57;i++){_58++;_56.render(this,this.items[i],i,_58);}}}finally{if(_56.endRendering){_56.endRendering(this);}}},addPageNavigation:function(_59){if(!this.getItemsCount()){return;}var _5a=this;var _5b=function(e){if(!e){var e=window.event;}abego.consumeEvent(e);var _5c=abego.toInt(this.getAttribute("page"),0);var _5d=_5a.getCurrentPageIndex();if(_5c==_5d){return;}var _5e=_5c*_5a.getItemsPerPage();_5a.setFirstIndexOnPage(_5e);_5a.onPageChanged(_5c,_5d);};var _5f;var _60=this.getCurrentPageIndex();var _61=this.getLastPageIndex();if(_60>0){_5f=createTiddlyButton(_59,"Previous","Go to previous page (Shortcut: Alt-'<')",_5b,"prev");_5f.setAttribute("page",(_60-1).toString());_5f.setAttribute("accessKey","<");}for(var i=-this.getMaxPagesInNavigation();i<this.getMaxPagesInNavigation();i++){var _62=_60+i;if(_62<0){continue;}if(_62>_61){break;}var _63=(i+_60+1).toString();var _64=_62==_60?"currentPage":"otherPage";_5f=createTiddlyButton(_59,_63,"Go to page %0".format([_63]),_5b,_64);_5f.setAttribute("page",(_62).toString());}if(_60<_61){_5f=createTiddlyButton(_59,"Next","Go to next page (Shortcut: Alt-'>')",_5b,"next");_5f.setAttribute("page",(_60+1).toString());_5f.setAttribute("accessKey",">");}}});abego.LimitedTextRenderer=function(){var _65=40;var _66=4;var _67=function(_68,_69,_6a){var n=_68.length;if(n==0){_68.push({start:_69,end:_6a});return;}var i=0;for(;i<n;i++){var _6b=_68[i];if(_6b.start<=_6a&&_69<=_6b.end){var r;var _6c=i+1;for(;_6c<n;_6c++){r=_68[_6c];if(r.start>_6a||_69>_6b.end){break;}}var _6d=_69;var _6e=_6a;for(var j=i;j<_6c;j++){r=_68[j];_6d=Math.min(_6d,r.start);_6e=Math.max(_6e,r.end);}_68.splice(i,_6c-i,{start:_6d,end:_6e});return;}if(_6b.start>_6a){break;}}_68.splice(i,0,{start:_69,end:_6a});};var _6f=function(_70){var _71=0;for(var i=0;i<_70.length;i++){var _72=_70[i];_71+=_72.end-_72.start;}return _71;};var _73=function(c){return (c>="a"&&c<="z")||(c>="A"&&c<="Z")||c=="_";};var _74=function(s,_75){if(!_73(s[_75])){return null;}for(var i=_75-1;i>=0&&_73(s[i]);i--){}var _76=i+1;var n=s.length;for(i=_75+1;i<n&&_73(s[i]);i++){}return {start:_76,end:i};};var _77=function(s,_78,_79){var _7a;if(_79){_7a=_74(s,_78);}else{if(_78<=0){return _78;}_7a=_74(s,_78-1);}if(!_7a){return _78;}if(_79){if(_7a.start>=_78-_66){return _7a.start;}if(_7a.end<=_78+_66){return _7a.end;}}else{if(_7a.end<=_78+_66){return _7a.end;}if(_7a.start>=_78-_66){return _7a.start;}}return _78;};var _7b=function(s,_7c){var _7d=[];if(_7c){var _7e=0;var n=s.length;var _7f=0;do{_7c.lastIndex=_7e;var _80=_7c.exec(s);if(_80){if(_7e<_80.index){var t=s.substring(_7e,_80.index);_7d.push({text:t});}_7d.push({text:_80[0],isMatch:true});_7e=_80.index+_80[0].length;}else{_7d.push({text:s.substr(_7e)});break;}}while(true);}else{_7d.push({text:s});}return _7d;};var _81=function(_82){var _83=0;for(var i=0;i<_82.length;i++){if(_82[i].isMatch){_83++;}}return _83;};var _84=function(s,_85,_86,_87,_88){var _89=Math.max(Math.floor(_88/(_87+1)),_65);var _8a=Math.max(_89-(_86-_85),0);var _8b=Math.min(Math.floor(_86+_8a/3),s.length);var _8c=Math.max(_8b-_89,0);_8c=_77(s,_8c,true);_8b=_77(s,_8b,false);return {start:_8c,end:_8b};};var _8d=function(_8e,s,_8f){var _90=[];var _91=_81(_8e);var pos=0;for(var i=0;i<_8e.length;i++){var t=_8e[i];var _92=t.text;if(t.isMatch){var _93=_84(s,pos,pos+_92.length,_91,_8f);_67(_90,_93.start,_93.end);}pos+=_92.length;}return _90;};var _94=function(s,_95,_96){var _97=_96-_6f(_95);while(_97>0){if(_95.length==0){_67(_95,0,_77(s,_96,false));return;}else{var _98=_95[0];var _99;var _9a;if(_98.start==0){_99=_98.end;if(_95.length>1){_9a=_95[1].start;}else{_67(_95,_99,_77(s,_99+_97,false));return;}}else{_99=0;_9a=_98.start;}var _9b=Math.min(_9a,_99+_97);_67(_95,_99,_9b);_97-=(_9b-_99);}}};var _9c=function(_9d,s,_9e,_9f,_a0){if(_9f.length==0){return;}var _a1=function(_a2,s,_a3,_a4,_a5){var t;var _a6;var pos=0;var i=0;var _a7=0;for(;i<_a3.length;i++){t=_a3[i];_a6=t.text;if(_a4<pos+_a6.length){_a7=_a4-pos;break;}pos+=_a6.length;}var _a8=_a5-_a4;for(;i<_a3.length&&_a8>0;i++){t=_a3[i];_a6=t.text.substr(_a7);_a7=0;if(_a6.length>_a8){_a6=_a6.substr(0,_a8);}if(t.isMatch){createTiddlyElement(_a2,"span",null,"marked",_a6);}else{createTiddlyText(_a2,_a6);}_a8-=_a6.length;}if(_a5<s.length){abego.createEllipsis(_a2);}};if(_9f[0].start>0){abego.createEllipsis(_9d);}var _a9=_a0;for(var i=0;i<_9f.length&&_a9>0;i++){var _aa=_9f[i];var len=Math.min(_aa.end-_aa.start,_a9);_a1(_9d,s,_9e,_aa.start,_aa.start+len);_a9-=len;}};this.render=function(_ab,s,_ac,_ad){if(s.length<_ac){_ac=s.length;}var _ae=_7b(s,_ad);var _af=_8d(_ae,s,_ac);_94(s,_af,_ac);_9c(_ab,s,_ae,_af,_ac);};};(function(){function _b0(msg){alert(msg);throw msg;};if(version.major<2||(version.major==2&&version.minor<1)){_b0("YourSearchPlugin requires TiddlyWiki 2.1 or newer.\n\nCheck the archive for YourSearch plugins\nsupporting older versions of TiddlyWiki.\n\nArchive: http://tiddlywiki.abego-software.de/archive");}abego.YourSearch={};var _b1;var _b2;var _b3=function(_b4){_b1=_b4;};var _b5=function(){return _b1?_b1:[];};var _b6=function(){return _b1?_b1.length:0;};var _b7=4;var _b8=10;var _b9=2;var _ba=function(s,re){var m=s.match(re);return m?m.length:0;};var _bb=function(_bc,_bd){var _be=_bd.getMarkRegExp();if(!_be){return 1;}var _bf=_bc.title.match(_be);var _c0=_bf?_bf.length:0;var _c1=_ba(_bc.getTags(),_be);var _c2=_bf?_bf.join("").length:0;var _c3=_bc.title.length>0?_c2/_bc.title.length:0;var _c4=_c0*_b7+_c1*_b9+_c3*_b8+1;return _c4;};var _c5=function(_c6,_c7,_c8,_c9,_ca,_cb){_b2=null;var _cc=_c6.reverseLookup("tags",_cb,false);try{var _cd=[];if(config.options.chkSearchInTitle){_cd.push("title");}if(config.options.chkSearchInText){_cd.push("text");}if(config.options.chkSearchInTags){_cd.push("tags");}_b2=new abego.TiddlerQuery(_c7,_c8,_c9,_cd,config.options.chkSearchExtendedFields);}catch(e){return [];}var _ce=_b2.filter(_cc);var _cf=abego.YourSearch.getRankFunction();for(var i=0;i<_ce.length;i++){var _d0=_ce[i];var _d1=_cf(_d0,_b2);_d0.searchRank=_d1;}if(!_ca){_ca="title";}var _d2=function(a,b){var _d3=a.searchRank-b.searchRank;if(_d3==0){if(a[_ca]==b[_ca]){return (0);}else{return (a[_ca]<b[_ca])?-1:+1;}}else{return (_d3>0)?-1:+1;}};_ce.sort(_d2);return _ce;};var _d4=80;var _d5=50;var _d6=250;var _d7=50;var _d8=25;var _d9=10;var _da="yourSearchResult";var _db="yourSearchResultItems";var _dc;var _dd;var _de;var _df;var _e0;var _e1=function(){if(version.extensions.YourSearchPlugin.styleSheetInited){return;}version.extensions.YourSearchPlugin.styleSheetInited=true;setStylesheet(store.getTiddlerText("YourSearchStyleSheet"),"yourSearch");};var _e2=function(){return _dd!=null&&_dd.parentNode==document.body;};var _e3=function(){if(_e2()){document.body.removeChild(_dd);}};var _e4=function(e){_e3();var _e5=this.getAttribute("tiddlyLink");if(_e5){var _e6=this.getAttribute("withHilite");var _e7=highlightHack;if(_e6&&_e6=="true"&&_b2){highlightHack=_b2.getMarkRegExp();}story.displayTiddler(this,_e5);highlightHack=_e7;}return (false);};var _e8=function(){if(!_de){return;}var _e9=_de;var _ea=findPosX(_e9);var _eb=findPosY(_e9);var _ec=_e9.offsetHeight;var _ed=_ea;var _ee=_eb+_ec;var _ef=findWindowWidth();if(_ef<_dd.offsetWidth){_dd.style.width=(_ef-100)+"px";_ef=findWindowWidth();}var _f0=_dd.offsetWidth;if(_ed+_f0>_ef){_ed=_ef-_f0-30;}if(_ed<0){_ed=0;}_dd.style.left=_ed+"px";_dd.style.top=_ee+"px";_dd.style.display="block";};var _f1=function(){if(_dd){window.scrollTo(0,ensureVisible(_dd));}if(_de){window.scrollTo(0,ensureVisible(_de));}};var _f2=function(){_e8();_f1();};var _f3;var _f4;var _f5=new abego.PageWiseRenderer();var _f6=function(_f7){this.itemHtml=store.getTiddlerText("YourSearchItemTemplate");if(!this.itemHtml){_b0("YourSearchItemTemplate not found");}this.place=document.getElementById(_db);if(!this.place){this.place=createTiddlyElement(_f7,"div",_db);}};merge(_f6.prototype,{render:function(_f8,_f9,_fa,_fb){_f3=_fb;_f4=_f9;var _fc=createTiddlyElement(this.place,"div",null,"yourSearchItem");_fc.innerHTML=this.itemHtml;applyHtmlMacros(_fc,null);refreshElements(_fc,null);},endRendering:function(_fd){_f4=null;}});var _fe=function(){if(!_dd||!_de){return;}var _ff=store.getTiddlerText("YourSearchResultTemplate");if(!_ff){_ff="<b>Tiddler YourSearchResultTemplate not found</b>";}_dd.innerHTML=_ff;applyHtmlMacros(_dd,null);refreshElements(_dd,null);var _100=new _f6(_dd);_f5.renderPage(_100);_f2();};_f5.getItemsPerPage=function(){var n=(config.options.chkPreviewText)?abego.toInt(config.options.txtItemsPerPageWithPreview,_d9):abego.toInt(config.options.txtItemsPerPage,_d8);return (n>0)?n:1;};_f5.onPageChanged=function(){_fe();};var _101=function(){if(_de==null||!config.options.chkUseYourSearch){return;}if((_de.value==_dc)&&_dc&&!_e2()){if(_dd&&(_dd.parentNode!=document.body)){document.body.appendChild(_dd);_f2();}else{abego.YourSearch.onShowResult(true);}}};var _102=function(){_e3();_dd=null;_dc=null;};var _103=function(self,e){while(e!=null){if(self==e){return true;}e=e.parentNode;}return false;};var _104=function(e){if(e.target==_de){return;}if(e.target==_df){return;}if(_dd&&_103(_dd,e.target)){return;}_e3();};var _105=function(e){if(e.keyCode==27){_e3();}};addEvent(document,"click",_104);addEvent(document,"keyup",_105);var _106=function(text,_107,_108){_dc=text;_b3(_c5(store,text,_107,_108,"title","excludeSearch"));abego.YourSearch.onShowResult();};var _109=function(_10a,_10b,_10c,_10d,_10e,_10f){_e1();_dc="";var _110=null;var _111=function(txt){if(config.options.chkUseYourSearch){_106(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}else{story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}_dc=txt.value;};var _112=function(e){_111(_de);return false;};var _113=function(e){if(!e){var e=window.event;}_de=this;switch(e.keyCode){case 13:if(e.ctrlKey&&_e0&&_e2()){_e0.onclick.apply(_e0,[e]);}else{_111(this);}break;case 27:if(_e2()){_e3();}else{this.value="";clearMessage();}break;}if(String.fromCharCode(e.keyCode)==this.accessKey||e.altKey){_101();}if(this.value.length<3&&_110){clearTimeout(_110);}if(this.value.length>2){if(this.value!=_dc){if(!config.options.chkUseYourSearch||config.options.chkSearchAsYouType){if(_110){clearTimeout(_110);}var txt=this;_110=setTimeout(function(){_111(txt);},500);}}else{if(_110){clearTimeout(_110);}}}if(this.value.length==0){_e3();}};var _114=function(e){this.select();clearMessage();_101();};var args=_10e.parseParams("list",null,true);var _115=getFlag(args,"buttonAtRight");var _116=getParam(args,"sizeTextbox",this.sizeTextbox);var btn;if(!_115){btn=createTiddlyButton(_10a,this.label,this.prompt,_112);}var txt=createTiddlyElement(null,"input",null,null,null);if(_10c[0]){txt.value=_10c[0];}txt.onkeyup=_113;txt.onfocus=_114;txt.setAttribute("size",_116);txt.setAttribute("accessKey",this.accessKey);txt.setAttribute("autocomplete","off");if(config.browser.isSafari){txt.setAttribute("type","search");txt.setAttribute("results","5");}else{txt.setAttribute("type","text");}if(_10a){_10a.appendChild(txt);}if(_115){btn=createTiddlyButton(_10a,this.label,this.prompt,_112);}_de=txt;_df=btn;};var _117=function(){_e3();var _118=_b5();var n=_118.length;if(n){var _119=[];for(var i=0;i<n;i++){_119.push(_118[i].title);}story.displayTiddlers(null,_119);}};var _11a=function(_11b,_11c,_11d,_11e){invokeMacro(_11b,"option",_11c,_11d,_11e);var elem=_11b.lastChild;var _11f=elem.onclick;elem.onclick=function(e){var _120=_11f.apply(this,arguments);_fe();return _120;};return elem;};var _121=function(s){var _122=["''","{{{","}}}","//","<<<","/***","***/"];var _123="";for(var i=0;i<_122.length;i++){if(i!=0){_123+="|";}_123+="("+_122[i].escapeRegExp()+")";}return s.replace(new RegExp(_123,"mg"),"").trim();};var _124=function(){var i=_f3;return (i>=0&&i<=9)?(i<9?(i+1):0):-1;};var _125=new abego.LimitedTextRenderer();var _126=function(_127,s,_128){_125.render(_127,s,_128,_b2.getMarkRegExp());};var _129=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_12a,_12b,_12c,_12d,_12e,tags,_12f){_129.apply(this,arguments);_102();};var _130=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_131){_130.apply(this,arguments);_102();};config.macros.yourSearch={label:"yourSearch",prompt:"Gives access to the current/last YourSearch result",handler:function(_132,_133,_134,_135,_136,_137){if(_134.length==0){return;}var name=_134[0];var func=config.macros.yourSearch.funcs[name];if(func){func(_132,_133,_134,_135,_136,_137);}},tests:{"true":function(){return true;},"false":function(){return false;},"found":function(){return _b6()>0;},"previewText":function(){return config.options.chkPreviewText;}},funcs:{itemRange:function(_138){if(_b6()){var _139=_f5.getLastIndexOnPage();var s="%0 - %1".format([_f5.getFirstIndexOnPage()+1,_139+1]);createTiddlyText(_138,s);}},count:function(_13a){createTiddlyText(_13a,_b6().toString());},query:function(_13b){if(_b2){createTiddlyText(_13b,_b2.toString());}},version:function(_13c){var t="YourSearch %0.%1.%2".format([version.extensions.YourSearchPlugin.major,version.extensions.YourSearchPlugin.minor,version.extensions.YourSearchPlugin.revision]);var e=createTiddlyElement(_13c,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#YourSearchPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_13d){var e=createTiddlyElement(_13d,"a");e.setAttribute("href","http://www.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2005-2008 <b><font color=\"red\">abego</font></b> Software<font>";},newTiddlerButton:function(_13e){if(_b2){var r=abego.parseNewTiddlerCommandLine(_b2.getQueryText());var btn=config.macros.newTiddler.createNewTiddlerButton(_13e,r.title,r.params,"new tiddler","Create a new tiddler based on search text. (Shortcut: Ctrl-Enter; Separators: '.', '#')",null,"text");var _13f=btn.onclick;btn.onclick=function(){_e3();_13f.apply(this,arguments);};_e0=btn;}},linkButton:function(_140,_141,_142,_143,_144,_145){if(_142<2){return;}var _146=_142[1];var text=_142<3?_146:_142[2];var _147=_142<4?text:_142[3];var _148=_142<5?null:_142[4];var btn=createTiddlyButton(_140,text,_147,_e4,null,null,_148);btn.setAttribute("tiddlyLink",_146);},closeButton:function(_149,_14a,_14b,_14c,_14d,_14e){var _14f=createTiddlyButton(_149,"close","Close the Search Results (Shortcut: ESC)",_e3);},openAllButton:function(_150,_151,_152,_153,_154,_155){var n=_b6();if(n==0){return;}var _156=n==1?"open tiddler":"open all %0 tiddlers".format([n]);var _157=createTiddlyButton(_150,_156,"Open all found tiddlers (Shortcut: Alt-O)",_117);_157.setAttribute("accessKey","O");},naviBar:function(_158,_159,_15a,_15b,_15c,_15d){_f5.addPageNavigation(_158);},"if":function(_15e,_15f,_160,_161,_162,_163){if(_160.length<2){return;}var _164=_160[1];var _165=(_164=="not");if(_165){if(_160.length<3){return;}_164=_160[2];}var test=config.macros.yourSearch.tests[_164];var _166=false;try{if(test){_166=test(_15e,_15f,_160,_161,_162,_163)!=_165;}else{_166=(!eval(_164))==_165;}}catch(ex){}if(!_166){_15e.style.display="none";}},chkPreviewText:function(_167,_168,_169,_16a,_16b,_16c){var _16d=_169.slice(1).join(" ");var elem=_11a(_167,"chkPreviewText",_16a,_16c);elem.setAttribute("accessKey","P");elem.title="Show text preview of found tiddlers (Shortcut: Alt-P)";return elem;}}};config.macros.foundTiddler={label:"foundTiddler",prompt:"Provides information on the tiddler currently processed on the YourSearch result page",handler:function(_16e,_16f,_170,_171,_172,_173){var name=_170[0];var func=config.macros.foundTiddler.funcs[name];if(func){func(_16e,_16f,_170,_171,_172,_173);}},funcs:{title:function(_174,_175,_176,_177,_178,_179){if(!_f4){return;}var _17a=_124();var _17b=_17a>=0?"Open tiddler (Shortcut: Alt-%0)".format([_17a.toString()]):"Open tiddler";var btn=createTiddlyButton(_174,null,_17b,_e4,null);btn.setAttribute("tiddlyLink",_f4.title);btn.setAttribute("withHilite","true");_126(btn,_f4.title,_d4);if(_17a>=0){btn.setAttribute("accessKey",_17a.toString());}},tags:function(_17c,_17d,_17e,_17f,_180,_181){if(!_f4){return;}_126(_17c,_f4.getTags(),_d5);},text:function(_182,_183,_184,_185,_186,_187){if(!_f4){return;}_126(_182,_121(_f4.text),_d6);},field:function(_188,_189,_18a,_18b,_18c,_18d){if(!_f4){return;}var name=_18a[1];var len=_18a.length>2?abego.toInt(_18a[2],_d7):_d7;var v=store.getValue(_f4,name);if(v){_126(_188,_121(v),len);}},number:function(_18e,_18f,_190,_191,_192,_193){var _194=_124();if(_194>=0){var text="%0)".format([_194.toString()]);createTiddlyElement(_18e,"span",null,"shortcutNumber",text);}}}};var opts={chkUseYourSearch:true,chkPreviewText:true,chkSearchAsYouType:true,chkSearchInTitle:true,chkSearchInText:true,chkSearchInTags:true,chkSearchExtendedFields:true,txtItemsPerPage:_d8,txtItemsPerPageWithPreview:_d9};for(var n in opts){if(config.options[n]==undefined){config.options[n]=opts[n];}}config.shadowTiddlers.AdvancedOptions+="\n<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]]) ([[help|YourSearch Help]])// ";config.shadowTiddlers["YourSearch Help"]="!Field Search\nWith the Field Search you can restrict your search to certain fields of a tiddler, e.g"+" only search the tags or only the titles. The general form is //fieldname//'':''//textToSearch// (e."+"g. {{{title:intro}}}). In addition one-character shortcuts are also supported for the standard field"+"s {{{title}}}, {{{text}}} and {{{tags}}}:\n|!What you want|!What you type|!Example|\n|Search ''titles "+"only''|start word with ''!''|{{{!jonny}}} (shortcut for {{{title:jonny}}})|\n|Search ''contents/text "+"only''|start word with ''%''|{{{%football}}} (shortcut for {{{text:football}}})|\n|Search ''tags only"+"''|start word with ''#''|{{{#Plugin}}} (shortcut for {{{tags:Plugin}}})|\n\nUsing this feature you may"+" also search the extended fields (\"Metadata\") introduced with TiddlyWiki 2.1, e.g. use {{{priority:1"+"}}} to find all tiddlers with the priority field set to \"1\".\n\nYou may search a word in more than one"+" field. E.g. {{{!#Plugin}}} (or {{{title:tags:Plugin}}} in the \"long form\") finds tiddlers containin"+"g \"Plugin\" either in the title or in the tags (but does not look for \"Plugin\" in the text). \n\n!Boole"+"an Search\nThe Boolean Search is useful when searching for multiple words.\n|!What you want|!What you "+"type|!Example|\n|''All words'' must exist|List of words|{{{jonny jeremy}}} (or {{{jonny and jeremy}}}"+")|\n|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\n|A word ''must "+"not exist''|Start word with ''-''|{{{-jonny}}} (or {{{not jonny}}})|\n\n''Note:'' When you specify two"+" words, separated with a space, YourSearch finds all tiddlers that contain both words, but not neces"+"sarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need"+" to put the words into quotes. I.e. you type: {{{\"john brown\"}}}.\n\nUsing parenthesis you may change "+"the default \"left to right\" evaluation of the boolean search. E.g. {{{not (jonny or jeremy)}}} finds"+" all tiddlers that contain neither \"jonny\" nor \"jeremy. In contrast to this {{{not jonny or jeremy}}"+"} (i.e. without parenthesis) finds all tiddlers that either don't contain \"jonny\" or that contain \"j"+"eremy\".\n\n!'Exact Word' Search\nBy default a search result all matches that 'contain' the searched tex"+"t. E.g. if you search for {{{Task}}} you will get all tiddlers containing 'Task', but also '~Complet"+"edTask', '~TaskForce' etc.\n\nIf you only want to get the tiddlers that contain 'exactly the word' you"+" need to prefix it with a '='. E.g. typing '=Task' will find the tiddlers that contain the word 'Tas"+"k', ignoring words that just contain 'Task' as a substring.\n\n!~CaseSensitiveSearch and ~RegExpSearch"+"\nThe standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearc"+"h. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\n\nIn addition you m"+"ay do a \"regular expression\" search even with the ''~RegExpSearch'' set to false by directly enterin"+"g the regular expression into the search field, framed with {{{/.../}}}. \n\nExample: {{{/m[ae][iy]er/"+"}}} will find all tiddlers that contain either \"maier\", \"mayer\", \"meier\" or \"meyer\".\n\n!~JavaScript E"+"xpression Filtering\nIf you are familiar with JavaScript programming and know some TiddlyWiki interna"+"ls you may also use JavaScript expression for the search. Just enter a JavaScript boolean expression"+" into the search field, framed with {{{ { ... } }}}. In the code refer to the variable tiddler and e"+"valuate to {{{true}}} when the given tiddler should be included in the result. \n\nExample: {{{ { tidd"+"ler.modified > new Date(\"Jul 4, 2005\")} }}} returns all tiddler modified after July 4th, 2005.\n\n!Com"+"bined Search\nYou are free to combine the various search options. \n\n''Examples''\n|!What you type|!Res"+"ult|\n|{{{!jonny !jeremy -%football}}}|all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its tit"+"les, but no {{{football}}} in content.|\n|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact wor"+"d). Tags named '~CompletedTask', '~TaskForce' etc. are not considered.|\n\n!Access Keys\nYou are encour"+"aged to use the access keys (also called \"shortcut\" keys) for the most frequently used operations. F"+"or quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\n\n|"+"!Key|!Operation|\n|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search in"+"put field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the pr"+"evious search result. This way you can quickly display multiple tiddlers using \"Press {{{Alt-F}}}. S"+"elect tiddler.\" sequences.|\n|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Resul"+"t]] is already closed and the cursor is in the search input field the field's content is cleared so "+"you start a new query.|\n|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second e"+"tc. tiddler from the result list.|\n|{{{Alt-O}}}|Opens all found tiddlers.|\n|{{{Alt-P}}}|Toggles the "+"'Preview Text' mode.|\n|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[Your"+"Search Result]].|\n|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the "+"{{{Return}}} key actually starts the search (as does pressing the 'search' button).|\n\n//If some of t"+"hese shortcuts don't work for you check your browser if you have other extensions installed that alr"+"eady \"use\" these shortcuts.//";config.shadowTiddlers["YourSearch Options"]="|>|!YourSearch Options|\n|>|<<option chkUseYourSearch>> Use 'Your Search'|\n|!|<<option chkPreviewText"+">> Show Text Preview|\n|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required"+" to start search)|\n|!|Default Search Filter:<<option chkSearchInTitle>>Title ('!')     <<option chk"+"SearchInText>>Text ('%')     <<option chkSearchInTags>>Tags ('#')    <<option chkSearchExtendedFiel"+"ds>>Extended Fields<html><br><font size=\"-2\">The fields of a tiddlers that are searched when you don"+"'t explicitly specify a filter in the search text <br>(Explictly specify fields using one or more '!"+"', '%', '#' or 'fieldname:' prefix before the word/text to find).</font></html>|\n|!|Number of items "+"on search result page: <<option txtItemsPerPage>>|\n|!|Number of items on search result page with pre"+"view text: <<option txtItemsPerPageWithPreview>>|\n";config.shadowTiddlers["YourSearchStyleSheet"]="/***\n!~YourSearchResult Stylesheet\n***/\n/*{{{*/\n.yourSearchResult {\n\tposition: absolute;\n\twidth: 800"+"px;\n\n\tpadding: 0.2em;\n\tlist-style: none;\n\tmargin: 0;\n\n\tbackground: #ffd;\n\tborder: 1px solid DarkGra"+"y;\n}\n\n/*}}}*/\n/***\n!!Summary Section\n***/\n/*{{{*/\n.yourSearchResult .summary {\n\tborder-bottom-width:"+" thin;\n\tborder-bottom-style: solid;\n\tborder-bottom-color: #999999;\n\tpadding-bottom: 4px;\n}\n\n.yourSea"+"rchRange, .yourSearchCount, .yourSearchQuery   {\n\tfont-weight: bold;\n}\n\n.yourSearchResult .summary ."+"button {\n\tfont-size: 10px;\n\n\tpadding-left: 0.3em;\n\tpadding-right: 0.3em;\n}\n\n.yourSearchResult .summa"+"ry .chkBoxLabel {\n\tfont-size: 10px;\n\n\tpadding-right: 0.3em;\n}\n\n/*}}}*/\n/***\n!!Items Area\n***/\n/*{{{*"+"/\n.yourSearchResult .marked {\n\tbackground: none;\n\tfont-weight: bold;\n}\n\n.yourSearchItem {\n\tmargin-to"+"p: 2px;\n}\n\n.yourSearchNumber {\n\tcolor: #808080;\n}\n\n\n.yourSearchTags {\n\tcolor: #008000;\n}\n\n.yourSearc"+"hText {\n\tcolor: #808080;\n\tmargin-bottom: 6px;\n}\n\n/*}}}*/\n/***\n!!Footer\n***/\n/*{{{*/\n.yourSearchFoote"+"r {\n\tmargin-top: 8px;\n\tborder-top-width: thin;\n\tborder-top-style: solid;\n\tborder-top-color: #999999;"+"\n}\n\n.yourSearchFooter a:hover{\n\tbackground: none;\n\tcolor: none;\n}\n/*}}}*/\n/***\n!!Navigation Bar\n***/"+"\n/*{{{*/\n.yourSearchNaviBar a {\n\tfont-size: 16px;\n\tmargin-left: 4px;\n\tmargin-right: 4px;\n\tcolor: bla"+"ck;\n\ttext-decoration: underline;\n}\n\n.yourSearchNaviBar a:hover {\n\tbackground-color: none;\n}\n\n.yourSe"+"archNaviBar .prev {\n\tfont-weight: bold;\n\tcolor: blue;\n}\n\n.yourSearchNaviBar .currentPage {\n\tcolor: #"+"FF0000;\n\tfont-weight: bold;\n\ttext-decoration: none;\n}\n\n.yourSearchNaviBar .next {\n\tfont-weight: bold"+";\n\tcolor: blue;\n}\n/*}}}*/\n";config.shadowTiddlers["YourSearchResultTemplate"]="<!--\n{{{\n-->\n<span macro=\"yourSearch if found\">\n<!-- The Summary Header ============================"+"================ -->\n<table class=\"summary\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">"+"<tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Result <span class=\"yourSearchRange\" macro=\"yourSearc"+"h itemRange\"></span>\n\t\t&nbsp;of&nbsp;<span class=\"yourSearchCount\" macro=\"yourSearch count\"></span>\n"+"\t\tfor&nbsp;<span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>\n\t</td>\n\t<td class=\"yourSea"+"rchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch chkPreviewText\"></span><span class=\"chkBoxLabel"+"\">preview text</span>\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch openAllButton\"></span>\n\t\t<span macro=\"yourSearch lin"+"kButton 'YourSearch Options' options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkB"+"utton 'YourSearch Help' help 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch clo"+"seButton\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n\n<!-- The List of Found Tiddlers ================="+"=========================== -->\n<div id=\"yourSearchResultItems\" itemsPerPage=\"25\" itemsPerPageWithPr"+"eview=\"10\"></div>\n\n<!-- The Footer (with the Navigation) ==========================================="+"= -->\n<table class=\"yourSearchFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody"+">\n  <tr>\n\t<td align=\"left\">\n\t\tResult page: <span class=\"yourSearchNaviBar\" macro=\"yourSearch naviBar"+"\"></span>\n\t</td>\n\t<td align=\"right\"><span macro=\"yourSearch version\"></span>, <span macro=\"yourSearc"+"h copyright\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n<!-- end of the 'tiddlers found' case ========="+"================================== -->\n</span>\n\n\n<!-- The \"No tiddlers found\" case ================="+"========================== -->\n<span macro=\"yourSearch if not found\">\n<table class=\"summary\" border="+"\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Resu"+"lt: No tiddlers found for <span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>.\n\t</td>\n\t<t"+"d class=\"yourSearchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Options'"+" options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Help' help"+" 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch closeButton\"></span>\n\t</td>\n  <"+"/tr>\n</tbody></table>\n</span>\n\n\n<!--\n}}}\n-->\n";config.shadowTiddlers["YourSearchItemTemplate"]="<!--\n{{{\n-->\n<span class='yourSearchNumber' macro='foundTiddler number'></span>\n<span class='yourSea"+"rchTitle' macro='foundTiddler title'/></span>&nbsp;-&nbsp;\n<span class='yourSearchTags' macro='found"+"Tiddler field tags 50'/></span>\n<span macro=\"yourSearch if previewText\"><div class='yourSearchText' macro='fo"+"undTiddler field text 250'/></div></span>\n<!--\n}}}\n-->";config.shadowTiddlers["YourSearch"]="<<tiddler [[YourSearch Help]]>>";config.shadowTiddlers["YourSearch Result"]="The popup-like window displaying the result of a YourSearch query.";config.macros.search.handler=_109;var _195=function(){if(config.macros.search.handler!=_109){alert("Message from YourSearchPlugin:\n\n\nAnother plugin has disabled the 'Your Search' features.\n\n\nYou may "+"disable the other plugin or change the load order of \nthe plugins (by changing the names of the tidd"+"lers)\nto enable the 'Your Search' features.");}};setTimeout(_195,5000);abego.YourSearch.getStandardRankFunction=function(){return _bb;};abego.YourSearch.getRankFunction=function(){return abego.YourSearch.getStandardRankFunction();};abego.YourSearch.getCurrentTiddler=function(){return _f4;};abego.YourSearch.closeResult=function(){_e3();};abego.YourSearch.getFoundTiddlers=function(){return _b1;};abego.YourSearch.getQuery=function(){return _b2;};abego.YourSearch.onShowResult=function(_196){highlightHack=_b2?_b2.getMarkRegExp():null;if(!_196){_f5.setItems(_b5());}if(!_dd){_dd=createTiddlyElement(document.body,"div",_da,"yourSearchResult");}else{if(_dd.parentNode!=document.body){document.body.appendChild(_dd);}}_fe();highlightHack=null;};})();}
//%/
{{nocol{}}}
<<tiddler OpenStoryButton with: "Open all tiddlers tagged with attachment" "Open the attachment tiddlers to cache their source URLs">>
!usage
{{{[img[block-icon.png]]}}}
[img[block-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./block-icon.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[bookmark-icon.png]]}}}
[img[bookmark-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./bookmark-icon.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[bubble-icon.png]]}}}
[img[bubble-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./bubble-icon.png
!url

!data
data:image/png;base64,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
<!--{{{-->
<div class='toolbar' macro='toolbar [[OtherToolbarCommands::ContentViewToolbar]]'></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='tiddler OpenStoryButton'>
<hr />
</div>
<div class='viewer' macro='view text wikified'></div>
<span macro="sectionTOC"></span>
<div id="Notes" class='notes viewer' macro='notes heading:Notebook tag:"Notes excludeLists noReload" suffix:Notes'></div>
<div class='tagClear'></div>
<!--}}}-->
!usage
{{{[img[clipboard-icon.png]]}}}
[img[clipboard-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./clipboard-icon.png
!url

!data
data:image/png;base64,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
This tag marks all tiddlers that the student will read. This is in contrast with [[structure]] tiddlers that are specific configurations that allow the unique functionality of this tiddlywiki to be implemented.

By default tiddlers tagged content do not switch to edit mode on a double click. This allows using double/triple click to select text from the content tiddler.. This allows easy copy/paste and prevents inadvertent changes that would be overwritten by synchronizing/updating the content from the master source.
<!--{{{-->
<div class='toolbar' macro='toolbar [[OtherToolbarCommands::ContentViewToolbar]]'></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>
<span macro="sectionTOC"></span>
<div id="Notes" class='notes viewer' macro='notes heading:Notebook tag:"Notes excludeLists noReload" suffix:Notes'></div>
<div class='tagClear'></div>
<!--}}}-->
!usage
{{{[img[delete-icon.png]]}}}
[img[delete-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./delete-icon.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[editModeTiddler.png]]}}}
[img[editModeTiddler.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./support/images/editModeTiddler.png
!url

!data

{{nocol{}}}
Examples are intended to illustrate the mechanism of log analysis with SEC. They usually have working rules and include information about the events that are recognized by the rules.
{{nocol{}}}
Exercises present problems in log analysis for the student to solve. Some of them include extensive background discussion and hints on how to solve the problem while others are intended for the student to solve from the ground up.
!usage
{{{[img[flag-icon.png]]}}}
[img[flag-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./flag-icon.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[goal.jpg]]}}}
[img[goal.jpg]]
!notes
attached by FileDropPlugin
!type
image/jpeg
!file
./support/images/goal.jpg
!url

!data

!usage
{{{[img[info-icon.png]]}}}
[img[info-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./info-icon.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[label-icon.png]]}}}
[img[label-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./label-icon.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[pageLayout.png]]}}}
[img[pageLayout.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./support/images/pageLayout.png
!url

!data

!usage
{{{[img[pencil-icon.png]]}}}
[img[pencil-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./pencil-icon.png
!url

!data
data:image/png;base64,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
<!--{{{-->
<div class='toolbar' macro='toolbar [[OtherToolbarCommands::ContentViewToolbar]]'></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='showWhenExists InstructorSlideShowStyleSheet'>
<div macro='tiddler SlideStyleLinks##Instructor'></div>
<div class="exclude" macro='slideShow  theme:InstructorSlideShowStyleSheet toc:titles noClicks footer:"copyright&copy; 2010<br />John Rouillard" clock:+ label:"Instructor" tooltip:"Start slideshow in instructor projection mode"'></div>
</div>

<div macro='tiddler SlideStyleLinks##Student'></div>
<div class='viewer exclude' macro='slideShow noClicks noKeyboard noOverlays toc:titles label:"Student" tooltip:"Start the slideshow in student mode"'></div>

<div macro='tiddler SlideStyleLinks##Print'></div>
<div class='viewer exclude' macro='slideShow showAll theme:PrintingSlideShowStyleSheet label:Print tooltip:"Display slide show for printing"'></div>
<hr />
</div>
<div class='viewer' macro='view text wikified'></div>
<span macro="sectionTOC"></span>
<div id="Notes" class='notes viewer' macro='notes heading:Notebook tag:"Notes excludeLists noReload" suffix:Notes'></div>
<div class='tagClear'></div>
<!--}}}-->
!usage
{{{[img[search-icon.png]]}}}
[img[search-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./search-icon.png
!url

!data
data:image/png;base64,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
<!--{{{-->
<div class='toolbar' macro='toolbar [[OtherToolbarCommands::ContentViewToolbar]]'></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 id="Notes" class='notes viewer' macro='notes heading:Notebook tag:"Notes excludeLists noReload" suffix:Notes'></div>
<div class='tagClear'></div>
<!--}}}-->
Tiddlers tagged with this tag are used to implement/control the functionality of the tiddlywiki and are not meant to be seen by the student.
To synchronize your {{{content}}} and {{{structure}}} tiddlers use the import button below. It will import all the updated tiddlers from the source site while preserving your notes.

<<loadTiddlers "label:Import new content from %0" updates {{store.getTiddlerSlice('GettingStarted','courseHomeContent')}} >>

If you want you can also manually import particular tiddlers using the import tool in  the backstage menu after seeing which tiddlers have been updated by looking at the ContentChanges tiddler.

After performing an update you may want to visit DeletedTiddler to remove/clean up any tiddlers that have been superseded and are no longer necessary. You can also display the removed tiddlers and copy any notes you may have before deleting the tiddlers.
! Slide 1
!! sub item

{{comment{
A slide comment
!!! sub sub item
}}}

<<tabs tabsClass
Welcome "A description of how tags work in TiddlyWiki" Welcome
"Chapter 1" "A description of slides in TiddlyWiki" [[Chapter  1 - Getting started, basic concepts and use]]
>>
!usage
{{{[img[tick-icon.png]]}}}
[img[tick-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./tick-icon.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[viewModeTiddler.png]]}}}
[img[viewModeTiddler.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./support/images/viewModeTiddler.png
!url

!data
data:image/png;base64,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
!usage
{{{[img[warning-icon.png]]}}}
[img[warning-icon.png]]
!notes
attached by FileDropPlugin
!type
image/png
!file
./warning-icon.png
!url

!data
data:image/png;base64,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
/***
! Make tiddler macro report an error if tiddler not found

Useful when debugging coursebook.

The zzInstructorSettings tiddler isn't exported to the student book, so missing tiddlers in the studentbook are just left blank,
but with this tiddler present they look like:

<<tiddler MissingTiddler>>

which should be somewhat attention grabbing 8-).
***/

//{{{
// monkey patched version
// display large red text indicating missing tiddler. Include link to tidder w/ reference. Also if tiddler w/ link is a part tiddler, reference
// the real tiddler not the part. Check to see if tidder is defined so that it doesn't cause an error with the TiddlerNotePlugin.
var newcode = 'if (params[0] && tiddler && !(store.getTiddlerText(params[0]) || store.isShadowTiddler(params[0]))) return wikify("@@background:red;font-size: 200%;Error in [["+tiddler.title.replace(new RegExp("/[^/]+$"), "")+"]]: <nowiki><<tiddler [[</nowiki>"+params[0]+"<nowiki>]]>></nowiki> not found@@",place);';

var code=config.macros.tiddler.handler.toString();
var pos=code.indexOf('{');
code = code.substr(0,pos+1)+newcode+code.substr(pos+1);
eval('config.macros.tiddler.handler='+code);

//}}}
/***
See also [[StorySaverPluginConfig]].
***/
/***
! Implementing excludeOrphans

Add the functionality for an excludeOrphans tag similar to excludeMissing. When a tiddler is tagged with excludeOrphans, it won't be shown as an orphan even if there are no referrers to it. It's used to allow top level tiddlers (like story tiddlers) to be referenced by the result of a search rather thanhard coded into tiddlers.

Ideas from: [[Searching for excludeOrphans tag functionality|http://groups.google.com/group/TiddlyWiki/browse_thread/thread/39f7be322883586e/2a19fc0a30a6c3ee]].
***/
//{{{
var orig = TiddlyWiki.prototype.getOrphans;
TiddlyWiki.prototype.getOrphans = function() {
     var results = [];
     var orphans = orig.apply(this, arguments);

     for (var i=0;i<orphans.length;i++) {
       var title = orphans[i];
       var tiddler = store.getTiddler(title); 
       if(this.getReferringTiddlers(title).length == 0 &&
             !tiddler.isTagged("excludeLists") &&
             !tiddler.isTagged("excludeOrphans")) {
                        results.push(title);
         }
     }
     results.sort();
     return results;
}; 
//}}}

/***
! Set the shadow DefaultTiddlers for Coursebook

Set the Welcome tiddler as the default tiddlers when student coursebook opens.
Set a default Instructor main menu to suppress missing tiddler report when editing
coursebook with instructor/editing style sheet and macro definitions.
***/
//{{{
config.shadowTiddlers.DefaultTiddlers = "[[Welcome]]";
config.shadowTiddlers.InstructorMainMenu = "";
//}}}

/***
! Make Unsaved Changes active in the SideBarOptions

Add call to < <unsavedChanges command> > to sidebar right before saveChanges
***/
//{{{
config.shadowTiddlers.SideBarOptions=config.shadowTiddlers.SideBarOptions.replace('<<saveChanges>>','<<unsavedChanges command>><<saveChanges>>');
//}}}

/***
! Closing a tiddler moves back to tiddler that it was linked from

From http://groups.google.com/group/tiddlywiki/browse_thread/thread/05719eb737c9ae22/fa2cff7e65fa2cb8?#fa2cff7e65fa2cb8:
{{{
From: FND <F...@gmx.net>
Date: Thu, 03 Sep 2009 17:44:55 +0100
Local: Thurs, Sep 3 2009 12:44 pm 
Subject: Re: [tw] Re: Close tiddler and go back to the one which opened it? Any thoughts?
Reply | Reply to author | Forward | Print | Individual message | Show original | Report this message | Find messages by this author 
You could try this quick hack: 
--------------- 
}}}
***/
//{{{
(function() {

var _closeTiddler = config.commands.closeTiddler.handler;
config.commands.closeTiddler.handler = function(event, src, title) {
     var tiddlerElem = story.getTiddler(title);
     var origin = tiddlerElem.getAttribute("origin");
     origin = tiddlerElem ? story.getTiddler(origin) : null;
     var status = _closeTiddler.apply(this, arguments);
     if(origin) {
         if(config.options.chkAnimate) {
             anim.startAnimating(new Zoomer(title, tiddlerElem, origin),
                 new Scroller(origin));
         } else {
             window.scrollTo(0,ensureVisible(origin));
         }
     }
     return status;

};

var _onClickTiddlerLink = onClickTiddlerLink;
onClickTiddlerLink = function(ev) {
     var status = _onClickTiddlerLink.apply(this, arguments);
     var target = resolveTarget(ev || window.event);
     var link = target;
     do {
         title = link.getAttribute("tiddlyLink");
         link = link.parentNode;
     } while(title === null && link !== null);
     var el = story.getTiddler(title);
     var origin = story.findContainingTiddler(target);
     origin = origin ? origin.getAttribute("tiddler") : null;
     el.setAttribute("origin", origin);
     return status;

};
})();
//}}}

/***
! Set an off mode for the Tabs in the sidebar

***/
//{{{
config.shadowTiddlers.SideBarTabs=config.shadowTiddlers.SideBarTabs.replace('<<tabs txtMainTab','<<tabs txtMainTab "Off" "A blank tab" ""');

//}}}

/***
! Define isFirefox config.browser option

To determine if this is running within firefox.
***/
//{{{
config.browser.isFirefox = navigator.userAgent.indexOf('Firefox') != -1;
//}}}