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

.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:0; top:0;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
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>>
/***
|''Name:''|AutoRefreshPlugin|
|''Version:''|1.0.1 (2007-01-20)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#AutoRefreshPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[AutoRefreshPlugin Documentation|http://tiddlywiki.abego-software.de/#%5B%5BAutoRefreshPlugin%20Documentation%5D%5D]]|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''~CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.5.0.9 or better; Internet Explorer 6.0|
A tiddler containing the {{{<<autoRefresh...>>}}} macro is automatically refreshed (re-painted) whenever a tiddler changes.
!Syntax
{{{
<<autoRefresh [observeTiddler: tiddler ...]>>
}}}
|{{{observeTiddler}}}|(optional) when specified the refresh will only happen when one of the tiddlers specified is changed.|
!Source Code
***/
//{{{

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

// autoRefresh Macro =============================================================
//
(function() {


var REFRESHER_NAME = "abego_onEveryChange";

var tiddlersToRefresh = {}; // A set holding the names of tiddlers to be refreshed

var onEveryChangeRefresher = function(e,changeList) {
	
	var tiddlerElem = story.findContainingTiddler(e);
	if (!tiddlerElem) return false;

	var title = tiddlerElem.getAttribute("tiddler");
	if (!title) return false;

	// if "observeTiddler" are specified we only refresh if one of the given 
	// tiddlers has changed.
	var observedTiddlers = e.getAttribute("observedTiddlers");
	if (observedTiddlers) {
		var a = observedTiddlers.readBracketedList();
		if (!changeList || !a.containsAny(changeList))
			return;
	}

	// Refresh the tiddler asynchronously. 
	// This way we can avoid repeated refreshes (e.g. when a tiddler is renamed)
	tiddlersToRefresh[title] = true;
	setTimeout(function() {
		// Refresh all tiddlers in tiddlersToRefresh
		for(var title in tiddlersToRefresh)
			story.refreshTiddler(title,null,true);

		// We have refreshed all pending tiddlers. Clear the set.
		tiddlersToRefresh = {};
	}, 0);

	return true;
}

config.refreshers[REFRESHER_NAME] = onEveryChangeRefresher;


config.macros.autoRefresh = {};

config.macros.autoRefresh.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    params = paramString.parseParams("observeTiddler",null,true,false,true); // allowEval, cascadeDefaults, names allowed

	var e = createTiddlyElement(place,"span");
	e.setAttribute("refresh",REFRESHER_NAME);
	var observedTiddlers = params[0]["observeTiddler"];
	if (observedTiddlers && observedTiddlers.length) {
		var s = "[["+observedTiddlers.join("]] [[")+"]]";
		e.setAttribute("observedTiddlers",s);
	}
};


})();

//}}}
Background: #fff
Foreground: #333
PrimaryPale: #FFBFBF
PrimaryLight: #BF2323
PrimaryMid: #BF2323
PrimaryDark: #660000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #ff0000
Background: #fff
Foreground: #333
PrimaryPale: #FFBFBF
PrimaryLight: #BF2323
PrimaryMid: #BF2323
PrimaryDark: #660000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #ff0000
Resultados previos.
*Un continuo se dice descomponible si existen $A,B\subset X$ con $X=A\cup B$ pero $X\neq A, B$.
*Un continuo es hereditariamente indescomponible si cada subcontinuo es indescomponible: si $C(X)$ es unicamente arcoconexo o equivalentemente si $P,Q\subseteq X$ con $P\cap Q\neq\emptyset$ entonces bien $P\subseteq Q$ o bien $Q\subseteq P$.
*Un continuo se dice unicoherente si $X=A\cup B$ entonces $A\cap B$ es conexo.
*Un dendroide es un continuo unicoherente y arcoconexo. En particular, son hereditariamente descomponible. Existe un dendroide suave universal.

Pseudoarco.
*$X$ se dice encadenable si para cada $\epsilon>0$ existe una cadena $\mathcal C$ con $mesh\mathcal C$ tendiendo a $0$ con $X=\bigcup_{C\in\mathcal C} C$.


Aplicaciones confluentes.
*$f:X\to Y$ se dice confluente si para todo $Q\subseteq Y$ y $C$ componente de $f^{-1}(Q)$ entonces $f(C)=Q$.
*Ser confluente es una generalizacion de aplicacion abierta y de aplicacion monotona. Recuerda monotona es que $f^{-1}(x)$ es conexo para cada $x\in Y$.
*Entre localmente conexos las confluentes son composiciones de abiertas y monotonas.
*Si $X$ es hereditariamente descomponible y $f$ es confluente entnces $Y$ es tambien hereditariamente descomponible.

Retractos absolutos y algunas clases de continuos.
Sea $\mathcal K$ una clase de e.t., no necesariamente compactos, diremos que $X\in AR(\mathcal K)$ si
* $X\in\mathcal K$;
* Ppara todo $Y\in\mathcal K$ con $X\subset Y$ cerrado entonces existe una retraccion $r:Y\to X$.

Algunos ejemplos y propiedades para $\mathcal M$ la categoria de espacios metricos:
* $[0,1]\in AR(\mathcal M)$;
* $AR(\mathcal M)$ es cerrado bajo productos, asi $[0,1]^n, [0,1]^\infty\in AR(\mathcal M)$.
* Si $r:X\to Y$ es una retraccion con $X\in AR(\mathcal M)$ entonces $Y\in AR(\mathcal M)$ tambien.
* Sabemos que los espacios en $AR(\mathcal M)$ son extensores en el sentido de que las aplicaciones se pueden extender desde el cerrado a todo el conjunto ambiente.

Queremos estudiar estas propiedades para las siguientes clases:
* $D_0$ dendritas,
* $D$ dendroides,
* $\lambda D$ $\lambda$-dendroides,
* $TL$ tipo arbol,
* $HU$ hereditariamente unicoherentes.
 Se tiene que $D_0\subset D\subset D\subset \lambda D\subset TL\subset HU$.

Teorema
 Si $\mathcal K$ es funcionalmente unionable(?) entonces $X\in AR(\mathcal K)$ sii para todo $A,B\in K$ con $A\subset B$ cerrado toda aplicacion $f:A\to X$ puede ser extendida a $f^*:B\to X$.

Teorema
 Si $\mathcal K$ es unionable entonces el retracto de un elemento en $AR(\mathcal K)$ esta en $AR(\mathcal K)$.

Definicion
 La clase $\mathcal K$ se dice unionable sii para todo $X,Y\in\mathcal K$ con $X\cap Y\in\mathcal K$ se tiene que $X\cup Y\in\mathcal K$.

Definicion
 Diremos que $X$ es pointwise $w$-unionable si dados $K$, $p$ y $p_n\to p$

Definicion
 La clase $\mathcal K$ se dice funcionalmene unionable si para toda pareja $X,Y\in\mathcal K$ y para todo $A\in\mathcal K$ con $A\subset X$ y $f:A\to Y$ con $f(A)\in\mathcal K$ entonces $X\cup_{f}Y\in\mathcal K$.

Teorema
 Si $X\in AR(HU)$ entonces $X$ es un continuo de Kelley.

Definicion
 Diremos que $X$ es pointwise $w$-unionable si dados $K$, $p$ y $p_n\to p$ y $K_n\to K$ son copias homeomorfas de $K$ y $h_n:K\to K_n$ son homeomorfismos con $h_n(p)=p_n$ entonces adjuntando las copias $K_n$ por $p_n$ a $X$, $Y=X\cup \bigcup_0^\infty K_n\in\mathcal K$.

Definicion
 $X$ se dice continuo (arco) Kelly si dados $K$ un compacto y $p_n\to p$ entonces existen compactos (arcoconexos, loc. conexos o arboles)$K_n\ni p_n$ con $K_n\to K$.

Nota
 El pseudarco es Kelley pero no arco-Kelley.

Teorema
 Si $X\in AR(\mathcal K)$ entonces es arco-Kelley.

Definicion
 $X$ se dice ser AAP, arc-approximation property, si para todo compacto $K$ de $X$ y $p\in K$ existen $K_n$ arcoconexos con $p\in K_n\to K\ni p$.

Proposicion
 Arco Kelley es equivalente a ser Kelley mas AAP.

Teorema de Effross
 Si $X$ es continuo homogeneo y $p_n\to p$ entonces existen homeomorfismos $h_n:X\to X$ tales que $h_n(p)=p_n$ y $h_n\to 1_X$.

$X$ tiene la generalized $\epsilon$-push property si dadas $p_n\to p$ existen entonces funciones continuas $f_n:X\to X$ tales que $f_n(p)=p_n$ y con $f_n\to 1_X$.

Teorema
 Si $\mathcal K$ es una clse $w$-unionable por puntos entonces los elementos en $AR(\mathcal K)$ tienen la generalized $\epsilon$-push property.

Teorema
 Si $X=\lim \{T_n, f_n\}$ con $T_n$  son arboles y $f_n$ aplicaciones confluentes entonces $X\in AR(HU)$.

Nota
** $X\in AR(D)$ sii $X$ es dendroide de Kelley.
** Existe un dendroide suave universal por Mohler y Nikel. Por un teorema de Czuba los dendroides de Kelley son suaves. Asi pues en la construccion del dendroide universal tenemos que este contiene a todos los dendroides de Kelley que son suaves.

Problemas
** Si cada elemento en $AR(HU)$ es tipo arbol.
** Sabemos que si $X\in AR(HU$ y no contiene triodo simple $T$ entonces $X$ es tipo arco (ademas con la propiedad de Kelley).

Nota
 Tenemos una caracterizacion: si $X$ es un dendroide y esta en $AR(HU)$  sii es un retracto de Mohler Nikel.

Corolario
$AR(D)=D\cap AR(HU)$

Proposicion
 Los solenoides no estan en $AR(HU)$. Para la demostracion se utilizan los siuientes resultados sobre solenoides.
*** Dado un solenoide $X$, existe $Y$ para el cual no existe $f:X\to Y$ continua y sobreyectiva.
*** Si $g:X\to Y$ entre solenoides entonces $g$ es homotopica a $h=\underset{\longleftarrow}{\lim} h_n:X_n\to Y_n$, entre torres.

Lema1 para demo de T1
  Si $f:S\to T$ es abierta entre arboles entonces existen $V\subset T$ y $W\subset S$ conjuntos finitos tales que $f(W)=V$ y tales que si restringimos $f$ a una componente de $S-W$ entonces es homeomorfismo entre intervalos abiertos.

Lema2 para demo de T1
 Si $f:S\to T$ abierta o monotona con un numero finito de preimagenes no degeneradas entre arboles y $\epsilon >0$ entonces existen $V_1,\dots , V_n$ abiertos conexos tales que $V=V_1\cup\dots\cup V_n$ con $diam V_i<\epsilon$ y $f$ restringida a componentes de $S-f^{-1}(V)$ es homeomorfismo entre intervalos abiertos.

Teorema
 Todo conjunto tipo arbol se puede encajar en el limite inverso de arboles con aplicaciones abiertas como aplicaciones borde.

Nota
** Sabemos que $AR(TL)=AR(HU)\cap TL$.
** Sabemos que existe un tipo arbol que es $AR$.

Teorema
 La imagen monotona de un continuo $AR(TL)$ es un $AR(TL)$.

Problemas
** No sabemos si la imagen monotona de un $AR(HU)$ esta en $AR(HU)$. Si es cierto si el espacio es tipo arbol.
** No sabemos si la imagen abierta (confluente) de un $AR(TL)$ esta en $AR(TL)$.
** Todos los ejemplos conocidos de $AR(HU)$ son bien limite inverso de $TL$ o bien imagen monotona de limite inverso de $TL$. No sabemos si un continuo en $AR(TL)$ es imagen monotona de limite inverso de arboles  con aplicaciones confluentes.
Professor
Ph.D. 1997 Binghamton University, 2001 Universidad de Sevilla
!!!Areas of interest:
Algebraic and geometric topology focused on algebraic K-theory and proper homotopy theory.
!!!Address information
Dpto. Geometría y Topología
Facultad de Matemáticas
Universidad de Sevilla
P.O.Box 1160
41080-Sevilla
Spain
Phone: +34 954557966
Fax: +34 954557970
Email address: m.cardenas.escudero"at"gmail.com
<<tiddler Tutorías>>
<<tiddler GoogleCalendar>>
-s-
''Note:'' These pages are @@color(red):~UTF-8@@ encoded and best viewed by [[downloading|http://www.math.union.edu/~dpvc/jsMath/download/jsMath-fonts.html]] the jsMath fonts. Any inquiries to ''mcard'' at ''us.es'' or ''m.cardenas.escudero'' at ''gmail.com'' .
You still may access my old [[homepage|http://personal.us.es/mcard/index2.php]].
-s-
[[Data]]
* [[Elementos de la Homología Clásica|http://ehcuds.tiddlyspot.com/]]
* [[Introducción a la Topología Geométrica|http://intro2gt.tiddlyspot.com/]]
* [[Topología|http://personal.us.es/mcard/index.php?option=com_content&view=category&layout=blog&id=46&Itemid=64]]
* Introducción a la Topología Poliedral
* [[Teoría de Homotopía|http://udsth0910.tiddlyspot.com/]]
<<tiddler Tutorías>>
[[Diario de clase|http://ehcuds.tiddlyspot.com]]
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.8.5|
|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||
|Description|select and extract tiddlers from your ~TiddlyWiki documents and save them to a separate file|
This plugin provides a control panel to select/export tiddlers to another TiddlyWiki document.  You can also save just the selected tiddlers as a TiddlyWiki '~PureStore' file (much smaller files!), or create plain-text output for manual copy/paste into other applications or XML files that can be used to publish an ~RSS news feed.
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2009.02.26 [2.8.5] use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 [0.0.0] development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 8, revision: 5, date: new Date(2009,2,26)};

// 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 tiddlers written to %1',
	failmsg: 'An error occurred while creating %1',
	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 with %1 previously saved tiddlers',
	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_NF: 'nf', // file type tokens
	type_map: { // map filetype param alternatives/abbreviations to token values
		tiddlywiki:'tw', tw:'tw', wiki: 'tw',
		purestore: 'ps', ps:'ps', store:'ps',
		plaintext: 'tx', tx:'tx', text: 'tx',
		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(this.css,'exportTiddlers');
		panel=createTiddlyElement(place,'span','exportPanel',null,null)
		panel.innerHTML=this.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') { // update list and set focus when panel is made visible
			cme.refreshList(0);
			cme.$('exportFilename').focus(); 
			cme.$('exportFilename').select();
		}
		e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
	},
	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%; }\
	',
	html: '\
		<!-- target path/file  -->\
		<div>\
		export to path/filename:<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>\
		output file 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="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="config.macros.exportTiddlers.process(this)" title="select all tiddlers">\
				&nbsp;all&nbsp;</a>\
			<a href="JavaScript:;" id="exportSelectChanges"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">\
				&nbsp;changes&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectOpened"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">\
				&nbsp;opened&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectRelated"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">\
				&nbsp;related&nbsp;</a> \
			<a href="JavaScript:;" id="exportToggleFilter"\
				onclick="config.macros.exportTiddlers.process(this)" title="show/hide selection filter">\
				&nbsp;filter&nbsp;</a>  \
		</td><td align="right">\
			<a href="JavaScript:;" id="exportListSmaller"\
				onclick="config.macros.exportTiddlers.process(this)" title="reduce list size">\
				&nbsp;&#150;&nbsp;</a>\
			<a href="JavaScript:;" id="exportListLarger"\
				onclick="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>\
		</div><!--box-->\
		<!-- 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="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-->\
	',
	process: function(which) { // process panel control interactions
		var theList=this.$('exportList'); if (!theList) return;
		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;
		}
	},
	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_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 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);
		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,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',
	plainTextTiddler:
		'\n// ----- %0 (by %1 on %2) -----\n\n%3',
	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) {
		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_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);
		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;
	},
	formatItem: function(s,f,t,u) {
		if (f==this.type_TW)
			var r=s.getSaver().externalizeTiddler(s,t);
		if (f==this.type_PS)
			var r=config.macros.exportTiddlers.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.modifier,t.modified.toLocaleString(),t.text]);
		return r||'';
	},
	getData: function(target,filetype,tids) {
		// 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));
			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 text=loadFile(target);
			if (text && text.length) {
				var remoteStore=new TiddlyWiki();
				if (remoteStore.importTiddlyWiki(convertUTF8ToUnicode(text))
					&& 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));
					displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
				}
			}
		}
		return out;
	}
}
//}}}
/***
|Name|ExportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.8.5|
|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|documentation|
|Requires||
|Overrides||
|Description|Documentation for ExportTiddlersPlugin|
ExportTiddlersPlugin provides an interactive control panel that allows you to 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
* ~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
<<<
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.  Transferring that file is now left to other mechanisms, such as email attachments, FTP uploads, portable media (USB,CD,DVD,...), etc.  Also, updated "save as TiddlyWiki document" output to correctly 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).  //Theoretically//, selecting all related tiddlers should ensure that the exported file contains all tiddlers needed to properly render all of the originally selected 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" instead of "tiddlerDisplay" but keep fallback to "tiddlerDisplay" for TW2.1 or earlier
2007.03.01 [2.2.5] removed hijack of store.saveChanges() (was catching save on http:, but there are other solutions that do a much better job of handling save to server.
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.  Based on report from Jose Gonzalez.
2006.05.11 [2.2.2] in createExportPanel, removed call to addNotification() to no longer auto-refresh the list every time a tiddler is changed.  Instead, call refreshExportList(0) only when the panel is first rendered and each time it is made visible.  Prevents unneeded feedback messages from being displayed and increases overall document performance, since the listbox is no longer being updated each time a tiddler is saved.
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.  Reported by Paul Reiber.
2006.04.29 [2.2.0] New features: "Notes" are free-form text that is inserted in the header of a TWDIV export file.  When exporting to a server, the "notify" checkbox indicates that server-side script processing should send an email message when the export file is stored on the server.  Comma-separated addresses may be typed in, or pre-defined in the SiteNotify tiddler.
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] added var to unintended global 'tags' in matchTags(). Avoids FF1501 bug when filtering by tags.  (based on report by TedPavlic)
2006.02.04 [2.1.1] added var to variables that were unintentionally global.  Avoids FireFox 1.5.0.1 crash bug when referencing global variables
2006.02.02 [2.1.0] Added support for output of complete TiddlyWiki documents.  Let's you use ExportTiddlers to generate 'starter' documents from selected tiddlers.
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
Defer initial panel creation and only register a notification function when panel first is created
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 as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding.
2005.11.15 [0.9.2] added non-Ajax post function to bypass javascript security restrictions on cross-domain I/O.  Moved AJAX functions to separate tiddler (no longer needed here).  Generalized HTTP server to support UnaWiki servers
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.  This allows exportPanel to be placed within the same containing element as the "export tiddlers" button, so that relative positioning can be achieved.
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 when filtering for date ranges. Improved error checking/reporting for invalid filter values and filters that don't match any tiddlers. Exporting localfile-to-localfile is working for IE and FF.  Exporting server-to-localfile works in IE (after ActiveX warnings), but has security issues in FF. Cross-domain exporting (localfile/server-to-server) is under development.  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
<<<
/***
|Name|ExternalTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExternalTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExternalTiddlersPluginInfo|
|Version|1.3.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|TemporaryTiddlersPlugin (optional, recommended)|
|Description|retrieve and wikify content from external files or remote URLs|
This plugin extends the {{{<<tiddler>>}}} macro syntax so you can retrieve and wikify content directly from external files or remote URLs.  You can also define alternative "fallback" sources to provide basic "import on demand" handling by automatically creating/importing tiddler content from external sources when the specified ~TiddlerName does not already exist in your document.
!!!!!Documentation
>see [[ExternalTiddlersPluginInfo]]
!!!!!Configuration
<<<
<<option chkExternalTiddlersImport>> automatically create/import tiddlers when using external fallback references
{{{usage: <<option chkExternalTiddlersImport>>}}}
<<option chkExternalTiddlersQuiet>> don't display messages when adding tiddlers ("quiet mode")
{{{usage: <<option chkExternalTiddlersQuiet>>}}}
<<option chkExternalTiddlersTemporary>> tag retrieved tiddlers as 'temporary'(requires [[TemporaryTiddlersPlugin]])
{{{usage: <<option chkExternalTiddlersTemporary>>}}}
tag retrieved tiddlers with: <<option txtExternalTiddlersTags>>
{{{usage: <<option txtExternalTiddlersTags>>}}}

__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 [[LoadTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2008.10.27 [1.3.1] in insertTiddler(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
|please see [[ExternalTiddlersPluginInfo]] for additional revision details|
2007.11.25 [1.0.0] initial release - moved from CoreTweaks
<<<
!!!!!Code
***/
//{{{
version.extensions.ExternalTiddlersPlugin= {major: 1, minor: 3, revision: 1, date: new Date(2008,10,27)};

// optional automatic import/create for missing tiddlers
if (config.options.chkExternalTiddlersImport==undefined) config.options.chkExternalTiddlersImport=true;
if (config.options.chkExternalTiddlersTemporary==undefined) config.options.chkExternalTiddlersTemporary=true;
if (config.options.chkExternalTiddlersQuiet==undefined) config.options.chkExternalTiddlersQuiet=false;
if (config.options.txtExternalTiddlersTags==undefined) config.options.txtExternalTiddlersTags="external";
if (config.options.txtRemoteUsername==undefined) config.options.txtRemoteUsername="";
if (config.options.txtRemotePassword==undefined) config.options.txtRemotePassword="";

config.macros.tiddler.externalTiddlers_handler = config.macros.tiddler.handler;
config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	params = paramString.parseParams("name",null,true,false,true);
	var names = params[0]["name"];
	var list = names[0];
	var items = list.split("|"); 
	var className = names[1] ? names[1] : null;
	var args = params[0]["with"];

	// UTILITY FUNCTIONS
	function extract(text,tids) { // get tiddler source content from plain text or TW doc
		if (!text || !tids || !tids.length) return text; // no text or no tiddler list... return text as-is
		var remoteStore=new TiddlyWiki();
		if (!remoteStore.importTiddlyWiki(text)) return text; // not a TW document... return text as-is
		var out=[]; for (var t=0;t<tids.length;t++)
			{ var txt=remoteStore.getTiddlerText(tids[t]); if (txt) out.push(txt); }
		return out.join("\n");
	}
	function substitute(text,args) { // replace "substitution markers" ($1-$9) with macro param values (if any)
		if (!text || !args || !args.length) return text;
		var n=args.length; if (n>9) n=9;
		for(var i=0; i<n; i++) { var re=new RegExp("\\$" + (i + 1),"mg"); text=text.replace(re,args[i]); }
		return text;
	}
	function addTiddler(src,text,tids) { // extract tiddler(s) from text and create local copy
		if (!config.options.chkExternalTiddlersImport) return; // not enabled... do nothing
		if (!text || !tids || !tids.length) return; // no text or no tiddler list... do nothing
		var remoteStore=new TiddlyWiki();
		if (!remoteStore.importTiddlyWiki(text)) // not a TW document... create a single tiddler from text
			makeTiddler(src,text,tids[0]);
		else // TW document with "permaview-like" suffix... copy tiddler(s) from remote store
			for (var t=0;t<tids.length;t++)
				insertTiddler(src,remoteStore.getTiddler(tids[t]));
		return;
	}
	function makeTiddler(src,text,title) { // create a new tiddler object from text
		var who=config.options.txtUserName; var when=new Date();
		var msg="/%\n\nThis tiddler was automatically created using ExternalTiddlersPlugin\n";
		msg+="by %0 on %1\nsource: %2\n\n%/";
		var tags=config.options.txtExternalTiddlersTags.readBracketedList();
		if (config.options.chkExternalTiddlersTemporary) tags.pushUnique(config.options.txtTemporaryTag); 
		store.saveTiddler(null,title,msg.format([who,when,src])+text,who,when,tags,{});
		if (!config.options.chkExternalTiddlersQuiet) displayMessage("Created new tiddler '"+title+"' from text file "+src);
	}
	function insertTiddler(src,t) { // import a single tiddler object into the current document store
		if (!t) return;
		var who=config.options.txtUserName; var when=new Date();
		var msg="/%\n\nThis tiddler was automatically imported using ExternalTiddlersPlugin\n";
		msg+="by %0 on %1\nsource: %2\n\n%/";
		var newtags=new Array().concat(t.tags,config.options.txtExternalTiddlersTags.readBracketedList());
		if (config.options.chkExternalTiddlersTemporary) newtags.push(config.options.txtTemporaryTag);
		store.saveTiddler(null,t.title,msg.format([who,when,src])+t.text,t.modifier,t.modified,newtags,t.fields);
		if (!config.options.chkExternalTiddlersQuiet) displayMessage("Imported tiddler '"+t.title+"' from "+src);
	}
	function getGUID()  // create a Globally Unique ID (for async reference to DOM elements)
		 { return new Date().getTime()+Math.random().toString(); }

	// loop through "|"-separated list of alternative tiddler/file/URL references until successful
	var fallback="";
	for (var i=0; i<items.length; i++) { var src=items[i];
		// if tiddler (or shadow) exists, replace reference list with current source name and apply core handler
		if (store.getTiddlerText(src)) {
			arguments[2][0]=src; // params[] array
			var p=arguments[4].split(list); arguments[4]=p[0]+src+p[1]; // paramString
			this.externalTiddlers_handler.apply(this,arguments);
			break; // stop processing alternatives
		}
		// tiddler doesn't exist, and not an external file/URL reference... skip it
		if (!config.formatterHelpers.isExternalLink(src)) {
			if (!fallback.length) fallback=src; // title to use when importing external tiddler
			continue;
		}
		// separate 'permaview' list of tiddlers (if any) from file/URL (i.e., '#name name name..." suffix)
		var p=src.split("#"); src=p[0]; var tids=p[1]?p[1].readBracketedList(false):[];
		// if reference is to a remotely hosted document or the current document is remotely hosted...
		if (src.substr(0,4)=="http" || document.location.protocol.substr(0,4)=="http") {
			if (src.substr(0,4)!="http") // fixup URL for relative remote references
				{ var h=document.location.href; src=h.substr(0,h.lastIndexOf("/")+1)+src; }
			var wrapper = createTiddlyElement(place,"span",getGUID(),className); // create placeholder for async rendering
			var callback=function(success,params,text,src,xhr) { // ASYNC CALLBACK
				if (!success) { displayMessage(xhr.status); return; } // couldn't read remote file... report the error 
				if (params.fallback.length)
					addTiddler(params.url,text,params.tids.length?params.tids:[params.fallback]); // import tiddler
				var wrapper=document.getElementById(params.id); if (!wrapper) return; 
				wikify(substitute(extract(text,params.tids),params.args),wrapper); // ASYNC RENDER
			};
			var callbackparams={ url:src, id:wrapper.id, args:args, tids:tids, fallback:fallback }  // ASYNC PARAMS
			var name=config.options.txtRemoteUsername; // optional value
			var pass=config.options.txtRemotePassword; // optional value
			var x=doHttp("GET",src,null,null,name,pass,callback,callbackparams,null)
			if (typeof(x)=="string") // couldn't start XMLHttpRequest... report error
				{ displayMessage("error: cannot access "+src); displayMessage(x); }
			break; // can't tell if async read will succeed.... stop processing alternatives anyway.
		}
		else { // read file from local filesystem
			var text=loadFile(getLocalPath(src));
			if (!text) { // couldn't load file... fixup path for relative reference and retry...
				var h=document.location.href;
				var text=loadFile(getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf("/")+1)))+src);
			}
			if (text) { // test it again... if file was loaded OK, render it in a class wrapper
				if (fallback.length) // create new tiddler using primary source name (if any)
					addTiddler(src,text,tids.length?tids:[fallback]);
				var wrapper=createTiddlyElement(place,"span",null,className);
				wikify(substitute(extract(text,tids),args),wrapper); // render
				break; // stop processing alternatives
			}
		}
	}
};
//}}}
//~~(Part of the [[ForEachTiddlerPlugin]])~~//

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

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


''Using JavaScript''

To give you a lot of flexibility the [[ForEachTiddlerMacro]] uses JavaScript in its arguments. Even if you are not that familiar with JavaScript you may find forEachTiddler useful. Just have a look at the various ready-to-use [[ForEachTiddlerExamples]] and adapt them to your needs.

''The Elements of the Macro''

The arguments of the ForEachTiddlerMacro consist of multiple parts, each of them being optional.

<<slider chkFETInClause [[inClause]] "inClause" "inClause">>
<<slider chkFETWhereClause [[whereClause]] "whereClause" "whereClause">>
<<slider chkFETSortClause [[sortClause]] "sortClause" "sortClause">>
<<slider chkFETScriptClause [[scriptClause]] "scriptClause" "scriptClause">>
<<slider chkFETActions [[Action Specification]] "Action Specification" "Action Specification">>

''Using Macros and ">" inside the forEachTiddler Macro''

You may use other macro calls into the expression, especially in the actionParameters. To avoid that the {{{>>}}} of such a macro call is misinterpreted as the end of the {{{<<forEachTiddler...>>}}} macro you must escape the {{{>>}}} of the inner macro with {{{$))}}} E.g. if you want to use {{{<<tiddler ...>>}}} inside the {{{forEachTiddler}}} macro you have to write {{{<<tiddler ...$))}}}.

In addition it is necessary to escape single {{{>}}} with the text {{{$)}}}.

''Using {{{<<tiddler ... with: ...>>}}} to re-use ForEachTiddler definitions''

Sometimes you may want to use a certain ForEachTiddler definition in slight variations. E.g. you may want to list either the tiddlers tagged with "ToDo" and in the other case with "Done". To do so you may use "Tiddler parameters". Here an example:

Replace the variable part of the ForEachTiddler definition with $1 ($2,... $9 are supported). E.g. you may create the tiddler "ListTaggedTiddlers" like this
{{{
<<forEachTiddler 
 where 
 'tiddler.tags.contains("$1")'
>>
}}}

Now you can use the ListTaggedTiddlers for various specific tags, using the {{{<<tiddler ...>>}}} macro:
{{{
<<tiddler ListTaggedTiddlers with: "systemConfig">>
}}}
{{{
<<tiddler ListTaggedTiddlers with: "Plugin">>
}}}


See also [[ForEachTiddlerExamples]].
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description

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

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

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

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

!Code
***/
//{{{

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of 
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
	if (!idPrefix) {
		idPrefix = "store";
	}
	var lenPrefix = idPrefix.length;
	
	// Read the content of the given file
	var content = loadFile(this.getLocalPath(path));
	if(content === null) {
		throw "TiddlyWiki '"+path+"' not found.";
	}
	
	var tiddlyWiki = new TiddlyWiki();

	// Starting with TW 2.2 there is a helper function to import the tiddlers
	if (tiddlyWiki.importTiddlyWiki) {
		if (!tiddlyWiki.importTiddlyWiki(content))
			throw "File '"+path+"' is not a TiddlyWiki.";
		tiddlyWiki.dirty = false;
		return tiddlyWiki;
	}
	
	// The legacy code, for TW < 2.2
	
	// Locate the storeArea div's
	var posOpeningDiv = content.indexOf(startSaveArea);
	var posClosingDiv = content.lastIndexOf(endSaveArea);
	if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
		throw "File '"+path+"' is not a TiddlyWiki.";
	}
	var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
	
	// Create a "div" element that contains the storage text
	var myStorageDiv = document.createElement("div");
	myStorageDiv.innerHTML = storageText;
	myStorageDiv.normalize();
	
	// Create all tiddlers in a new TiddlyWiki
	// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
	var store = myStorageDiv.childNodes;
	for(var t = 0; t < store.length; t++) {
		var e = store[t];
		var title = null;
		if(e.getAttribute)
			title = e.getAttribute("tiddler");
		if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
			title = e.id.substr(lenPrefix);
		if(title && title !== "") {
			var tiddler = tiddlyWiki.createTiddler(title);
			tiddler.loadFromDiv(e,title);
		}
	}
	tiddlyWiki.dirty = false;

	return tiddlyWiki;
};


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

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

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

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

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

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

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

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


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

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


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

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

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

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

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

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


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



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


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

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

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

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


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


} // of "install only once"

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


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

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

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

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

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

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

This one DOES work.
<<slideShow>>
<<forEachTiddler 
 where
 'tiddler.tags.contains("show")'
 write
 '"[["+tiddler.title+"]]\n"'
>>
''Note:'' I know this is a poor and unnecessary example but fancier things can be done with the {{exclude{[[ForEachTiddlerPlugin]]}}}.
/***
<<checkForDataTiddlerPlugin>>
|''Name:''|FormTiddlerPlugin|
|''Version:''|1.0.6 (2007-06-24)|
|''Source:''|http://tiddlywiki.abego-software.de/#FormTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''Macros:''|formTiddler, checkForDataTiddlerPlugin, newTiddlerWithForm|
|''Requires:''|DataTiddlerPlugin|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Use form-based tiddlers to enter your tiddler data using text fields, listboxes, checkboxes etc. (All standard HTML Form input elements supported).

''Syntax:'' 
|>|{{{<<}}}''formTiddler'' //tiddlerName//{{{>>}}}|
|//tiddlerName//|The name of the FormTemplate tiddler to be used to edit the data of the tiddler containing the macro.|

|>|{{{<<}}}''newTiddlerWithForm'' //formTemplateName// //buttonLabel// [//titleExpression// [''askUser'']] {{{>>}}}|
|//formTemplateName//|The name of the tiddler that defines the form the new tiddler should use.|
|//buttonLabel//|The label of the button|
|//titleExpression//|A (quoted) JavaScript String expression that defines the title (/name) of the new tiddler.|
|''askUser''|Typically the user is not asked for the title when a title is specified (and not yet used). When ''askUser'' is given the user will be asked in any case. This may be used when the calculated title is just a suggestion that must be confirmed by the user|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|

For details and how to use the macros see the [[introduction|FormTiddler Introduction]] and the [[examples|FormTiddler Examples]].

!Revision history
* v1.0.6 (2007-06-24)
** Fixed problem when using SELECT component in Internet Explorer (thanks to MaikBoenig for reporting)
* v1.0.5 (2006-02-24)
** Removed "debugger;" instruction
* v1.0.4 (2006-02-07)
** Bug: On IE no data is written to data section when field values changed (thanks to KenGirard for reporting)
* v1.0.3 (2006-02-05)
** Bug: {{{"No form template specified in <<formTiddler>>"}}} when using formTiddler macro on InternetExplorer (thanks to KenGirard for reporting)
* v1.0.2 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.1 (2005-12-22)
** Features: 
*** Support InternetExplorer
*** Added newTiddlerWithForm Macro
* v1.0.0 (2005-12-14)
** initial version

!Code
***/
//{{{

//============================================================================
//============================================================================
//						FormTiddlerPlugin
//============================================================================
//============================================================================

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

abego.getOptionsValue = function(element,i) {
	var v = element.options[i].value;
	if (!v && element.options[i].text)
		v = element.options[i].text;
	return v;
};

version.extensions.FormTiddlerPlugin = {
	major: 1, minor: 0, revision: 5,
	date: new Date(2006, 2, 24), 
	type: 'plugin',
	source: "http://tiddlywiki.abego-software.de/#FormTiddlerPlugin"
};

// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window; 
if (!TiddlyWiki.prototype.getTiddler) TiddlyWiki.prototype.getTiddler = function(title) { return t = this.tiddlers[title]; return (t != undefined && t instanceof Tiddler) ? t : null; } 

//============================================================================
// formTiddler Macro
//============================================================================

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

config.macros.formTiddler = {
	// Standard Properties
	label: "formTiddler",
	version: {major: 1, minor: 0, revision: 4, date: new Date(2006, 2, 7)},
	prompt: "Edit tiddler data using forms",

	// Define the "setters" that set the values of INPUT elements of a given type
	// (must match the corresponding "getter")
	setter: {  
		button:				function(e, value) {/*contains no data */ },
		checkbox:			function(e, value) {e.checked = value;},
		file:				function(e, value) {try {e.value = value;} catch(e) {/* ignore, possibly security error*/}},
		hidden:				function(e, value) {e.value = value;},
		password:			function(e, value) {e.value = value;},
		radio:				function(e, value) {e.checked = (e.value == value);},
		reset:				function(e, value) {/*contains no data */ },
		"select-one":		function(e, value) {config.macros.formTiddler.setSelectOneValue(e,value);},
		"select-multiple":	function(e, value) {config.macros.formTiddler.setSelectMultipleValue(e,value);},
		submit:				function(e, value) {/*contains no data */},
		text:				function(e, value) {e.value = value;},
		textarea:			function(e, value) {e.value = value;}
	},

	// Define the "getters" that return the value of INPUT elements of a given type
	// Return undefined to not store any data.
	getter: {  
		button:				function(e, value) {return undefined;},
		checkbox:			function(e, value) {return e.checked;},
		file:				function(e, value) {return e.value;},
		hidden:				function(e, value) {return e.value;},
		password:			function(e, value) {return e.value;},
		radio:				function(e, value) {return e.checked ? e.value : undefined;},
		reset:				function(e, value) {return undefined;},
		"select-one":		function(e, value) {return config.macros.formTiddler.getSelectOneValue(e);},
		"select-multiple":	function(e, value) {return config.macros.formTiddler.getSelectMultipleValue(e);},
		submit:				function(e, value) {return undefined;},
		text:				function(e, value) {return e.value;},
		textarea:			function(e, value) {return e.value;}
	}
};


// -------------------------------------------------------------------------------
// The formTiddler Macro Handler 
// -------------------------------------------------------------------------------

config.macros.formTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	if (!config.macros.formTiddler.checkForExtensions(place, macroName)) {
		return;
	}
	// --- Parsing ------------------------------------------

	var i = 0; // index running over the params

	// get the name of the form template tiddler
	var formTemplateName = undefined;
	if (i < params.length) {
		formTemplateName = params[i];
		i++;
	}

	if (!formTemplateName) {
		config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");
		return;
	}


	// --- Processing ------------------------------------------

	// Get the form template text. 
	// (This contains the INPUT elements for the form.)
	var formTemplateTiddler = store.getTiddler(formTemplateName);
	if (!formTemplateTiddler) {
		config.macros.formTiddler.createErrorElement(place, "Form template '" + formTemplateName + "' not found.");
		return;
	}
	var templateText = formTemplateTiddler.text;
	if(!templateText) {
		// Shortcut: when template text is empty we do nothing.
		return;
	}

	// Get the name of the tiddler containing this "formTiddler" macro
	// (i.e. the tiddler, that will be edited and that contains the data)
	var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(place);

	// Append a "form" element. 
	var formName = "form"+formTemplateName+"__"+tiddlerName;
	var e = document.createElement("form");
	e.setAttribute("name", formName);
	place.appendChild(e);

	// "Embed" the elements defined by the templateText (i.e. the INPUT elements) 
	// into the "form" element we just created
	wikify(templateText, e);

	// Initialize the INPUT elements.
	config.macros.formTiddler.initValuesAndHandlersInFormElements(formName, DataTiddler.getDataObject(tiddlerName));
}


// -------------------------------------------------------------------------------
// Form Data Access 
// -------------------------------------------------------------------------------

// Internal.
//
// Initialize the INPUT elements of the form with the values of their "matching"
// data fields in the tiddler. Also setup the onChange handler to ensure that
// changes in the INPUT elements are stored in the tiddler's data.
//
config.macros.formTiddler.initValuesAndHandlersInFormElements = function(formName, data) {
	// config.macros.formTiddler.trace("initValuesAndHandlersInFormElements(formName="+formName+", data="+data+")");

	// find the form
	var form = config.macros.formTiddler.findForm(formName);
	if (!form) {
		return;
	}

	try {
		var elems = form.elements;
		for (var i = 0; i < elems.length; i++) {
			var c = elems[i];
		
			var setter = config.macros.formTiddler.setter[c.type];
			if (setter) {
				var value = data[c.name];
				if (value != null) {
					setter(c, value);
				}
				c.onchange = onFormTiddlerChange;
			} else {
				config.macros.formTiddler.displayFormTiddlerError("No setter defined for INPUT element of type '"+c.type+"'. (Element '"+c.name+"' in form '"+formName+"')");
			}
		}
	} catch(e) {
		config.macros.formTiddler.displayFormTiddlerError("Error when updating elements with new formData. "+e);
	}
}


// Internal.
//
// @return [may be null]
//
config.macros.formTiddler.findForm = function(formName) {
	// We must manually iterate through the document's forms, since
	// IE does not support the "document[formName]" approach

	var forms = window.document.forms;
	for (var i = 0; i < forms.length; i++) {
		var form = forms[i];
		if (form.name == formName) {
			return form;
		}
	}

	return null;
}


// Internal.
//
config.macros.formTiddler.setSelectOneValue = function(element,value) {
	var n = element.options.length;
	for (var i = 0; i < n; i++) {
		element.options[i].selected = abego.getOptionsValue(element,i) == value;
	}
}

// Internal.
//
config.macros.formTiddler.setSelectMultipleValue = function(element,value) {
	var values = {};
	for (var i = 0; i < value.length; i++) {
		values[value[i]] = true;
	}
	
	var n = element.length;
	for (var i = 0; i < n; i++) {
		element.options[i].selected = !(!values[abego.getOptionsValue(element,i)]);
	}
}

// Internal.
//
config.macros.formTiddler.getSelectOneValue = function(element) {
	var i = element.selectedIndex;
	return (i >= 0) ? abego.getOptionsValue(element,i) : null;
}

// Internal.
//
config.macros.formTiddler.getSelectMultipleValue = function(element) {
	var values = [];
	var n = element.length;
	for (var i = 0; i < n; i++) {
		if (element.options[i].selected) {
			values.push(abego.getOptionsValue(element,i));
		}
	}
	return values;
}



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

// Internal.
//
config.macros.formTiddler.checkForExtensions = function(place,macroName) {
	if (!version.extensions.DataTiddlerPlugin) {
		config.macros.formTiddler.createErrorElement(place, "<<" + macroName + ">> requires the DataTiddlerPlugin. (You can get it from http://tiddlywiki.abego-software.de/#DataTiddlerPlugin)");
		return false;
	}
	return true;
}

// Internal.
//
// Displays a trace message in the "TiddlyWiki" message pane.
// (used for debugging)
//
config.macros.formTiddler.trace = function(s) {
	displayMessage("Trace: "+s);
}

// Internal.
//
// Display some error message in the "TiddlyWiki" message pane.
//
config.macros.formTiddler.displayFormTiddlerError = function(s) {
	alert("FormTiddlerPlugin Error: "+s);
}

// Internal.
//
// Creates an element that holds an error message
// 
config.macros.formTiddler.createErrorElement = function(place, message) {
	return createTiddlyElement(place,"span",null,"formTiddlerError",message);
}

// Internal.
//
// Returns the name of the tiddler containing the given element.
// 
config.macros.formTiddler.getContainingTiddlerName = function(element) {
	return story.findContainingTiddler(element).id.substr(7);
}

// -------------------------------------------------------------------------------
// Event Handlers 
// -------------------------------------------------------------------------------

// This function must be called by the INPUT elements whenever their
// data changes. Typically this is done through an "onChange" handler.
//
function onFormTiddlerChange (e) {
	// config.macros.formTiddler.trace("onFormTiddlerChange "+e);

	if (!e) var e = window.event;

	var target = resolveTarget(e);
	var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(target);
	var getter = config.macros.formTiddler.getter[target.type];
	if (getter) {
		var value = getter(target);
		DataTiddler.setData(tiddlerName, target.name, value);
	} else {
		config.macros.formTiddler.displayFormTiddlerError("No getter defined for INPUT element of type '"+target.type+"'. (Element '"+target.name+"' used in tiddler '"+tiddlerName+"')");
	}
}

// ensure that the function can be used in HTML event handler
window.onFormTiddlerChange = onFormTiddlerChange;


// -------------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// -------------------------------------------------------------------------------

setStylesheet(
	".formTiddlerError{color: #ffffff;background-color: #880000;}",
	"formTiddler");


//============================================================================
// checkForDataTiddlerPlugin Macro
//============================================================================

config.macros.checkForDataTiddlerPlugin = {
	// Standard Properties
	label: "checkForDataTiddlerPlugin",
	version: {major: 1, minor: 0, revision: 0, date: new Date(2005, 12, 14)},
	prompt: "Check if the DataTiddlerPlugin exists"
}

config.macros.checkForDataTiddlerPlugin.handler = function(place,macroName,params) {
	config.macros.formTiddler.checkForExtensions(place, config.macros.formTiddler.label);
}



//============================================================================
// newTiddlerWithForm Macro
//============================================================================

config.macros.newTiddlerWithForm = {
	// Standard Properties
	label: "newTiddlerWithForm",
	version: {major: 1, minor: 0, revision: 1, date: new Date(2006, 1, 6)},
	prompt: "Creates a new Tiddler with a <<formTiddler ...>> macro"
}

config.macros.newTiddlerWithForm.handler = function(place,macroName,params) {
	// --- Parsing ------------------------------------------

	var i = 0; // index running over the params

	// get the name of the form template tiddler
	var formTemplateName = undefined;
	if (i < params.length) {
		formTemplateName = params[i];
		i++;
	}

	if (!formTemplateName) {
		config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");
		return;
	}

	// get the button label
	var buttonLabel = undefined;
	if (i < params.length) {
		buttonLabel = params[i];
		i++;
	}

	if (!buttonLabel) {
		config.macros.formTiddler.createErrorElement(place, "No button label specified in <<" + macroName + ">>.");
		return;
	}

	// get the (optional) tiddlerName script and "askUser"
	var tiddlerNameScript = undefined;
	var askUser = false;
	if (i < params.length) {
		tiddlerNameScript = params[i];
		i++;

		if (i < params.length && params[i] == "askUser") {
			askUser = true;
			i++;
		}
	}

	// --- Processing ------------------------------------------

	if(!readOnly) {
		var onClick = function() {
			var tiddlerName;
			if (tiddlerNameScript) {
				try {
					tiddlerName = eval(tiddlerNameScript);
				} catch (ex) {
				}
			}
			if (!tiddlerName || askUser) {
				tiddlerName = prompt("Please specify a tiddler name.", askUser ? tiddlerName : "");
			}
			while (tiddlerName && store.getTiddler(tiddlerName)) {
				tiddlerName = prompt("A tiddler named '"+tiddlerName+"' already exists.\n\n"+"Please specify a tiddler name.", tiddlerName);
			}

			// tiddlerName is either null (user canceled) or a name that is not yet in the store.
			if (tiddlerName) {
				var body = "<<formTiddler [["+formTemplateName+"]]>>";
				var tags = [];
				store.saveTiddler(tiddlerName,tiddlerName,body,config.options.txtUserName,new Date(),tags);
				story.displayTiddler(null,tiddlerName,1);
			}
		}

		createTiddlyButton(place,buttonLabel,buttonLabel,onClick);
    }
}

//}}}


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

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

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

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

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

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
/***
|Name|FramedLinksPlugin|
|Source|http://www.TiddlyTools.com/#FramedLinksPlugin|
|Version|1.1.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|clicking an external link opens an IFRAME following the link instead of opening a new tab/window|
This plugin causes clicks on external links to be rendered as inline frames (~IFRAMEs) instead of opening new browser tabs/windows.
!!!!!Usage
<<<
Use standard TiddlyWiki external link syntax into your tiddler content. If {{{chkFramedLinks}}} is enabled or the tiddler is tagged with 'framedLinks' (see Configuration), then whenever you click the external link an IFRAME will be dynamically added to the content.  Clicking on the link again removes the IFRAME.  Hold down any modifier (shift, control, or alt) while clicking a link ''temporarily'' bypasses the IFRAME handling and use the standard link handling behavior.
<<<
!!!!!Configuration
<<<
<<option chkFramedLinks>> display inline frames for all external links
&nbsp; &nbsp; {{{<<option chkFramedLinks>>}}}
<<option chkFramedLinksTag>> display inline frames for external links in tiddlers tagged with: <<option txtFramedLinksTag>> 
&nbsp; &nbsp; {{{<<option chkFramedLinksTag>> <<option txtFramedLinksTag>>}}}
IFRAME size (CSS units: %, em, px, cm, in) - width: <<option txtFrameWidth>> height: <<option txtFrameHeight>>
&nbsp; &nbsp; {{{<<option txtFrameWidth>> <<option txtFrameHeight>>}}}
<<<
!!!!!Examples
<<<
Try these links:
*http://www.TiddlyWiki.com
*http://www.TiddlyTools.com
*http://groups.google.com/group/TiddlyWiki/topics
<<<
!!!!!Revisions
<<<
2008.11.14 [1.1.1] fixed handling for external links embedded in //shadow// tiddlers
2008.09.13 [1.1.0] added support to selectively enable embedded IFRAMEs if the containing tiddler is tagged with 'framedLinks'
2007.11.29 [1.0.5] added slider animation and improved CSS handling for IFRAME height/width to maximize display area
2007.11.29 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.FramedLinksPlugin= {major: 1, minor: 1, revision: 1, date: new Date(2008,11,14)};

var co=config.options; // abbreviation
if (co.chkFramedLinks==undefined) co.chkFramedLinks=false;
if (co.chkFramedLinksTag==undefined) co.chkFramedLinksTag=true;
if (co.txtFramedLinksTag==undefined) co.txtFramedLinksTag="framedLinks";
if (co.txtFrameWidth==undefined) co.txtFrameWidth="100%";
if (co.txtFrameHeight==undefined) co.txtFrameHeight="80%";

window.framedLinks_createExternalLink=createExternalLink;
window.createExternalLink=function(place,url)
{
	var link=this.framedLinks_createExternalLink.apply(this,arguments);
	link.onclick=function(ev) { var e=ev?ev:window.event;
		var co=config.options; // abbreviation
		var here=story.findContainingTiddler(this);
		if (here) var tid=store.getTiddler(here.getAttribute("tiddler"));
		var enabled=co.chkFramedLinks || co.chkFramedLinksTag && tid && tid.isTagged(co.txtFramedLinksTag);
		if (!enabled || e.ctrlKey || e.shiftKey || e.altKey) return; // BYPASS
		var p=this.parentNode; 
		var f=this.nextSibling?this.nextSibling.firstChild:null; // get the IFRAME... maybe...
		var w=co.txtFrameWidth; if (!w || !w.length) w="100%";
		var h=co.txtFrameHeight; if (!h || !h.length) h="80%";
		if (h.indexOf("%")) h=(findWindowHeight()*h.replace(/%/,"")/100)+"px"; // calc height as % of window
		var showing=f && f.nodeName.toUpperCase()=="IFRAME"; // does IFRAME really exist?
		var stretchCell=p.nodeName.toUpperCase()=="TD" && w.indexOf("%")!=-1 && w.replace(/%/,"")>=100;
		if (!showing) { // create an iframe
			link.style.display="block"; // force IFRAME onto line following link
			if (stretchCell) { p.setAttribute("savedWidth",p.style.width); p.style.width="100%"; } // adjust TD so IFRAME stretches
			var wrapper=createTiddlyElement(null,"span"); // wrapper for slider animation
			wrapper.setAttribute("url",this.href); // for async loading of frame after animation completes
			var f=createTiddlyElement(wrapper,"iframe"); // create IFRAME
			f.style.backgroundColor="#fff"; f.style.width=w; f.style.height=h;
			p.insertBefore(wrapper,this.nextSibling);
			function loadURL(wrapper) { var f=wrapper.firstChild; var url=wrapper.getAttribute("url");
				var d=f.contentDocument?f.contentDocument:(f.contentWindow?f.contentWindow.document:f.document);
				d.open(); d.writeln("<html>connecting to "+url+"</html>"); d.close();
				try { f.src=url; } // if the iframe can't handle the href
				catch(e) { alert(e.description?e.description:e.toString()); } // ... then report the error
				window.scrollTo(0,ensureVisible(wrapper));
			}
			if (!co.chkAnimate) loadURL(wrapper);
			else {
				var morph=new Slider(wrapper,true);
				morph.callback=loadURL;
				morph.properties.push({style: 'width', start: 0, end: 100, template: '%0%'});
				anim.startAnimating(morph);
			}
		} else { // remove iframe
			link.style.display="inline"; // restore link style
			if (stretchCell) p.style.width=p.getAttribute("savedWidth"); // restore previous width of TD
			if (!co.chkAnimate) p.removeChild(f.parentNode);
			else {
				var morph=new Slider(f.parentNode,false,false,"all");
				morph.properties.push({style: 'width', start: 100, end: 0, template: '%0%'});
				anim.startAnimating(morph);
			}
		}
		e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); return false;
	}
	return link;
}
//}}}
!!!Calendario de Actividades
<html><div align="center"><iframe src="https://www.google.com/calendar/embed?showTitle=0&amp;mode=WEEK&amp;height=300&amp;wkst=2&amp;bgcolor=%23FFFFFF&amp;src=9j9a0a1iqgafvpq9sboahltdtc%40group.calendar.google.com&amp;color=%23B1440E&amp;src=hgnhn8qrt20ih333tummrmi7ps%40group.calendar.google.com&amp;color=%230D7813&amp;src=m.cardenas.escudero%40gmail.com&amp;color=%232952A3&amp;src=es.spain%23holiday%40group.v.calendar.google.com&amp;color=%23A32929&amp;src=p%23weather%40group.v.calendar.google.com&amp;color=%2388880E&amp;ctz=Europe%2FMadrid" style=" border-width:0 " width="500" height="300" frameborder="0" scrolling="no"></iframe></div></html>
|UploadUserName:|Cardenas|
|pasUploadPassword|lepe3lso1|
|UploadStoreUrl:|http://personal.us.es/mcard/store.php|
|UploadDir:|.|
|UploadFilename:|tw2.html|
|UploadBackupDir:|backup|
|txtUploadTiddlerStoreUrl|http://personal.us.es/mcard/storeTiddler.php|
To upload a TiddlyWiki on your web server:
#Import UploadPlugin from BidiXTW aka http://TiddlyWiki.bidix.info/
#Install an UploadService on your web server by configuring this scripts [[store.php]]
#set an {{{<<upload [params]>>}}} button for example in your SideBarOptions with {{{params}}} or UploadOptions as describe in UploadPluginDoc
#click on the <<upload>> button
Or sign at http://TiddlySpot.com/
 
/***
|Name|ImageSizePlugin|
|Source|http://www.TiddlyTools.com/#ImageSizePlugin|
|Version|1.2.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|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.4.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|config.macros.importTiddlers.handler|
|Description|interactive controls for import/export with filtering.|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Documentation
<<<
see [[ImportTiddlersPluginInfo]] for details
<<<
!!!!!interactive control panel:
<<<
<<importTiddlers inline>>
{{clear{
^^(see also: [[ImportTiddlers]] shadow tiddler)^^}}}
<<<
!!!!!Installation Notes
<<<
* As of 6/27/2007, supporting functions for TW2.1.x and earlier have been moved to [[ImportTiddlersPluginPatch]] tiddler to reduce installation overhead for //this// plugin.  Only install the patch plugin when using TW2.1.x or earlier.
* As of 3/21/2007, {{{<<importTiddlers>>}}} and {{{<<loadTiddlers>>}}} macro definitions have been split into [[ImportTiddlersPlugin]] and [[LoadTiddlersPlugin]] to permit separate installation of either macro, as needed.
<<<
!!!!!Revisions
<<<
2009.03.04 [4.4.2] in createImportPanel(), init option checkboxes from internal config values
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImportTiddlersPlugin= {major: 4, minor: 4, revision: 2, date: new Date(2009,3,5)};

// 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(cmi.css,'importTiddlers');
	panel=createTiddlyElement(place,'span','importPanel',null,null)
	panel.innerHTML=cmi.html;
	refreshImportList();
	var siteURL=store.getTiddlerText('SiteUrl'); if (!siteURL) siteURL='';
	cmi.$('importSourceURL').value=siteURL;
	cmi.src=siteURL;
	var siteProxy=store.getTiddlerText('SiteProxy'); if (!siteProxy) siteProxy='SiteProxy';
	cmi.$('importSiteProxy').value=siteProxy;
	cmi.proxy=siteProxy;
	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;
}
//}}}
//{{{
config.macros.importTiddlers.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; }\
';
//}}}
//{{{
config.macros.importTiddlers.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="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="onClickImportButton(this);return false;" title="SELECT all tiddlers">\
	all</a>\
&nbsp;<a href="javascript:;" id="importSelectNew"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers not already in destination document">\
	added</a>\
&nbsp;<a href="javascript:;" id="importSelectChanges"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been updated in source document">\
	changes</a>\
&nbsp;<a href="javascript:;" id="importSelectDifferences"\
	onclick="onClickImportButton(this);return false;" 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="onClickImportButton(this);return false;" title="SHRINK list size">\
	&nbsp;&#150;&nbsp;</a>\
<a href="javascript:;" id="importListLarger"\
	onclick="onClickImportButton(this);return false;" title="GROW list size">\
	&nbsp;+&nbsp;</a>\
<a href="javascript:;" id="importListMaximize"\
	onclick="onClickImportButton(this);return false;" 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:\\n\\ntiddler titles\\ntag:[[tagvalue]]\\ntag:[[tag expression]] (requires MatchTagsPlugin)\\nstory:[[TiddlerName]]\\nsearch:[[searchtext]]\\n\\nUse a blank filter for all tiddlers.\')"\
	>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="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-->\
';
//}}}
//{{{
// process control interactions
function onClickImportButton(which,event) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var list=cmi.$('importList'); if (!list) return;
	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;
			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(p,false);
			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?'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 (callback) callback(true,original,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
		var xhr=doHttp('GET',src,null,null,name,pass,callback,original,null)
		if (!xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,'(XMLHTTPRequest error)']));
	}
}

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

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);
	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;
}
//}}}
/***
|Name|ImportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.4.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|documentation|
|Requires||
|Overrides||
|Description|documentation for ImportTiddlersPlugin|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!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: When loading a remote document, there may be some 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 (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items).  You can also click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in, 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)

When you have chosen the tiddlers you want, press ''[import]'' to begin copying them to the current TiddlyWiki document.  When importing a tiddler whose title matches one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''skip'', ''rename'', ''merge'' and ''replace''.
* ''skip'' bypasses importing the tiddler
* ''rename'' allows you to enter a new title in the input field to give the inbound tiddler a different name, so that both the old and new tiddlers will exist when the import is done.
* ''merge'' combines the content from both tiddlers into a single tiddler so you can then edit it to eliminate unwanted content.
* ''[replace]'' overwrites the existing tiddler with the imported one, discarding the previous tiddler content.

''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 reverse-chronological history of imports is maintained.  If this cumulative 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
<<<
!!!!!Revisions
<<<
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 as an optional alternative to the standard import wizard.  (Moved from BackstageTweaks).
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, so the plugin control panel is displayed instead of the standard core interface.
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 backward-compatibility with TW2.1.x to separate [[ImportTiddlersPluginPatch2.1.x]] tiddler, reducing the size of //this// plugin tiddler by a significant amount.
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] if 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 location and try again.  Allows use of simple "foo.html" file references with importTiddlers and/or loadTiddlers macros
2007.02.24 [3.2.1] re-labeled control panel "open" button to "load" to avoid confusion with "open" button in system-provided Browse... dialog.  (i.e., "browse, open, open" becomes "browse, open, 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 TW2.1 built-in importTiddlers.handler() so it can co-exist with the plugin interface 'panel'.  Use macro without params (or use 'core' keyword) to display built-in core interface.  Use new "link" param to embed "import tiddlers" link that shows floating panel when clicked.  Renamed a few plugin utility functions so they don't collide with core internal functions.  More code restructuring to come.
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 ZW and other adaptations that hijack low-level tiddler handling.  Also, in CreateImportPanel(), no longer register notify to "refresh listbox after every tiddler change" (left over from old 'auto-filtered' list handling).  Thanks to Bob McElrath for report/solution.
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] additional refactoring of 'core candidate' code.  Proposed API now defines "loadRemoteFile()" for XMLHttpRequest processing with built in fallback for handling local filesystem access, and readTiddlersFromHTML() to process the resulting source HTML content.
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.  Also, ImportedTiddlers report generator output has been simplified and "importReplace/importPublic" tags and associated "force" param (which were rarely, if ever, used) has been dropped.
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 (IE does *not* define these values, so we bypass this code)
Also, when extracting store area from remote URL, explicitly look for "</body>\n</html>" to exclude any extra content that may have been added to the end of the file by hosting environments such as GeoCities.  Thanks to Tom Otvos for finding these bugs and suggesting some fixes.
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 for selecting dynamic import source controls in ImportPanel.  Default file control is replaced with URL text input field when "web server" is selected.  Default remote document URL is defined in SiteURL tiddler.  Also, added option for prepending SiteProxy URL as prefix to remote URL to mask cross-domain document access (requires compatible server-side script)
2006.02.17 [2.6.0] Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences.  Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.
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.  Clear the checkbox to skip this step.
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 individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax.  Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.
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.  Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins).  Seems to resolve the "Found 0 tiddlers" problem.  Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.
2006.01.12 [2.3.0] Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest.  Let's processing continue while waiting for remote hosts to respond to URL requests.  Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source.  Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.
2006.01.11 [2.2.0] Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck
2006.01.09 [2.1.1] When a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button.  This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit.  I removed the onChange handling for file input field.  To open a file (local or URL), you must now explicitly press the "open" button in the control panel.
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
<<<
/***
|Name|ImportTiddlersPluginPatch|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPluginPatch|
|Version|4.4.0|
|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|ImportTiddlersPlugin|
|Overrides|config.macros.importTiddlers.handler|
|Description|backward-compatible function patches for use with ImportTiddlersPlugin and TW2.1.x or earlier|
!!!!!Usage
<<<
The current version ImportTiddlersPlugin is compatible with the TW2.2.x core functions.  This "patch" plugin provides additional functions needed to enable the current version of ImportTiddlersPlugin to operate correctly under TW2.1.x or earlier.

{{medium{You do not need to install this plugin if you are using TW2.2.0 or above}}}
(though it won't hurt anything if you do... it will just take up more space).
<<<
!!!!!Revisions
<<<
2008.09.30 [4.4.0] added safety check for TW21Loader object and forward-compatible loadFromDiv() prototype to permit use with TW2.0.x and TW1.2.x.
2008.08.05 [4.3.2] rewrote loadRemoteFile to eliminate use of platform-specific fileExists() function
2008.01.03 [3.6.0] added support for passing txtRemoteUsername and txtRemotePassword for accessing password-protected remote servers
2007.06.27 [3.5.5] compatibility functions split from ImportTiddlersPlugin
|please see [[ImportTiddlersPlugin]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
// these functions are only defined when installed in TW2.1.x and earlier... 
if (version.major+version.minor/10 <= 2.1) {

// Version
version.extensions.ImportTiddlersPluginPatch= {major: 4, minor: 4, revision: 0, date: new Date(2008,9,30)};

// fixups for TW2.0.x and earlier
if (window.merge==undefined) window.merge=function(dst,src,preserveExisting)
	{ for (p in src) if (!preserveExisting||dst[p]===undefined) dst[p]=src[p]; return dst; }
if (config.macros.importTiddlers==undefined) config.macros.importTiddlers={ };

config.macros.importTiddlers.loadRemoteFile = function(src,callback,quiet) {
	if (src==undefined || !src.length) return null; // filename is required
	if (!quiet) clearMessage();
	if (!quiet) displayMessage(this.openMsg.format([src]));

	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
			if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,src,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var x; // get an request object
		try {x = new XMLHttpRequest()} // moz
		catch(e) {
			try {x = new ActiveXObject("Msxml2.XMLHTTP")} // IE 6
			catch (e) {
				try {x = new ActiveXObject("Microsoft.XMLHTTP")} // IE 5
				catch (e) { return }
			}
		}
		// setup callback function to handle server response(s)
		x.onreadystatechange = function() {
			if (x.readyState == 4) {
				if (x.status==0 || x.status == 200) {
					if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([x.responseText.length,src]));
					if (callback) callback(true,src,x.responseText,src,x);
				}
				else {
					if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,x.status]));
				}
			}
		}
		// get privileges to read another document's DOM via http:// or file:// (moz-only)
		if (typeof(netscape)!="undefined") {
			try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }
			catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }
		}
		// send the HTTP request
		try {
			var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();
			x.open("GET",src,true,config.options.txtRemoteUsername,config.options.txtRemotePassword);
			if (x.overrideMimeType) x.overrideMimeType('text/html');
			x.send(null);
		}
		catch (e) {
			if (!quiet) {
				displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(unknown)"]));
				displayMessage(e.description?e.description:e.toString());
			}
		}
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html) {
	// for TW2.1 and earlier
	// extract store area from html 
	var start=html.indexOf('<div id="storeArea">');
	var end=html.indexOf("<!--POST-BODY-START--"+">",start);
	if (end==-1) var end=html.indexOf("</body"+">",start); // backward-compatibility for older documents
	var sa="<html><body>"+html.substring(start,end)+"</body></html>";

	// load html into iframe document
	var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);
	f=document.createElement("iframe"); f.id="loaderFrame";
	f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
	document.body.appendChild(f);
	var d=f.document;
	if (f.contentDocument) d=f.contentDocument; // For NS6
	else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
	d.open(); d.writeln(sa); d.close();

	// read tiddler DIVs from storeArea DOM element	
	var sa = d.getElementById("storeArea");
	if (!sa) return null;
	sa.normalize();
	var nodes = sa.childNodes;
	if (!nodes || !nodes.length) return null;
	var tiddlers = [];
	for(var t = 0; t < nodes.length; t++) {
		var title = null;
		if(nodes[t].getAttribute)
			title = nodes[t].getAttribute("title"); // TW 2.2+
		if(!title && nodes[t].getAttribute)
			title = nodes[t].getAttribute("tiddler"); // TW 2.1.x
		if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))
			title = nodes[t].id.substr(5); // TW 1.2.x
		if(title && title != "")
			tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));
	}
	return tiddlers;
}

// // FORWARD-COMPATIBLE SUPPORT FOR TW2.1.x
// // enables reading tiddler definitions using TW2.2+ storeArea format, even when plugin is running under TW2.1.x
if (typeof TW21Loader!="undefined") {
TW21Loader.prototype.internalizeTiddler = function(store,tiddler,title,node) {
	var e = node.firstChild;
	var text = null;
	if(node.getAttribute("tiddler"))
		text = getNodeText(e).unescapeLineBreaks();
	else {
		while(e.nodeName!="PRE" && e.nodeName!="pre") e = e.nextSibling;
		text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
	}
	var modifier = node.getAttribute("modifier");
	var c = node.getAttribute("created");
	var m = node.getAttribute("modified");
	var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date;
	var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created;
	var tags = node.getAttribute("tags");
	var fields = {};
	var attrs = node.attributes;
	for(var i = attrs.length-1; i >= 0; i--) {
		var name = attrs[i].name;
		if (attrs[i].specified && !TiddlyWiki.isStandardField(name))
			fields[name] = attrs[i].value.unescapeLineBreaks();
		
	}
	tiddler.assign(title,text,modifier,modified,tags,created,fields);
	return tiddler;
};
}

// FORWARD-COMPATIBLE SUPPORT FOR TW2.0.x and TW1.2.x
// enables reading tiddler definitions using TW2.2+ storeArea format, even when plugin is running under TW2.0.x or TW1.2.x
if (typeof Tiddler.prototype.loadFromDiv!="undefined") {
Tiddler.prototype.loadFromDiv = function(node,title) { // Load a tiddler from an HTML DIV
	var e = node.firstChild;
	var text = null;
	if(node.getAttribute("tiddler")) {
		// get merged text from adjacent text nodes
		var t=""; while(e&&e.nodeName=="#text") { t+=e.nodeValue; e=e.nextSibling; }
		text = Tiddler.unescapeLineBreaks(t);
	} else {
		while(e.nodeName!="PRE" && e.nodeName!="pre") e = e.nextSibling;
		text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
	}
	var modifier = node.getAttribute("modifier");
	var c = node.getAttribute("created");
	var m = node.getAttribute("modified");
	var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date;
	var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created;
	var tags = node.getAttribute("tags");
	this.set(title,text,modifier,modified,tags,created);
	return this;
}
}

} // END OF pre-TW2.2 backward-compatibility functions
//}}}
On Wed 02 Nov 2011 09:27:33 AM CET, Ramkikura imported 2 tiddlers from
[[file:///home/olmy/Dropbox/tiddly/empty.recovered.upgraded.html|file:///home/olmy/Dropbox/tiddly/empty.recovered.upgraded.html]]:
<<<
#[[StyleSheet]] - added
#[[StyleSheetShortcuts]] - added
<<<

----
On Wed 02 Nov 2011 09:22:58 AM CET, Ramkikura imported 1 tiddler from
[[file:///home/olmy/Dropbox/tiddly/empty.recovered.upgraded.html|file:///home/olmy/Dropbox/tiddly/empty.recovered.upgraded.html]]:
<<<
#[[TiddlersBarPlugin]] - replaces TiddlersBarPlugin - 7/4/2011 18:53:00 by YourName
<<<
/***
|''Name:''|abego.IncludePlugin|
|''Version:''|1.0.1 (2007-04-30)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IncludePlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IncludePlugin Documentation|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]]|
|''Community:''|([[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23IncludePlugin]]) ([[Support|http://groups.google.com/group/TiddlyWiki]])|
|''Copyright:''|&copy; 2007 [[abego Software|http://www.abego-software.de]]|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''~CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.5.0.9 or better; Internet Explorer 6.0|
***/
/***
This plugin's source code is compressed (and hidden). Use this [[link|http://tiddlywiki.abego-software.de/archive/IncludePlugin/Plugin-Include-src.1.0.0.js]] to get the readable source code.
***/
///%
if(!window.abego){window.abego={};}var invokeLater=function(_1,_2,_3){return abego.invokeLater?abego.invokeLater(_1,_2,_3):setTimeout(_1,_2);};abego.loadFile=function(_4,_5,_6){var _7=function(_8,_9,_a,_b,_c){return _8?_5(_a,_b,_9):_5(undefined,_b,_9,"Error loading %0".format([_b]));};if(_4.search(/^((http(s)?)|(file)):/)!=0){if(_4.search(/^((.\:\\)|(\\\\)|(\/))/)==0){_4="file://"+_4;}else{var _d=document.location.toString();var i=_d.lastIndexOf("/");_4=_d.substr(0,i+1)+_4;}_4=_4.replace(/\\/mg,"/");}loadRemoteFile(_4,_7,_6);};abego.loadTiddlyWikiStore=function(_f,_10,_11,_12){var _13=function(_14,_15){if(_12){_12(_14,"abego.loadTiddlyWikiStore",_15,_f,_11);}};var _16=function(_17,_18){var _19=_18.indexOf(startSaveArea);var _1a=_18.indexOf("<!--POST-BODY-END--"+">");var _1b=_18.lastIndexOf(endSaveArea,_1a==-1?_18.length:_1a);if((_19==-1)||(_1b==-1)){return config.messages.invalidFileError.format([_f]);}var _1c="<html><body>"+_18.substring(_19,_1b+endSaveArea.length)+"</body></html>";var _1d=document.createElement("iframe");_1d.style.display="none";document.body.appendChild(_1d);var doc=_1d.document;if(_1d.contentDocument){doc=_1d.contentDocument;}else{if(_1d.contentWindow){doc=_1d.contentWindow.document;}}doc.open();doc.writeln(_1c);doc.close();var _1f=doc.getElementById("storeArea");_17.loadFromDiv(_1f,"store");_1d.parentNode.removeChild(_1d);return null;};var _20=function(_21){_13("Error when loading %0".format([_f]),"Failed");_10(undefined,_f,_11,_21);return _21;};var _22=function(_23){_13("Loaded %0".format([_f]),"Done");_10(_23,_f,_11);return null;};var _24=function(_25,_26,_27,_28){if(_25===undefined){_20(_28);return;}_13("Processing %0".format([_f]),"Processing");var _29=config.messages.invalidFileError;config.messages.invalidFileError="The file '%0' does not appear to be a valid TiddlyWiki file";try{var _2a=new TiddlyWiki();var _2b=_16(_2a,_25);if(_2b){_20(_2b);}else{_22(_2a);}}catch(ex){_20(exceptionText(ex));}finally{config.messages.invalidFileError=_29;}};_13("Start loading %0".format([_f]),"Started");abego.loadFile(_f,_24,_11);};(function(){if(abego.TiddlyWikiIncluder){return;}var _2c="waiting";var _2d="loading";var _2e=1000;var _2f=-200;var _30=-100;var _31=-300;var _32;var _33=[];var _34={};var _35=[];var _36;var _37=[];var _38;var _39=function(){if(_32===undefined){_32=config.options.chkUseInclude===undefined||config.options.chkUseInclude;}return _32;};var _3a=function(url){return "No include specified for %0".format([url]);};var _3c=function(){var _3d=_35;_35=[];if(_3d.length){for(var i=0;i<_37.length;i++){_37[i](_3d);}}};var _3f;var _40=function(){if(_36!==undefined){clearInterval(_36);}_3f=0;var _41=function(){abego.TiddlyWikiIncluder.sendProgress("","","Done");};_36=setInterval(function(){_3f++;if(_3f<=10){return;}clearInterval(_36);_36=undefined;abego.TiddlyWikiIncluder.sendProgress("Refreshing...","","");refreshDisplay();invokeLater(_41,0,_2f);},1);};var _42=function(_43){var _44;for(var i=0;i<_33.length;i++){var _46=abego.TiddlyWikiIncluder.getStore(_33[i]);if(_46&&(_44=_43(_46,_33[i]))){return _44;}}};var _47=function(){if(!window.store){return invokeLater(_47,100);}var _48=store.fetchTiddler;store.fetchTiddler=function(_49){var t=_48.apply(this,arguments);if(t){return t;}if(config.shadowTiddlers[_49]!==undefined){return undefined;}if(_49==config.macros.newTiddler.title){return undefined;}return _42(function(_4b,url){var t=_4b.fetchTiddler(_49);if(t){t.includeURL=url;}return t;});};if(_33.length){_40();}};var _4e=function(){if(!window.store){return invokeLater(_4e,100);}var _4f=store.getTiddlerText("IncludeList");if(_4f){wikify(_4f,document.createElement("div"));}};var _50=function(_51){var _52=function(){var _53=store.forEachTiddler;var _54=function(_55){var _56={};var _57;var _58=function(_59,_5a){if(_56[_59]){return;}_56[_59]=1;if(_57){_5a.includeURL=_57;}_55.apply(this,arguments);};_53.call(store,_58);for(var n in config.shadowTiddlers){_56[n]=1;}_56[config.macros.newTiddler.title]=1;_42(function(_5c,url){_57=url;_5c.forEachTiddler(_58);});};store.forEachTiddler=_54;try{return _51.apply(this,arguments);}finally{store.forEachTiddler=_53;}};return _52;};var _5e=function(_5f,_60){return _5f[_60]=_50(_5f[_60]);};abego.TiddlyWikiIncluder={};abego.TiddlyWikiIncluder.setProgressFunction=function(_61){_38=_61;};abego.TiddlyWikiIncluder.getProgressFunction=function(_62){return _38;};abego.TiddlyWikiIncluder.sendProgress=function(_63,_64,_65){if(_38){_38.apply(this,arguments);}};abego.TiddlyWikiIncluder.onError=function(url,_67){displayMessage("Error when including '%0':\n%1".format([url,_67]));};abego.TiddlyWikiIncluder.hasPendingIncludes=function(){for(var i=0;i<_33.length;i++){var _69=abego.TiddlyWikiIncluder.getState(_33[i]);if(_69==_2c||_69==_2d){return true;}}return false;};abego.TiddlyWikiIncluder.getIncludes=function(){return _33.slice();};abego.TiddlyWikiIncluder.getState=function(url){var s=_34[url];if(!s){return _3a(url);}return typeof s=="string"?s:null;};abego.TiddlyWikiIncluder.getStore=function(url){var s=_34[url];if(!s){return _3a(url);}return s instanceof TiddlyWiki?s:null;};abego.TiddlyWikiIncluder.include=function(url,_6f){if(!_39()||_34[url]){return;}var _70=this;_33.push(url);_34[url]=_2c;var _71=function(_72,_73,_74,_75){if(_72===undefined){_34[url]=_75;_70.onError(url,_75);return;}_34[url]=_72;_35.push(url);invokeLater(_3c);};var _76=function(){_34[url]=_2d;abego.loadTiddlyWikiStore(url,_71,null,_38);};if(_6f){invokeLater(_76,_6f);}else{_76();}};abego.TiddlyWikiIncluder.forReallyEachTiddler=function(_77){var _78=function(){store.forEachTiddler(_77);};_50(_78).call(store);};abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler=_50;abego.TiddlyWikiIncluder.useForReallyEachTiddler=_5e;abego.TiddlyWikiIncluder.addListener=function(_79){_37.push(_79);};abego.TiddlyWikiIncluder.addListener(_40);if(config.options.chkUseInclude===undefined){config.options.chkUseInclude=true;}config.shadowTiddlers.AdvancedOptions+="\n<<option chkUseInclude>> Include ~TiddlyWikis (IncludeList | IncludeState | [[help|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]])\n^^(Reload this ~TiddlyWiki to make changes become effective)^^";config.shadowTiddlers.IncludeState="<<includeState>>";var _7a=function(e,_7c,_7d){if(!anim||!abego.ShowAnimation){e.style.display=_7c?"block":"none";return;}anim.startAnimating(new abego.ShowAnimation(e,_7c,_7d));};abego.TiddlyWikiIncluder.getDefaultProgressFunction=function(){setStylesheet(".includeProgressState{\n"+"background-color:#FFCC00;\n"+"position:absolute;\n"+"right:0.2em;\n"+"top:0.2em;\n"+"width:7em;\n"+"padding-left:0.2em;\n"+"padding-right:0.2em\n"+"}\n","abegoInclude");var _7e=function(){var e=document.createElement("div");e.className="includeProgressState";e.style.display="none";document.body.appendChild(e);return e;};var _80=_7e();var _81=function(_82){removeChildren(_80);createTiddlyText(_80,_82);_7a(_80,true,0);};var _83=function(){invokeLater(function(){_7a(_80,false,_2e);},100,_30);};var _84=function(_85,_86,_87,url,_89){if(_87=="Done"||_87=="Failed"){_83();return;}if(_86=="abego.loadTiddlyWikiStore"){_3f=0;if(_87=="Processing"){_81("Including...");}}else{_81(_85);}};return _84;};abego.TiddlyWikiIncluder.setProgressFunction(abego.TiddlyWikiIncluder.getDefaultProgressFunction());config.macros.include={};config.macros.include.handler=function(_8a,_8b,_8c,_8d,_8e,_8f){_8c=_8e.parseParams("url",null,true,false,true);var _90=parseInt(getParam(_8c,"delay","0"));var _91=_8c[0]["url"];var _92=getFlag(_8c,"hide",false);if(!_92){createTiddlyText(createTiddlyElement(_8a,"code"),_8d.source.substring(_8d.matchStart,_8d.nextMatch));}for(var i=0;_91&&i<_91.length;i++){abego.TiddlyWikiIncluder.include(_91[i],_90);}};config.macros.includeState={};config.macros.includeState.handler=function(_94,_95,_96,_97,_98,_99){var _9a=function(){var s="";var _9c=abego.TiddlyWikiIncluder.getIncludes();if(!_9c.length){return "{{noIncludes{\nNo includes or 'include' is disabled (see AdvancedOptions)\n}}}\n";}s+="|!Address|!State|\n";for(var i=0;i<_9c.length;i++){var inc=_9c[i];s+="|{{{"+inc+"}}}|";var t=abego.TiddlyWikiIncluder.getState(inc);s+=t?"{{{"+t+"}}}":"included";s+="|\n";}s+="|includeState|k\n";return s;};var _a0=function(){removeChildren(div);wikify(_9a(),div);if(abego.TiddlyWikiIncluder.hasPendingIncludes()){invokeLater(_a0,500,_31);}};var div=createTiddlyElement(_94,"div");invokeLater(_a0,0,_31);};var _a2=Tiddler.prototype.isReadOnly;Tiddler.prototype.isReadOnly=function(){return _a2.apply(this,arguments)||this.isIncluded();};Tiddler.prototype.isIncluded=function(){return this.includeURL!=undefined;};Tiddler.prototype.getIncludeURL=function(){return this.includeURL;};var _a3={getMissingLinks:1,getOrphans:1,getTags:1,reverseLookup:1,updateTiddlers:1};for(var n in _a3){_5e(TiddlyWiki.prototype,n);}var _a5=function(){if(abego.IntelliTagger){_5e(abego.IntelliTagger,"assistTagging");}};var _a6=function(){if(config.macros.forEachTiddler){_5e(config.macros.forEachTiddler,"findTiddlers");}};_47();invokeLater(_4e,100);invokeLater(_a5,100);invokeLater(_a6,100);})();
//%/
/***
|''Name:''|LaunchApplicationPlugin|
|''Author:''|Lyall Pearce|
|''Source:''|http://www.Remotely-Helpful.com/TiddlyWiki/LaunchApplication.html|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Version:''|1.4.0|
|''~CoreVersion:''|2.3.0|
|''Requires:''| |
|''Overrides:''| |
|''Description:''|Launch an application from within TiddlyWiki using a button|
!!!!!Usage
<<<
{{{<<LaunchApplication "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationButton "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationLink "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
* buttonLabel is anything you like
* tooltip is anything you like
* application is a path to the executable (which is Operating System dependant)
* arguments is any command line arguments the application requires.
* You must supply relative path from the location of the TiddlyWiki OR a fully qualified path
* Forward slashes works fine for Windows

{{{<<LaunchApplication...>>}}} functions the same as {{{<<LaunchApplicationButton...>>}}}

eg.

{{{
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>
}}}
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>

{{{
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
}}}
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
					     
{{{
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>
}}}
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>

{{{
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>
}}}
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>


!!!!!Revision History
* 1.1.0 - leveraged some tweaks from from Bradly Meck's version (http://bradleymeck.tiddlyspot.com/#LaunchApplicationPlugin) and the example text.
* 1.2.0 - Make launching work in Linux too and use displayMessage() to give diagnostics/status info.
* 1.3.0 - execute programs relative to TiddlyWiki html file plus fix to args for firefox.
* 1.3.1 - parameters to the macro are properly parsed, allowing dynamic paramters using {{{ {{javascript}} }}} notation.
* 1.4.0 - updated core version and fixed empty tooltip and added launch link capability

<<<
***/
//{{{
version.extensions.LaunchApplication = {major: 1, minor: 4, revision: 0, date: new Date(2007,12,29)};
config.macros.LaunchApplication = {};
config.macros.LaunchApplicationButton = {};
config.macros.LaunchApplicationLink = {};

function LaunchApplication(appToLaunch,appParams) {
    if(! appToLaunch)
	return;
    var tiddlyBaseDir = self.location.pathname.substring(0,self.location.pathname.lastIndexOf("\\")+1);
    if(!tiddlyBaseDir || tiddlyBaseDir == "") {
	tiddlyBaseDir = self.location.pathname.substring(0,self.location.pathname.lastIndexOf("/")+1);
    }
    // if Returns with a leading slash, we don't want that.
    if(tiddlyBaseDir.substring(0,1) == "/") {
	tiddlyBaseDir = tiddlyBaseDir.substring(1);
    }
    if(appToLaunch.indexOf("file:///") == 0) // windows would have C:\ as the resulting file
    {
	tiddlyBaseDir = "";
	appToLaunch = appToLaunch.substring(8);
    }

    if (config.browser.isIE) {
	// want where the tiddly is actually located, excluding tiddly html file

	var theShell = new ActiveXObject("WScript.Shell");
	if(theShell) {
            // the app name may have a directory component, need that too
	    // as we want to start with current working dir as the location
	    // of the app.
	    var appDir = appToLaunch.substring(0, appToLaunch.lastIndexOf("\\"));
	    if(! appDir || appDir == "") {
		appDir = appToLaunch.substring(0, appToLaunch.lastIndexOf("/"));
	    }
	    appParams = appParams.length > 0 ? " \""+appParams.join("\" \"")+"\"" : "";
	    try {
		theShell.CurrentDirectory = decodeURI(tiddlyBaseDir + appDir);
		var commandString = ('"' +decodeURI(tiddlyBaseDir+appToLaunch) + '" ' + appParams);
		pluginInfo.log.push(commandString);
	        theShell.run(commandString);
	    } catch (e) {
		displayMessage("LaunchApplication cannot locate/execute file '"+tiddlyBaseDir+appToLaunch+"'");
		return;
	    }
	} else {
	    displayMessage("LaunchApplication failed to create ActiveX component WScript.Shell");
	}
    } else { // Not IE
	// want where the tiddly is actually located, excluding tiddly html file
	netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
        var launchString;
	try { // try linux/unix format
            launchString = decodeURI(tiddlyBaseDir+appToLaunch);
	    file.initWithPath(launchString);
	} catch (e) {
	    try { // leading slash on tiddlyBaseDir
                launchString = decodeURI("/"+tiddlyBaseDir+appToLaunch);
		file.initWithPath(launchString);
	    } catch (e) {
		try { // try windows format
		    launchString = decodeURI(appToLaunch).replace(/\//g,"\\");
		    file.initWithPath(launchString);
		} catch (e) {
		    try { // try windows format
			launchString = decodeURI(tiddlyBaseDir+appToLaunch).replace(/\//g,"\\");
			file.initWithPath(launchString);
		    } catch (e) {
			displayMessage("LaunchApplication cannot locate file '"+launchString+"' : "+e);
			return;
		    } // try windows mode
		} // try windows mode
	    }; // try with leading slash in tiddlyBaseDir
	}; // try linux/unix mode
	try {
	    if (file.isFile() && file.isExecutable()) {
		displayMessage("LaunchApplication executing '"+launchString+"' "+appParams.join(" "));
		var process = Components.classes['@mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
		process.init(file);
		process.run(false, appParams, appParams.length);
	    }
	    else
	    {
		displayMessage("LaunchApplication launching '"+launchString+"' "+appParams.join(" "));
		file.launch(); // No args available with this option
	    }
	} catch (e) {
	    displayMessage("LaunchApplication cannot execute/launch file '"+launchString+"'");
	}
    }
};

config.macros.LaunchApplication.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
    // 0=ButtonText, 1=toolTip, 2=AppToLaunch, 3...AppParameters
    if (params[0] && (params[1] || params[1] == "") && params[2]) {
        var theButton = createTiddlyButton(place, getParam(params,"buttonText",params[0]), getParam(params,"toolTip",params[1]), onClickLaunchApplication);
        theButton.setAttribute("appToLaunch", getParam(params,"appToLaunch",params[2]));
        params.splice(0,3);
        theButton.setAttribute("appParameters", params.join(" "));
        return;
    }
}
config.macros.LaunchApplicationButton.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
    config.macros.LaunchApplication.handler (place,macroName,params,wikifier,paramString,tiddler);
}

config.macros.LaunchApplicationLink.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
    // 0=ButtonText, 1=toolTip, 2=AppToLaunch, 3...AppParameters
    if (params[0] && (params[1] || params[1] == "") && params[2]) {
        //var theLink = createExternalLink(place, getParam(params,"buttonText",params[0]));
        var theLink = createTiddlyButton(place, getParam(params,"buttonText",params[0]), getParam(params,"toolTip",params[1]), onClickLaunchApplication,"link");
        theLink.setAttribute("appToLaunch", getParam(params,"appToLaunch",params[2]));
        params.splice(0,3);
        theLink.setAttribute("appParameters", params.join(" "));
        return;
    }
}

function onClickLaunchApplication(e) {
	var theAppToLaunch = this.getAttribute("appToLaunch");
	var theAppParams = this.getAttribute("appParameters").readMacroParams();
	LaunchApplication(theAppToLaunch,theAppParams);
}

//}}}
/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.4|
|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||
|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
<<<
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)
|please see [[LoadTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.LoadTiddlersPlugin= {major: 3, minor: 6, revision: 4, date: new Date(2008,11,14)};

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});
			})
		}
		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 (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
			}
		// otherwise, use XMLHttpRequest to fetch document
		} else {
			var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
			var x=doHttp('GET',src,null,null,name,pass,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');	
		}
	},
	doImport: function(status,params,html,src,xhr) {
		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 = config.macros.loadTiddlers.readTiddlersFromHTML(html);
		var count=tiddlers?tiddlers.length:0;
		var querypos=src.lastIndexOf('?'); if (querypos!=-1) src=src.substr(0,querypos);
		if (!quiet) displayMessage(config.macros.loadTiddlers.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==config.macros.loadTiddlers.reportTitle)
				continue; // skip 'ImportedTiddlers' history from the other document...
			if (theExisting && theExisting.tags.contains(config.macros.loadTiddlers.lockedTag)) {
				if (!quiet) displayMessage(config.macros.loadTiddlers.lockedMsg.format([theExisting.title,config.macros.loadTiddlers.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=config.macros.loadTiddlers.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=config.macros.loadTiddlers.skippedMsg; continue; }
			// DO IT!
			var tags=new Array().concat(inbound.tags,config.macros.loadTiddlers.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(config.macros.loadTiddlers.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound); 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) config.macros.loadTiddlers.report(src,tiddlers,count,quiet);
		}
		// always show final message when tiddlers were actually loaded
		if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g,' ')]));
	},
	report: function(src,tiddlers,count,quiet) {
		// 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) { 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.6.4|
|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|documentation|
|Requires||
|Overrides||
|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
<<<
__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
<<<
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).  Fixes error caused when ImportTiddlersPlugin has NOT been installed along side this plugin.
2007.03.26 [3.4.2] renamed import() to doImport() to fix IE load-time error ("identifier expected").  This may also cause a problem with FF1.5.0.x.... Apparently, "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 functionality into separate plugins
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
/***
|Name|LoadTiddlersPluginPatch|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPluginPatch|
|Version|3.6.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|LoadTiddlersPlugin|
|Overrides||
|Description|backward-compatible function patches for use with LoadTiddlersPlugin and TW2.1.x or earlier|

!!!!!Usage
<<<
The current version LoadTiddlersPlugin is compatible with the TW2.2.x core functions.
This "patch" plugin provides additional functions needed to enable the current version of LoadTiddlersPlugin to operate correctly under TW2.1.x or earlier.

{{medium{You do not need to install this plugin if you are using TW2.2.0 or above}}}
(though it won't hurt anything if you do... it will just take up more space).
<<<
!!!!!Revisions
<<<
2008.08.05 [3.6.2] rewrote loadFile to eliminate use of platform-specific fileExists() function
2008.01.03 [3.5.0] added support for passing txtRemoteUsername and txtRemotePassword for accessing password-protected remote servers
2007.06.27 [3.4.8] compatibility functions split from LoadTiddlersPlugin
|please see [[LoadTiddlersPlugin]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
// these functions are only defined when installed in TW2.1.x and earlier... 
if (version.major+version.minor/10 <= 2.1) {

// Version
version.extensions.LoadTiddlersPluginPatch= {major: 3, minor: 6, revision: 2, date: new Date(2008,8,5)};

config.macros.loadTiddlers.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]));

	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
			if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var x; // get an request object
		try {x = new XMLHttpRequest()} // moz
		catch(e) {
			try {x = new ActiveXObject("Msxml2.XMLHTTP")} // IE 6
			catch (e) {
				try {x = new ActiveXObject("Microsoft.XMLHTTP")} // IE 5
				catch (e) { return }
			}
		}
		// setup callback function to handle server response(s)
		x.onreadystatechange = function() {
			if (x.readyState == 4) {
				if (x.status==0 || x.status == 200) {
					if (!quiet) displayMessage(config.macros.loadTiddlers.readMsg.format([x.responseText.length,src]));
					if (callback) callback(true,params,x.responseText,src,x);
				}
				else {
					if (!quiet) displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,x.status]));
				}
			}
		}
		// get privileges to read another document's DOM via http:// or file:// (moz-only)
		if (typeof(netscape)!="undefined") {
			try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }
			catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }
		}
		// send the HTTP request
		try {
			var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();
			x.open("GET",src,true,config.options.txtRemoteUsername,config.options.txtRemotePassword);
			if (x.overrideMimeType) x.overrideMimeType('text/html');
			x.send(null);
		}
		catch (e) {
			if (!quiet) {
				displayMessage(this.openErrMsg.format([src,"(unknown)"]));
				displayMessage(e.description?e.description:e.toString());
			}
		}
	}
}

config.macros.loadTiddlers.readTiddlersFromHTML=function(html) {
	// for TW2.1 and earlier
	// extract store area from html 
	var start=html.indexOf('<div id="storeArea">');
	var end=html.indexOf("<!--POST-BODY-START--"+">",start);
	if (end==-1) var end=html.indexOf("</body"+">",start); // backward-compatibility for older documents
	var sa="<html><body>"+html.substring(start,end)+"</body></html>";

	// load html into iframe document
	var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);
	f=document.createElement("iframe"); f.id="loaderFrame";
	f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
	document.body.appendChild(f);
	var d=f.document;
	if (f.contentDocument) d=f.contentDocument; // For NS6
	else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
	d.open(); d.writeln(sa); d.close();

	// read tiddler DIVs from storeArea DOM element	
	var sa = d.getElementById("storeArea");
	if (!sa) return null;
	sa.normalize();
	var nodes = sa.childNodes;
	if (!nodes || !nodes.length) return null;
	var tiddlers = [];
	for(var t = 0; t < nodes.length; t++) {
		var title = null;
		if(nodes[t].getAttribute)
			title = nodes[t].getAttribute("tiddler");
		if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))
			title = nodes[t].id.substr(5);
		if(title && title != "")
			tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));
	}
	return tiddlers;
}

// // COPIED FROM TW2.2beta5
// // enables reading tiddler definitions using TW2.2 storeArea format, even when plugin is running under TW2.1.x
// // storeArea format changes include:
// // <pre> nodes
// // attribute(tiddler) renamed to attribute(title)
// // attribute(modified) is omitted if created==modified
TW21Loader.prototype.internalizeTiddler = function(store,tiddler,title,node)
{
	var e = node.firstChild;
	var text = null;
	if(node.getAttribute("tiddler")) {
		text = getNodeText(e).unescapeLineBreaks();
	} else {
		while(e.nodeName!="PRE" && e.nodeName!="pre") {
			e = e.nextSibling;
		}
		text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
	}
	var modifier = node.getAttribute("modifier");
	var c = node.getAttribute("created");
	var m = node.getAttribute("modified");
	var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date;
	var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created;
	var tags = node.getAttribute("tags");
	var fields = {};
	var attrs = node.attributes;
	for(var i = attrs.length-1; i >= 0; i--) {
		var name = attrs[i].name;
		if (attrs[i].specified && !TiddlyWiki.isStandardField(name)) {
			fields[name] = attrs[i].value.unescapeLineBreaks();
		}
	}
	tiddler.assign(title,text,modifier,modified,tags,created,fields);
	return tiddler;
};

} // END OF TW2.1.x backward-compatibility functions
//}}}
[[Índice|Data]]
[[Docencia]]
[[Novedades]]
[[Research]]
[[Multimedia]]
[[RSS|tw.xml]]
*(31-07-2011) Debido a cambios en el software del servidor de la U. de S. temporalmente mi página web usual está fuera de combate y utilizaré este formato hasta que sea capaz de recuperar la antigua. Perdonen las molestias.
PROPERLY 3-REALIZABLE GROUPS: OPEN QUESTIONS
SEPTEMBER 9, 2008

Abstract. We quickly review P3R-groups and their relations to well-known conjectures. We also detail some of the open problems on this topic.
1. Introduction

A group G is said to be properly 3-realizable, P3R for short, if there is a finite 2-complex X with π1(X)≅G whose universal cover X̃ is proper homotopy equivalent to a 3-manifold (which may be called a proper 3-realization of G). One can only ensure X̃ always to be proper homotopy equivalent to some 4-manifold, see [CL05].
The class of P3R-groups is known to contain the classes of finite groups, finitely generated abelian groups, direct products and ascending HNN-extensions of finitely presented groups, simply connected at ∞ groups and one-relator groups. Also, the class of P3R-groups is closed under amalgamated products (and HNN-extensions) over finite groups. See [CL05], [CLRQ] and related works.
It is worth noting P3R-groups have H2(G, ℤG) free abelian. This is related to a long standing conjecture attributed to Hopf. Recent results, see [CLQ06], show that not all semistable groups are P3R. It is unknown whether or not all P3R-groups are semistable. This relates for 1-ended groups to the Covering Conjecture as follows. Clearly, the fundamental group G of a closed 3-manifold is P3R. A proper 3-realization of such G is, up to proper homotopy equivalence, an open 3-manifold with a collection of 3-balls removed. If there were non-semistable P3R-groups this manifold would be a punctured ℝ3 showing the conjecture, see [CLQ06].
Some open questions

Non-semistability and P3R-groups. One-ended groups which are semistable are known to be P3R if and only if the fundamental pro-group is pro-isomorphic to a tower of finitely generated free groups of increasing rank, where the bonding maps are projections, see [CLQ06]. It is an open question what kind of towers may occur as fundamental pro-groups of (non-semistable) P3R-groups. Notice that the possible proper 3-realizations for these groups are open Whitehead manifolds, once the boundary is filled up by spheres and semiplanes if necessary. It is also unknown whether or not the class of P3R-groups is contained in the class of semistable groups.

Independence. The definition of a P3R-group seems to depend on the choice of the 2-complex X. In this respect, given a P3R-group G and any other finite 2-complex Y with π1(Y )≅G, the universal cover of the wedge Y ∨ S2 is shown to be proper homotopy equivalent to a 3-manifold, see [CL05]. Under which conditions is Ỹ proper homotopy equivalent to a 3-manifold itself?

Higher dimensions. Proper 3-realizability can be alternetively described as follows: a group G of type F2 for which the 2-skeleton of the universal cover of a K(G,1) is proper homotopy equivalent to a 3-manifold. Similarly, we may say that a Fn group G is proper 2n − 1-realizable, P(2n − 1)R for short, if the n-skeleton of the universal cover of a K(G,1) is properly homotopy equivalent to a 2n − 1-manifold. As in the 3-dimensional case, the embedding theorems [J.R65],[DR93] and [CFLQ03] only ensure proper homotopy equivalence to 2n-manifolds. We ask ourselves which kind of algebraic properties consecuences has this property on G and when, for which n, this property becomes trivial.
References

 

[CFLQ03] M. Cárdenas, T. Fernández, F. F. Lasheras, and A. Quintero, Embedding proper homotopy types, Colloq. Math. 95 (2003), no. 1, 1–20. MR 1 967 550

[CL05] M. Cárdenas and F. F. Lasheras, Properly 3-realizable groups: a survey, Geometric methods in group theory, Contemp. Math., vol. 372, Amer. Math. Soc., Providence, RI, 2005, pp. 1–9. MR MR2139672

[CLQ06] M. Cárdenas, F. F. Lasheras, and A. Quintero, On ends of proper 3-realizable groups, Work on progress, 2006.

[CLRQ] M. Cárdenas, F. F. Lasheras, D. Repovš, and A. Quintero, Amalgamated products and properly 3-realizable groups, To appear.

[DR93] A. N. Dranišnikov and D. Repovš, Embeddings up to homotopy type in Euclidean space, Bull. Austral. Math. Soc. 47 (1993), no. 1, 145–148. MR 94d:57049

[J.R65] Stallings J.R., The embedding of homotopy types into manifolds, Mimeographed Notes. Fine Library Princetone University, 1965.

-s-
Some lost open questions are:

i) If $G$ is P3R, when is one , if any, of its proper realizations the result of a thickening (of the corresponding universal covering)? 

ii) For $\underline{P}$ , a telescopic tower of groups, the classifying space  $B(\underline{P})$ is not the proper homotopy type of any covering space, i.e., its thickening it is not the proper realization of any f.p. group. True or false?

iii) For $G$ P3R and one-ended, gwsc, qsf and sci are equivalent, true? Update: Not true take $G=\mathbb Z\oplus\mathbb Z$.

iv) For $G$ infinite, P3R and one-ended  we have that $pi_2$ is isomorphic as a group to an infinite sum of copies of $\mathbb Z$. What kind of $\mathbb ZG$-module can be?

Here is a brief [[presentation|http://personal.us.es/mcard/jp3r/p3rhtml.html]].
/***
|<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>
***/
PasswordOptionPlugin extends the core Options with a non encrypted password type.

Notice:
*How a style can be specified for a specific option in StyleSheet

----
Test Password: <<option pasPassword myPasOptionInput >>
/***
|''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"
	});
*/
//}}}
/***
|Name|Plugin: jsMath|
|Created by|BobMcElrath|
|Email|my first name at my last name dot org|
|Location|http://bob.mcelrath.org/tiddlyjsmath.html|
|Version|1.5.1|
|Requires|[[TiddlyWiki|http://www.tiddlywiki.com]] &ge; 2.0.3, [[jsMath|http://www.math.union.edu/~dpvc/jsMath/]] &ge; 3.0|
!Description
LaTeX is the world standard for specifying, typesetting, and communicating mathematics among scientists, engineers, and mathematicians.  For more information about LaTeX itself, visit the [[LaTeX Project|http://www.latex-project.org/]].  This plugin typesets math using [[jsMath|http://www.math.union.edu/~dpvc/jsMath/]], which is an implementation of the TeX math rules and typesetting in javascript, for your browser.  Notice the small button in the lower right corner which opens its control panel.
!Installation
In addition to this plugin, you must also [[install jsMath|http://www.math.union.edu/~dpvc/jsMath/download/jsMath.html]] on the same server as your TiddlyWiki html file.  If you're using TiddlyWiki without a web server, then the jsMath directory must be placed in the same location as the TiddlyWiki html file.

I also recommend modifying your StyleSheet use serif fonts that are slightly larger than normal, so that the math matches surrounding text, and \\small fonts are not unreadable (as in exponents and subscripts).
{{{
.viewer {
  line-height: 125%;
  font-family: serif;
  font-size: 12pt;
}
}}}

If you had used a previous version of [[Plugin: jsMath]], it is no longer necessary to edit the main tiddlywiki.html file to add the jsMath <script> tag.  [[Plugin: jsMath]] now uses ajax to load jsMath.
!History
* 11-Nov-05, version 1.0, Initial release
* 22-Jan-06, version 1.1, updated for ~TW2.0, tested with jsMath 3.1, editing tiddlywiki.html by hand is no longer necessary.
* 24-Jan-06, version 1.2, fixes for Safari, Konqueror
* 27-Jan-06, version 1.3, improved error handling, detect if ajax was already defined (used by ZiddlyWiki)
* 12-Jul-06, version 1.4, fixed problem with not finding image fonts
* 26-Feb-07, version 1.5, fixed problem with Mozilla "unterminated character class".
* 27-Feb-07, version 1.5.1, Runs compatibly with TW 2.1.0+, by Bram Chen
!Examples
|!Source|!Output|h
|{{{The variable $x$ is real.}}}|The variable $x$ is real.|
|{{{The variable \(y\) is complex.}}}|The variable \(y\) is complex.|
|{{{This \[\int_a^b x = \frac{1}{2}(b^2-a^2)\] is an easy integral.}}}|This \[\int_a^b x = \frac{1}{2}(b^2-a^2)\] is an easy integral.|
|{{{This $$\int_a^b \sin x = -(\cos b - \cos a)$$ is another easy integral.}}}|This $$\int_a^b \sin x = -(\cos b - \cos a)$$ is another easy integral.|
|{{{Block formatted equations may also use the 'equation' environment \begin{equation}  \int \tan x = -\ln \cos x \end{equation} }}}|Block formatted equations may also use the 'equation' environment \begin{equation}  \int \tan x = -\ln \cos x \end{equation}|
|{{{Equation arrays are also supported \begin{eqnarray} a &=& b \\ c &=& d \end{eqnarray} }}}|Equation arrays are also supported \begin{eqnarray} a &=& b \\ c &=& d \end{eqnarray} |
|{{{I spent \$7.38 on lunch.}}}|I spent \$7.38 on lunch.|
|{{{I had to insert a backslash (\\) into my document}}}|I had to insert a backslash (\\) into my document|
!Code
***/
//{{{

// AJAX code adapted from http://timmorgan.org/mini
// This is already loaded by ziddlywiki...
if(typeof(window["ajax"]) == "undefined") {
  ajax = {
      x: function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}},
      gets: function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText}
  }
}

// Load jsMath
jsMath = {
  Setup: {inited: 1},          // don't run jsMath.Setup.Body() yet
  Autoload: {root: new String(document.location).replace(/[^\/]*$/,'jsMath/')}  // URL to jsMath directory, change if necessary
};
var jsMathstr;
try {
  jsMathstr = ajax.gets(jsMath.Autoload.root+"jsMath.js");
} catch(e) {
  alert("jsMath was not found: you must place the 'jsMath' directory in the same place as this file.  "
       +"The error was:\n"+e.name+": "+e.message);
  throw(e);  // abort eval
}
try {
  window.eval(jsMathstr);
} catch(e) {
  alert("jsMath failed to load.  The error was:\n"+e.name + ": " + e.message + " on line " + e.lineNumber);
}
jsMath.Setup.inited=0;  //  allow jsMath.Setup.Body() to run again

// Define wikifers for latex
config.formatterHelpers.mathFormatHelper = function(w) {
    var e = document.createElement(this.element);
    e.className = this.className;
    var endRegExp = new RegExp(this.terminator, "mg");
    endRegExp.lastIndex = w.matchStart+w.matchLength;
    var matched = endRegExp.exec(w.source);
    if(matched) {
        var txt = w.source.substr(w.matchStart+w.matchLength, 
            matched.index-w.matchStart-w.matchLength);
        if(this.keepdelim) {
          txt = w.source.substr(w.matchStart, matched.index+matched[0].length-w.matchStart);
        }
        e.appendChild(document.createTextNode(txt));
        w.output.appendChild(e);
        w.nextMatch = endRegExp.lastIndex;
    }
}

config.formatters.push({
  name: "displayMath1",
  match: "\\\$\\\$",
  terminator: "\\\$\\\$\\n?", // 2.0 compatibility
  termRegExp: "\\\$\\\$\\n?",
  element: "div",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

config.formatters.push({
  name: "inlineMath1",
  match: "\\\$", 
  terminator: "\\\$", // 2.0 compatibility
  termRegExp: "\\\$",
  element: "span",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

var backslashformatters = new Array(0);

backslashformatters.push({
  name: "inlineMath2",
  match: "\\\\\\\(",
  terminator: "\\\\\\\)", // 2.0 compatibility
  termRegExp: "\\\\\\\)",
  element: "span",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

backslashformatters.push({
  name: "displayMath2",
  match: "\\\\\\\[",
  terminator: "\\\\\\\]\\n?", // 2.0 compatibility
  termRegExp: "\\\\\\\]\\n?",
  element: "div",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

backslashformatters.push({
  name: "displayMath3",
  match: "\\\\begin\\{equation\\}",
  terminator: "\\\\end\\{equation\\}\\n?", // 2.0 compatibility
  termRegExp: "\\\\end\\{equation\\}\\n?",
  element: "div",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

// These can be nested.  e.g. \begin{equation} \begin{array}{ccc} \begin{array}{ccc} ...
backslashformatters.push({
  name: "displayMath4",
  match: "\\\\begin\\{eqnarray\\}",
  terminator: "\\\\end\\{eqnarray\\}\\n?", // 2.0 compatibility
  termRegExp: "\\\\end\\{eqnarray\\}\\n?",
  element: "div",
  className: "math",
  keepdelim: true,
  handler: config.formatterHelpers.mathFormatHelper
});

// The escape must come between backslash formatters and regular ones.
// So any latex-like \commands must be added to the beginning of
// backslashformatters here.
backslashformatters.push({
    name: "escape",
    match: "\\\\.",
    handler: function(w) {
        w.output.appendChild(document.createTextNode(w.source.substr(w.matchStart+1,1)));
        w.nextMatch = w.matchStart+2;
    }
});

config.formatters=backslashformatters.concat(config.formatters);

window.wikify = function(source,output,highlightRegExp,tiddler)
{
    if(source && source != "") {
        if(version.major == 2 && version.minor > 0) {
            var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
            wikifier.subWikifyUnterm(output);
        } else {
            var wikifier = new Wikifier(source,formatter,highlightRegExp,tiddler);
            wikifier.subWikify(output,null);
        }
        jsMath.ProcessBeforeShowing();
    }
}
//}}}
"Problemas abiertos en teoría de los continuos"

por el

Profesor W. Charatonik, Missouri University.

 

Ante cualquier duda consúltese "Hyperspaces : fundamentals and recent advances" de Alejandro Illanes y Sam B. Nadler, Jr. 

Q1 Si $X\subset \mathbb R^2$ es un continuo tal que $\mathbb R^2-X$ es conexo. ¿Es cierto que $X$ tiene la propiedad de punto fijo?

Q2 ¿Cuáles son los conjuntos hereditariamente equivalentes?

Q3 ¿Es cierto que si $X$ es un conjunto encadenable y $f:X\to Y$ es una aplicación confluente entonces $Y$ también es encadenable?

Q4 ¿Cuáles son los subconjuntos del plano que son homogéneos?

Q5 ¿Es el pseudoarco el único homogéneo hereditariamente indescomponible tipo árbol?

Q6 Dado un triodo simple $Y$, ¿existen aplicaciones continuas $f,g:Y\to Y$ tales que $fg=gf$ y con $f(x)\neq g(x)$ para todo $x\in Y$?

Q7 ¿Cuáles son los conjuntos homogéneos de $\mathbb R^3$ localmente conexos?

Q8 ¿Cómo se llaman los conjuntos $X\subset\mathbb R^2$ que verifican que dado para todo $x\in X-\mathbb R^2$ esixste una recta $l$ que no corta a $X$? ¿Y si permitimos que $l$ pueda ser además una semirrecta?

Q9 Dada la sucesión numérica $\{x_n\}$ con $1\leq x_n \leq 15$, cuyos primeros términos son $14, 5, 4, 10, 12, 2, 9, 8, 11, 15, 6, 7, 13, 3, 1$, ¿cuál es la regla que la describe? Si permitimos $1\leq x_n \leq 16$ ¿dónde aparecería $16$?

Podemos encontrar más problemas, y algunas soluciones aquí.

 
We list some resources on projective crossed modules:

    An AMS article http://www.ams.org/mathscinet-getitem?mr=2001e:57001.
    The mother of all references on crossed modules http://www.bangor.ac.uk/~mas010/nonab-a-t.html.(Thanks to Andy Tonks for the ref).
    Bangor's resources http://www/bangor.ac.uk/~mas010/nonlnpub.htm. (Thanks to Andy Tonks for the ref).
Published papers:

    "Homology decompositions in proper homotopy", R. Ayala, M. Cárdenas, and A. Quintero, Math. Japon. 42 (1995), no. 3, 443-457. MR 96k:55008
    "On the Karoubi filtration of a category". M. Cárdenas and E. K. Pedersen, K-Theory 12 (1997), no. 2, 165-191. MR 98g:18012
    "Minimal covers of open manifolds with half-spaces and the proper l-s category of product spaces". M. Cárdenas, F.F. Lasheras and A. Quintero, B. Belg. Math. Soc-Sim. 9 (2002), 419-431.
    "Embedding Proper Homotoy Types". M. Cárdenas, T. Férnandez, F.F. Lasheras and A. Quintero, Coll. Math. vol.95 (2003) no.1, 1-20.
    "An elementary Approach to the Projective Dimension in Proper Homotopy Theory", R. Ayala, M. Cárdenas, F. Muro and A. Quintero, Comm. in Alg. vol. 31 No. 12, pp. 5995-6017, 2003.
    "Direct products and properly 3-realizable groups". M. Cárdenas, F.F. Lasheras and R. Roy, Bull. Austral. Math. Soc. Vol. 70 (2004) no. 2, Pages 199-205.
    " On properly $3$-realizable groups". M. Cárdenas and F.F. Lasheras, Topology and its Applications, vol. 153, Issues 2-3, 1 September 2005, pp. 337-349 .
    " Properly $3$-realizable groups". R. Ayala, M. Cárdenas, F.F. Lasheras and A. Quintero, Proc. Amer. Math. Soc. 133 (2005), 1527-1535.
    "Properly 3-realizable goups: a survey". M. Cárdenas and F.F. Lasheras, CONM book series Proceedings of the Conference on Geometric Group Theory and Geometric Methods in Group Theory edited by S. Cleary, J. Taback, M. Elder, J. Burillo, and E. Ventura.
    "The proper L-S category of Whitehead manifolds ", M. Cárdenas, F. Muro and A. Quintero, Topology and its Applications, Volume 153, Issue 4, 1 November 2005, Pages 557-579
    "Proper L-S category, fundamental pro-groups and 2-dimensional proper co-H-spaces ", M. Cárdenas, F. Muro and A. Quintero, Topology and its Applications, Volume 153, Issue 4, 1 November 2005, Pages 557-579
    "Amalgamated products and properly 3-realizable groups ", M. Cárdenas, F.F. Lasheras, A. Quintero and D. Repovs, Journal of Pure and Applied Algebra, Vol. 208, Issue 1, January 2007, Pages 293-296.
    "Properly 3-realizable groups ", M. Cárdenas, F.F. Lasheras and A. Quintero, Fundamentalnaya i Prikladnaya Matematika (Fundamental and Applied mathematics) 2005, Vol. 11, num.4 [95-103]
    "One-relator groups and proper 3-realizability", M. Cárdenas, F.F. Lasheras, A. Quintero and D. Repovs, Rev. Mat. Iberoamericana 25 (2009), no. 2, 739–756.
*[[Seminars with Dr. Dušan Repovš |http://mcard.tiddlyspot.com/]]
*[[Continuum]]
*[[Problemas abiertos en Teoría de Contínuos]]
*[[P3R-groups]]
*[[Open problems on P3R-groups]]
*[[Projective crossed modules]]
*[[Published papers]]
*[[Talks]]
*[[Work in progress]]
/***
|Name|SaveAsPlugin|
|Source|http://www.TiddlyTools.com/#SaveAsPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveAsPluginInfo|
|Version|2.4.3|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Save current document to a different path/filename|
This plugin automatically adds a 'save as' command to the TiddlyWiki 'backstage' menu that allows you to 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).
>//Note: This plugin now supersedes [[NewDocumentPlugin]], which has been retired and is no longer being distributed.  In addition, the HTML+CSS "snapshot" functionality previous provided by that plugin has been moved to a separate plugin.  Please see [[SnapshotPlugin]] for additional information.//
!!!!!Documentation
<<<
see [[SaveAsPluginInfo]]
<<<
!!!!!Revisions
<<<
2008.09.29 [2.4.3] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
| Please see [[SaveAsPluginInfo]] for additional revision details |
2006.02.03 [1.0.0] Created.
<<<
!!!!!Code
***/
//{{{
version.extensions.SaveAsPlugin= {major: 2, minor: 4, revision: 2, date: new Date(2008,9,28)};

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_NF: "nf", // file type tokens
	type_map: { // map filetype param alternatives/abbreviations to token values
		tiddlywiki:"tw", tw:"tw", wiki: "tw",
		purestore: "ps", ps:"ps", store:"ps",
		plaintext: "tx", tx:"tx", text: "tx",
		newsfeed:  "nf", nf:"nf", xml:  "nf", rss:"nf"
	},
	replaceparam: "replace",
	mergeparam: "merge",
	quietparam: "quiet",
	openparam: "open",
	askParam: "ask",
	askMsg: "Enter a tag filter (use * for all tiddlers, 'none' for blank document)",
	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] && params[0].substr(0,this.labelparam.length)==this.labelparam)
			var label=params.shift().substr(this.labelparam.length);
		if (params[0] && params[0].substr(0,this.promptparam.length)==this.promptparam)
			var prompt=params.shift().substr(this.promptparam.length);
		if (params[0] && params[0].substr(0,this.targetparam.length)==this.targetparam)
			var target=params.shift().substr(this.targetparam.length);
		if (params[0] && params[0].substr(0,this.filenameparam.length)==this.filenameparam)
			var filename=params.shift().substr(this.filenameparam.length);
		if (params[0] && params[0].substr(0,this.typeparam.length)==this.typeparam)
			var filetype=this.type_map[params.shift().substr(this.typeparam.length).toLowerCase()];
		var q=(params[0] && params[0]==this.quietparam);   if (q) params.shift();
		var o=(params[0] && params[0]==this.replaceparam); if (o) params.shift();
		var m=(params[0] && params[0]==this.mergeparam);   if (m) params.shift();
		var a=(params[0] && 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('quiet')=="true",
				this.getAttribute('overwrite')=="true",
				this.getAttribute('merge')=="true",
				this.getAttribute('autoopen')=="true");  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("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,quiet,overwrite,merge,autoopen) {
		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);
		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':'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,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) {
		var cms=config.macros.saveAs; // abbreviation
		cms.filter=filter||"";
		if (filter==cms.emptyParam) return [];
		if (!filter||!filter.length) return store.getTiddlers("title");
		// get filtered tiddlers
		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=="*") return store.getTiddlers("title");
		}
		return store.filterTiddlers("[tag["+filter+"]]");
	},
	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',
	plainTextTiddler:
		'\n// ----- %0 (by %1 on %2) -----\n\n%3',
	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,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_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) { 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;
		}
		var out=this.getData(target,filetype,tids,quiet,overwrite,merge);
		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;
	},
	formatItem: function(s,f,t,u) {
		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.modifier,t.modified.toLocaleString(),t.text]);
		return r||"";
	},
	getData: function(target,filetype,tids,quiet,overwrite,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));
			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 text=loadFile(target);
			if (text && text.length) {
				var remoteStore=new TiddlyWiki();
				if (remoteStore.importTiddlyWiki(convertUTF8ToUnicode(text))
					&& (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;
	}
};
//}}}
//{{{
// 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.4.3|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for SaveAsPlugin|
This plugin automatically adds a 'save as' command to the TiddlyWiki 'backstage' menu that allows you to 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).
>//Note: This plugin now supersedes [[NewDocumentPlugin]], which has been retired and is no longer being distributed.  In addition, the HTML+CSS "snapshot" functionality previous provided by that plugin has been moved to a separate plugin.  Please see [[SnapshotPlugin]] for additional information.//
!!!!!Usage
<<<
When the command link is clicked, a standard system-specific dialog box will be displayed so you can select/enter the desired target path and filename.  The default is to create a file called "new.html" in the same directory as the current document.
Syntax:
{{{
<<saveAs "label:..." "prompt:..." "filename:..." "type:..." quiet open tagfilter>>
}}}
where:
*''label:...'' //(optional)//<br>defines alternative link text (replaces default "save as..." display)
*''prompt:...'' //(optional)//<br>defines alternative tooltip text for 'mouseover' prompting (replaces default hard-coded tooltip text)
*''filename:...'' //(optional)//<br>specifies the //default// filename to be shown when asking for an output path/file
*''type:...'' //(optional)//<br>specifies a keyword indicating one of four file output formats:
**''type:~TiddlyWiki'' (or ''wiki'' or ''tw'')<br>a TiddlyWiki HTML document 
**''type:~PureStore'' (or ''store'' or ''ps'')<br>a TiddlyWiki "PureStore" HTML export file (just tiddlers, no core code)
**''type:~PlainText'' (or ''text'' or ''tx'')<br>a plain text file listing of tiddler //source// content
**''type:~NewsFeed'' (or ''xml'' or ''rss'' or ''nf'')<br>an RSS ~NewsFeed XML file
*''quiet'' //(optional)//<br>normally, when using tag 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.
*''open'' //(optional)//<br>Use the ''open'' keyword to auto-open the newly created document file in a separate browser tab/window.
*''tagfilter'' or ''ask'' or ''none''//(optional)//<br>You can use the tag filter parameter to select a subset of tiddlers to be written into the new document file.  If you specify a single tag value, then only tiddlers that are tagged with that value are included in the resulting file.  To use a combination of tag values, you can install [[MatchTagsPlugin]], which provides full 'boolean' logic with AND, OR, and NOT operators, as well as nested parentheses, to create complex expressions for filtering and selecting the desired set of tiddlers.  If you specify the keyword, ''ask'' in place of the tagfilter, you will be prompted to enter a tag or tag expression whenever you click on the 'save as...' command link.  Alternatively, you can specify the keyword, ''none'' in place of the tagfilter to omit all tiddlers and create a new //empty// document.
*By default, when no tag filter parameter is provided, all tiddlers in the document are written to the new file.
<<<
!!!!!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>>
<<<
!!!!!Revisions
<<<
2008.09.29 [2.4.3] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
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").  Based on a suggestion from Xavier Verges.
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.
<<<
/***
|Name|SaveFromWebConfig|
|Source|http://www.TiddlyTools.com/#SaveFromWebConfig|
|Documentation|http://www.TiddlyTools.com/#SaveFromWebPluginInfo|
|Version|1.3.0|
|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||
|Description|configuration settings for SaveFromWebPlugin|
***/
/***
!!!!! URL for server-side 'reflector' script.
***/
//{{{
config.options.txtSaveFromWebScriptURL="savefromweb.php";
//}}}
/***
>Script can be hosted on ANY web server that supports PHP5.
***/
/***
!!!!! URL for TiddlyWiki core source
//{{{
config.options.txtSaveFromWebSourceFile="http://www.TiddlyTools.com/empty.html";
//}}}
/***
>use alternative document URL for retrieving TiddlyWiki core source code. Using an *empty* TW minimizes data transfer for retrieving TW core. Can be on ANY domain... If blank, retrieve core source code from current document URL.
***/
/***
!!!!! Target filename
//{{{
config.options.txtSaveFromWebTargetFilename="";
//}}}
/***
>specifies the desired destination filename for the downloaded file. Can be any valid filename for local filesystem and will appear as the default value when you are prompted to save the file.  If blank, plugin uses the filename from the URL of the current document (or the domain name if there is no filename in the URL)
***/
/***
!!!!! Pre-fetch option:
//{{{
config.options.chkSaveFromWebPreFetch=false;
//}}}
/***
<<<
* true=get (and cache) TW core code when document is first loaded (i.e., when plugin is initialized)
* false=get and cache core code the first time the file is being saved
This option causes the plugin to retrieve the TiddlyWiki core source as soon as you load the document, instead of waiting for the first time you save.  This ensures that the TiddlyWiki core source can still be saved to the local filesystem even if your network connection is dropped before you save your changes.  Note that, even without pre-fetching, the core source is always cached after it is retrieved, so that subsequent saves don't do extra work to get it again.
<<<
***/
/***
!!!!! Local I/O option
//{{{
config.options.chkSaveFromWebAttemptLocalIO=false;
//}}}
/***
<<<
(requires browser security permissions, i.e., "trusted site" settings).
The plugin will try to obtain security permission for direct filesystem I/O.  If you grant filesystem access to the script, then it writes the document directly to your filesystem, and doesn't use the server-side reflector script at all.  This allows you to save a remote file to your local filesystem, even if your net connection drops after you open the document. Note: if filesystem permissions are not granted, the plugin will automatically attempt to use the server-side reflector script as a fallback... even if no longer connected to the net.
<<<
***/
/***
|Name|SaveFromWebPlugin|
|Source|http://www.TiddlyTools.com/#SaveFromWebPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveFromWebPluginInfo|
|Version|1.3.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||
|Overrides||
|Options|##Configuration|
|Description|extend 'save changes' to get remote document contents and save to local filesystem |
Normally, when you are viewing a TiddlyWiki document over the web (i.e., not via {{{file://}}}) and you select the "save changes" (or "save to disk") command, an error message is displayed: //__"You need to save this TiddlyWiki to a file before you can save changes."__//  This plugin extends the use of {{{<<saveChanges>>}}} so that when you are viewing and/or editing a remote TiddlyWiki document, instead of receiving this somewhat confusing and unhelpful message, you can still click the "save changes" (or "save to disk") command to ''store a copy of the remote document directly onto your local filesystem'', //including any unsaved tiddler changes/additions you have made while working on-line.//
!!!!!Documentation
>see [[SaveFromWebPluginInfo]]
!!!!!Configuration
> see [[SaveFromWebConfig]]
!!!!!Revisions
<<<
2008.09.29 [1.3.1] in saveFromWeb(), do NOT convert UTF8 to Unicode when merging retrieved source for submission to server-side reflector script.  Fixes mangling of international characters and symbols.
|please see [[SaveFromWebPluginInfo]] for additional revision details|
2007.06.26 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.SaveFromWebPlugin= {major: 1, minor: 3, revision: 1, date: new Date(2008,9,29)};
//}}}

//{{{
// DEFAULT SETTINGS
if (config.options.txtSaveFromWebScriptURL==undefined)
	config.options.txtSaveFromWebScriptURL="savefromweb.php";
if (config.options.txtSaveFromWebTargetFilename==undefined)
	config.options.txtSaveFromWebTargetFilename=""; // use current filename when blank
if (config.options.txtSaveFromWebSourceFile==undefined)
	config.options.txtSaveFromWebSourceFile=""; // use current URL when blank
if (config.options.chkSaveFromWebAttemptLocalIO==undefined)
	config.options.chkSaveFromWebAttemptLocalIO=true; // true=try to use local filesystem I/O (requires security permissions)
if (config.options.chkSaveFromWebPreFetch==undefined)
	config.options.chkSaveFromWebPreFetch=false; // true=retrieve TW core when document is first loaded
//}}}

//{{{
// OPTIONAL: get TW core source code when plugin is loaded (i.e., once per document session)
if (document.location.protocol!="file:" && config.options.chkSaveFromWebPreFetch) {
	// retrieve TW source from server...
	var src=document.location.href;
	if (config.options.txtSaveFromWebSourceFile && config.options.txtSaveFromWebSourceFile.length)
		src=config.options.txtSaveFromWebSourceFile;
	var target=config.options.txtSaveFromWebTargetFilename;
	if (!target.length) { // use current filename
		var loc=document.location.pathname;
		var slashpos=loc.lastIndexOf("/");
		target=(slashpos==-1)?loc:loc.substr(slashpos+1);
		if (!target.length) target=document.location.host+".html";
	}
	var xhr=loadRemoteFile(src,function(success,target,txt,src,xhr){if(success)config.saveFromWebSourceCache=txt;},target);
}
//}}}

//{{{
window.saveFromWeb_saveChanges = window.saveChanges;
window.saveChanges = function(onlyIfDirty,tiddlers) {
	// if on file:, just use standard core save handling
	if(document.location.protocol == "file:") { window.saveFromWeb_saveChanges.apply(this,arguments); return; }
	clearMessage();
	// get target filename
	var target=config.options.txtSaveFromWebTargetFilename;
	if (!target.length) { // use current filename
		var loc=document.location.pathname;
		var slashpos=loc.lastIndexOf("/");
		target=(slashpos==-1)?loc:loc.substr(slashpos+1);
		if (!target.length) target=document.location.host+".html";
	}
	// get TW core source location
	var src=document.location.href;
	if (config.options.txtSaveFromWebSourceFile && config.options.txtSaveFromWebSourceFile.length)
		src=config.options.txtSaveFromWebSourceFile;
	// if core source has already been cached, go straight to saving the file...
	if (config.saveFromWebSourceCache)
		{ window.saveFromWeb(true,target,config.saveFromWebSourceCache,src,null); return; }
	// otherwise, retrieve TW source from server...
	displayMessage("Retrieving TiddlyWiki core from "+src);
	var xhr=loadRemoteFile(src,window.saveFromWeb,target);
	if (!xhr) { // couldn't load remote, report core error message
		displayMessage("Could not retrieve TiddlyWiki core... download unsuccessful.");
		alert(config.messages.notFileUrlError);
		if(store.tiddlerExists(config.messages.saveInstructions))
			story.displayTiddler(null,config.messages.saveInstructions);
	}
	return;
}
//}}}

//{{{
window.saveFromWeb = function(success,target,txt,url,xhr) {
	if(!success) {
		displayMessage("Could not retrieve TiddlyWiki core... download unsuccessful.");
		alert(config.messages.cantSaveError);
		if(store.tiddlerExists(config.messages.saveInstructions))
			story.displayTiddler(null,config.messages.saveInstructions);
		return;
	}
	// Locate the storeArea div's in the original source
	var posDiv=locateStoreArea(txt);
	if(!posDiv) { alert(config.messages.invalidFileError.format([url])); return; }

	// cache the document source so subsequent saves don't have to retrieve the source each time
	if (!config.saveFromWebSourceCache) config.saveFromWebSourceCache=txt;

	// if we can get local filesystem access, then ask for a filename and merge/write the file
	if (config.options.chkSaveFromWebAttemptLocalIO) {
		try {
			// get local target path+filename (may be blocked by browser security)
			var target=promptForFilename( "Save file as:","C:\\",target,"html");
			if (!target || !target.length) return;
			saveBackup(target,txt);
			saveRss(target);
			saveEmpty(target,txt,posDiv);
			saveMain(target,txt,posDiv);
			return;
		} catch(e) { }
	}
	// otherwise, fallback to using online 'reflector' script (if any)
	if (config.options.txtSaveFromWebScriptURL.length) {
		displayMessage("Merging tiddlers with core and preparing for download...");
		var merged=txt.substr(0,posDiv[0]+startSaveArea.length)+"\n"+
			store.allTiddlersAsHtml()+"\n"+txt.substr(posDiv[1]);
		var title=getPageTitle().htmlEncode();
		merged=merged.replaceChunk("<title"+">","</title"+">"," "+title+" ");
		merged=updateLanguageAttribute(merged);
		merged=updateMarkupBlock(merged,"PRE-HEAD","MarkupPreHead");
		merged=updateMarkupBlock(merged,"POST-HEAD","MarkupPostHead");
		merged=updateMarkupBlock(merged,"PRE-BODY","MarkupPreBody");
		merged=updateMarkupBlock(merged,"POST-SCRIPT","MarkupPostBody");
		// create form in a hidden frame and submit it to server
		var html='<input type="hidden" name="filename" value="">'
			+'<input type="hidden" name="contents" value="">';
		var form=window.createHiddenForm(config.options.txtSaveFromWebScriptURL,html);
		form.filename.value=target;
		form.contents.value=merged;
		form.submit();
	}
}
//}}}

//{{{
window.createHiddenForm=function(action,body) {
	var f=document.getElementById("saveFromWebFrame");
	if (f) document.body.removeChild(f);
	var f=createTiddlyElement(document.body,"iframe","saveFromWebFrame");
	f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
	var d=f.document;
	if (f.contentDocument) d=f.contentDocument; // For NS6
	else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
	d.open();
	d.writeln('<form target="_self" action="'+action+'" method="post" enctype="multipart/form-data">'+body+'</form>');
	d.close();
	return d.getElementsByTagName("form")[0];
}
//}}}

//{{{
// note: if blocked by browser security, this function will throw an error...
// the CALLING function should use "try{...} catch(e){...}" to handle the security errors
window.promptForFilename=function(msg,path,file,defext) {
	var result="";
	if(window.Components) { // moz
		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);
		picker.displayDirectory=null;
		picker.defaultExtension=defext;
		picker.defaultString=file;
		picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
		if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
	}
	else { // IE (XP only)
		var s = new ActiveXObject('UserAccounts.CommonDialog');
		s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
		s.FilterIndex=1; // default to ALL files;
		s.InitialDir=path;
		s.FileName=file;
		if (s.showOpen()) var result=s.FileName;
	}
	return result;
}
//}}}
|Name|SaveFromWebPluginInfo|
|Source|http://www.TiddlyTools.com/#SaveFromWebPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveFromWebPluginInfo|
|Version|1.3.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|documentation|
|Requires||
|Overrides||
|Description|documentation for SaveFromWebPlugin|
Normally, when you are viewing a TiddlyWiki document over the web (i.e., not via {{{file://}}}) and you select the "save changes" (or "save to disk") command, an error message is displayed: //__"You need to save this TiddlyWiki to a file before you can save changes."__//  This plugin extends the use of {{{<<saveChanges>>}}} so that when you are viewing and/or editing a remote TiddlyWiki document, instead of receiving this somewhat confusing and unhelpful message, you can still click the "save changes" (or "save to disk") command to ''store a copy of the remote document directly onto your local filesystem'', //including any unsaved tiddler changes/additions you have made while working on-line.//
!!!!!Usage
<<<
When you select <<saveChanges>> while viewing a remote document (i.e., a URL starting with http: rather than file:), the plugin first ''retrieves the TiddlyWiki core source code from the original document'' file stored on the remote server.  Then, it ''combines that core source with the tiddlers'' contained in the currently loaded document, ''including any changes you have made.''

While the next step //should// be to simply write the merged core+tiddler data directly to your hard drive, certain JavaScript features, such as reading/writing directly to the local filesystem, require expanded "cross-domain" privileges that are normally restricted for use only with ''signed'' scripts.  Although some browsers will let you grant filesystem permissions to a remotely-loaded script, this usually involves either a series of popup confirmation messages or manually re-configuring (and/or disabling) your browser's built-in security protections, which often include settings and options that most users find difficult to understand and inconvenient to access.

To avoid these security complications, the "save from web" processing requires just a few additional steps to prepare the modified document and deliver it to your browser: rather than writing the document data directly to the local filesystem, the plugin ''sends the merged core+tiddler data to a small companion script installed on the remote server'' (see savefromweb.php, below).  This simple "reflector" script then immediately ''downloads the new document data back to the browser'', which prompts you to either open the downloaded document for viewing or save it to your local hard drive.  Once the document has been stored on your filesystem, you can open that copy in your browser and work offline with full access to all TiddlyWiki features.

Important note for users of Internet Explorer's Popup Blocker feature...
>{{block{
//The default security settings of IE's "Popup Blocker" feature will warn you whenever an attempt is made to download a file in response to a scripted action such as the internal javascript processing performed by SaveFromWebPlugin.  However, if you then click IE's yellow warning message and select the 'download this file...' menu command, this will also cause IE to attempt a 'page transition' away from the currently loaded TiddlyWiki document... but, because there are unsaved changes in the document, you will first receive a confirmation message, allowing you to cancel the page transition.  Regrettably, this also prevents the download from succeeding.  Unfortunately, if you permit the page transition to occur, then your TiddlyWiki document is immediately reloaded and all the unsaved tiddler changes are discarded... and the download still fails to complete!//

''__To permit SaveFromWebPlugin to function properly with Internet Explorer, you will need to adjust the "download" security setting...__''
#From the ''Tools > Internet Options > Security'' tab,
#Select the "Internet" security zone (or what ever zone you are using to view the remote document)
#Press the "Custom level..." button
#In the "Settings" listbox, scroll to the "Downloads" section
#''ENABLE "automatic prompting for downloads"''(the first setting in the section)
#Press OK to accept the new settings.
}}}
<<<
!!!!!Configuration
> see [[SaveFromWebConfig]]
!!!!! Server script installation
<<<
On your web server, in the same directory as your published document, create a file called ''{{{savefromweb.php}}}'', containing the following PHP server-side script.  //(note: you can actually give this script any name you like, and place it at //any// URL, even one that is on a different domain from the document you are saving.  However, to do so you must specify the server-side script location using the plugin's configuration settings//
//{{{
<?php
// savefromweb.php
// Author: Eric L. Shulman / ELS Design Studios
// Source: http://www.TiddlyTools.com/savefromweb.php
// License: http://www.TiddlyTools.com/#LegalStatements
// Usage: install the php script on the server in the same directory as your TiddlyWiki document(s)

// This script acts as a 'reflector', so that any contents sent to it (via form POST) will
// be sent back to the browser as a binary file.  The browser then prompts you to
// save the content to a local file.  Because this process uses the browser's built-in
// download-and-save/open handler, it does not require security permissions to access
// the local filesystem.

$args=$_POST;
header('Pragma: private');
header('Cache-control: private, must-revalidate');
header('Content-type: application/binary; charset="UTF-8"');
header('Content-disposition: attachment; filename="'.$args['filename'].'"');
$c=$args['contents'];
$c=str_replace("\\'","'",$c); // decode single-quotes
$c=str_replace("\\\"","\"",$c); // decode double-quotes
$c=str_replace("\\\\","\\",$c); // decode backslashes
$c=str_replace("\r\n","\n",$c); // change CRLF to LF
print $c;
?>
//}}}
<<<
!!!!!Direct filesystem access (browser security permissions)
<<<
Although sending the merged document data from browser to server and back again allows it to be saved to your filesystem without requiring you to extensively re-configure your browser's built-in security protections, it also increases the overall processing time because the document's data is actually being transmitted //three// times: it is first retrieved from the remote server to get the TiddlyWiki core source; then, after merging with the updated tiddler data, it is sent back to the server, which immediately 'reflects' it back to the browser for final handling by the built-in "file download" interface.

However, ''if you are accessing a "trusted site"'' (perhaps on a server within a secure private network), depending upon the specific options provided by your browser, ''you may be able to eliminate the round-trip processing by authorizing the appropriate filesystem security permissions in your browser''.  When filesystem access has been permitted, instead of making the round trip with the merged core+tiddler data, the plugin will directly prompt you for a destination path/file, using your computer's "native" path/file selection interface, and then write new the TiddlyWiki document data directly to the indicated location on your local file system.

FireFox users: please see [[FAQ_BrowserSecurity]] for information on configuring your browser to permit remote filesystem access from trusted sites
<<<
!!!!!Revisions
<<<
2008.09.29 [1.3.1] in saveFromWeb(), do NOT convert UTF8 to Unicode when merging retrieved source for submission to server-side reflector script.  Fixes mangling of international characters and symbols.
2008.01.08 [*.*.*] plugin size reduction: documentation moved to SaveFromWebPluginInfo
2007.08.08 [1.3.0] added caching of the downloaded TW core source code so it only has to be retrieved once.
2007.08.08 [1.2.5] added an option to 'pre-fetch' the TW core when plugin is initialized, so that the download-and-cache will be performed, in background, each time the document is loaded/re-loaded.  Also, added option to allow attempt to use direct filesystem access (bypassing the round-trip through the server-side reflector script) so you can save a remote file to your local filesystem, even if the connection to the network is dropped after the document was loaded into the browser.  If local filesystem permissions are not granted, the plugin will still attempt to use the server-side reflector script as a fallback.
2007.08.07 [1.2.0] removed 'download only' optimization: when a document is unchanged, instead of performing a simple download from server, the plugin now performs a full 'round-trip' process (i.e., download the TW source from a server, merge with current tiddlers, and then upload merged document and reflect back as a binary file).  Although the round-trip takes longer, it does permit the reflector script to be located ANYWHERE on the net, at ANY valid URL, rather than having to be placed on the same server and in the same directory as the remote document.  This should permit online services such as TiddlySpot to support SaveFromWebPlugin using a single hosted copy of the reflector script that can be shared by all users.
2007.07.27 [1.1.1] new documentation and code cleanup
2007.07.26 [1.1.0] re-wrote to support savefromweb.php remote "reflector" script.  Allows use of browser's native download dialog to receive file as a fallback alternative to using local filesystem I/O (which would require additional security permissions)
2007.06.27 [1.0.1] in saveFromWeb(), pass content from server through convertUnicodeToUTF8() before writing to file.
2007.06.26 [1.0.0] initial release
<<<
<<search>>[[GettingStarted]]<<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<upload>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
<<toggleSideBar "" "" hide>>Universidad de Sevilla, Dept. Geometría y Topología 
Manuel Cárdenas' homepage
/***
|''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);
  } 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);}
    this.buildNavigator();
  }
  contentWrapper.toggleClass("slideShowMode");
  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.
<!--{{{-->
@media print {#siteSubtitle {display: none ! important;}}
@media print {#siteTitle {display: none ! important;}}
@media print {.tiddler .siteSubtitle {display: none ! important;}}
@media print {.tiddler .siteTitle {display: none ! important;}}
@media print {#mainMenu {display: none ! important;}}
@media print {#topMenu {display: none ! important;}}
@media print {#sidebar {display: none ! important;}}
@media print {#messageArea {display: none ! important;}} 
@media print {#toolbar {display: none ! important;}}
@media print {.header {display: none ! important;}}
@media print {.tiddler .subtitle {display: none ! important;}}
@media print {.tiddler .toolbar {display; none ! important; }}
@media print {.tiddler .tagging {display; none ! important; }}
@media print {.tiddler .tagged {display; none ! important; }}
<!--}}}-->
[[StyleSheetShortcuts]] 
[[StyleSheetKanbanPlugin]] 
/*{{{*/

.kanbantable {
	float:none;
	clear:both;
	display:block;
}

.kanbancolumndiv	{
	float:left;
	display:inline;
	margin: 0em 0em 0em 0.5em; 
}

.kanbancolumn {
	list-style: none; 
	margin: 0;
	padding: 0;
}
	
.kanbancolumnheader { 
	font-weight: bold; 
	height: 3em; 
	background-color: #e0e0e0; 
	color: #a0a0a0;
	border: 1px solid black; 
	align: center;
}

.kanbannewlink {
	align: right;
	color: #0000F0;
}

.kanbanworkitem { 
	font-size: 80%; 
	border: 1px solid black; 
	background-color: #e0ffe0; 
 	margin: 0.5em 0em 0.5em 0em;
}

/*}}}*/
/* text alignments */
.left
	{ display:block;text-align:left; }
.center
	{ display:block;text-align:center; }
.center table
	{ margin:auto !important; }
.right	
	{ display:block;text-align:right; }
.justify
	{ display:block;text-align:justify; }
.indent
	{ display:block;margin:0;padding:0;border:0;margin-left:2em; }
.floatleft
	{ float:left; }
.floatright
	{ float:right; }
.valignTop, .valignTop table, .valignTop tbody, .valignTop th, .valignTop tr, .valignTop td
	{ vertical-align:top; }
.valignBottom, .valignBottom table, .valignBottom tbody, .valignBottom th, .valignBottom tr, .valignBottom td
	{ vertical-align:bottom; }
.clear
	{ clear:both; }
.wrap
	{ white-space:normal; }
.nowrap
	{ white-space:nowrap; }
.hidden
	{ display:none; }
.show
	{ display:inline !important; }
.span
	{ display:span; }
.block
	{ display:block; }
.relative
	{ position:relative; }
.absolute
	{ position:absolute; }

/* font sizes */
.big
	{ font-size:14pt;line-height:120% }
.medium
	{ font-size:12pt;line-height:120% }
.normal
	{ font-size:9pt;line-height:120% }
.small
	{ font-size:8pt;line-height:120% }
.fine
	{ font-size:7pt;line-height:120% }
.tiny
	{ font-size:6pt;line-height:120% }
.larger
	{ font-size:120%; }
.smaller
	{ font-size:80%; }

/* font styles */
.bold
	{ font-weight:bold; }
.italic
	{ font-style:italic; }
.underline
	{ text-decoration:underline; }

/* plain list items (no bullets or indent) */
.nobullets li { list-style-type: none; margin-left:-2em; }

/* vertical tabsets - courtesy of Tobias Beer */
.vTabs .tabset {float:left;display:block;padding:0px;margin-top:.5em;min-width:20%;}
.vTabs .tabset .tab {display:block;text-align:right;padding:2px 3px 2px 7px; margin:0 1px 1px 0;}
.vTabs .tabContents {margin-left:20%;max-width:80%;padding:5px;}
.vTabs .tabContents .tabContents {border:none; background:transparent;}

/* multi-column tiddler content (not supported in Internet Explorer) */
.twocolumns { display:block;
	-moz-column-count:2; -moz-column-gap:1em; -moz-column-width:50%; /* FireFox */
	-webkit-column-count:2; -webkit-column-gap:1em; -webkit-column-width:50%; /* Safari */
	column-count:2; column-gap:1em; column-width:50%; /* Opera */
}
.threecolumns { display:block;
	-moz-column-count:3; -moz-column-gap:1em; -moz-column-width:33%; /* FireFox */
	-webkit-column-count:3; -webkit-column-gap:1em; -webkit-column-width:33%; /* Safari */
	column-count:3; column-gap:1em; column-width:33%; /* Opera */
}
.fourcolumns { display:block;
	-moz-column-count:4; -moz-column-gap:1em; -moz-column-width:25%; /* FireFox */
	-webkit-column-count:4; -webkit-column-gap:1em; -webkit-column-width:25%; /* Safari */
	column-count:4; column-gap:1em; column-width:25%; /* Opera */
}

/* page breaks */
.breakbefore { page-break-before:always; }
.breakafter { page-break-before:always; } 

/* show/hide browser-specific content for InternetExplorer vs. non-IE ("moz") browsers */
*[class="ieOnly"]
	{ display:none; } /* hide in moz (uses CSS selector) */
* html .mozOnly, *:first-child+html .mozOnly
	{ display: none; } /* hide in IE (uses IE6/IE7 CSS hacks) */

/* borderless tables */
.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody
	{ border:0 !important; margin:0 !important; padding:0 !important; }
.widetable, .widetable table
	{ width:100%; }

/* thumbnail images (fixed-sized scaled images) */
.thumbnail img { height:5em !important; }

/* stretchable images (auto-size to fit tiddler) */
.stretch img { width:95%; }

/* grouped content */
.outline
	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; }
.menubox
	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#fff; color:#000; }
.menubox .button, .menubox .tiddlyLinkExisting, .menubox .tiddlyLinkNonExisting
	{ color:#009 !important; }
.groupbox
	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#ffe; color:#000; }
.groupbox a, .groupbox .button, .groupbox .tiddlyLinkExisting, .groupbox .tiddlyLinkNonExisting
	{ color:#009 !important; }
.groupbox code
	{ color:#333 !important; }
.borderleft
	{ margin:0;padding:0;border:0;margin-left:1em; border-left:1px dotted; padding-left:.5em; }
.borderright
	{ margin:0;padding:0;border:0;margin-right:1em; border-right:1px dotted; padding-right:.5em; }
.borderbottom
	{ margin:0;padding:1px 0;border:0;border-bottom:1px dotted; margin-bottom:1px; padding-bottom:1px; }
.bordertop
	{ margin:0;padding:0;border:0;border-top:1px dotted; margin-top:1px; padding-top:1px; }

/* scrolled content */
.scrollbars { overflow:auto; }
.height10em { height:10em; }
.height15em { height:15em; }
.height20em { height:20em; }
.height25em { height:25em; }
.height30em { height:30em; }
.height35em { height:35em; }
.height40em { height:40em; }

/* compact form */
.smallform
	{ white-space:nowrap; }
.smallform input, .smallform textarea, .smallform button, .smallform checkbox, .smallform radio, .smallform select
	{ font-size:8pt; }

/* stretchable edit fields and textareas (auto-size to fit tiddler) */
.stretch input { width:99%; }
.stretch textarea { width:99%; }

/* compact input fields (limited to a few characters for entering percentages and other small values) */
.onechar input   { width:1em; }
.twochar input   { width:2em; }
.threechar input { width:3em; }
.fourchar input  { width:4em; }
.fivechar input  { width:5em; }

/* text colors */
.white { color:#fff !important }
.gray  { color:#999 !important }
.black { color:#000 !important }
.red   { color:#f66 !important }
.green { color:#0c0 !important }
.blue  { color:#99f !important }

/* rollover highlighting */
.mouseover 
	{color:[[ColorPalette::TertiaryLight]] !important;}
.mouseover a
	{color:[[ColorPalette::TertiaryLight]] !important;}
.selected .mouseover
	{color:[[ColorPalette::Foreground]] !important;}
.selected .mouseover .button, .selected .mouseover a
	{color:[[ColorPalette::PrimaryDark]] !important;}

/* rollover zoom text */
.zoomover
	{ font-size:80% !important; }
.selected .zoomover
	{ font-size:100% !important; }

/* [[ColorPalette]] text colors */
.Background	{ color:[[ColorPalette::Background]];	 }
.Foreground	{ color:[[ColorPalette::Foreground]];	 }
.PrimaryPale	{ color:[[ColorPalette::PrimaryPale]];	 }
.PrimaryLight	{ color:[[ColorPalette::PrimaryLight]];	 }
.PrimaryMid	{ color:[[ColorPalette::PrimaryMid]];	 }
.PrimaryDark	{ color:[[ColorPalette::PrimaryDark]];	 }
.SecondaryPale	{ color:[[ColorPalette::SecondaryPale]]; }
.SecondaryLight	{ color:[[ColorPalette::SecondaryLight]];}
.SecondaryMid	{ color:[[ColorPalette::SecondaryMid]];	 }
.SecondaryDark	{ color:[[ColorPalette::SecondaryDark]]; }
.TertiaryPale	{ color:[[ColorPalette::TertiaryPale]];	 }
.TertiaryLight	{ color:[[ColorPalette::TertiaryLight]]; }
.TertiaryMid	{ color:[[ColorPalette::TertiaryMid]];	 }
.TertiaryDark	{ color:[[ColorPalette::TertiaryDark]];	 }
.Error		{ color:[[ColorPalette::Error]];	 }

/* [[ColorPalette]] background colors */
.BGBackground	  { background-color:[[ColorPalette::Background]];	}
.BGForeground	  { background-color:[[ColorPalette::Foreground]];	}
.BGPrimaryPale	  { background-color:[[ColorPalette::PrimaryPale]];	}
.BGPrimaryLight	  { background-color:[[ColorPalette::PrimaryLight]];	}
.BGPrimaryMid	  { background-color:[[ColorPalette::PrimaryMid]];	}
.BGPrimaryDark	  { background-color:[[ColorPalette::PrimaryDark]];	}
.BGSecondaryPale  { background-color:[[ColorPalette::SecondaryPale]]; 	}
.BGSecondaryLight { background-color:[[ColorPalette::SecondaryLight]];	}
.BGSecondaryMid	  { background-color:[[ColorPalette::SecondaryMid]];	}
.BGSecondaryDark  { background-color:[[ColorPalette::SecondaryDark]]; 	}
.BGTertiaryPale	  { background-color:[[ColorPalette::TertiaryPale]];	}
.BGTertiaryLight  { background-color:[[ColorPalette::TertiaryLight]]; 	}
.BGTertiaryMid	  { background-color:[[ColorPalette::TertiaryMid]];	}
.BGTertiaryDark	  { background-color:[[ColorPalette::TertiaryDark]];	}
.BGError	  { background-color:[[ColorPalette::Error]];	 	}
    Defensa de la tesis de Sevilla.
    Jornadas Matemáticas: Geometrías. Sevilla, 20 de Marzo de 2001. Problemas geométricos sobre finitud: soluciones algebraicas.
    Seminario de Categorías y aplicaciones. Logroño 28 de Febrero y 1 de Marzo de 2003 Categorías Exactas pequeñas: K-teoría, localización y control.
    RSME-AMS meeting at Sevilla, 18-21 June 2003. Properly 3-realizable groups.
    990th AMS Meeting at Binghamton University, October 11-12, 2003. Controlled Exact Categories..
    Institute of Mathematics, Phisics and Mechanics, Ljubljana (Slovenja), September 9, 2005. Semistability does not imply proper $3$-realizability..
/***
|''Name:''|TiddlersBarPlugin|
|''Description:''|A bar to switch between tiddlers through tabs (like browser tabs bar).|
|''Version:''|1.2.5|
|''Date:''|Jan 18,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demos
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], open several tiddlers to use the tabs bar.
!Installation
#import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
#save and reload
#''if you're using a custom [[PageTemplate]]'', add {{{<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>}}} before {{{<div id='tiddlerDisplay'></div>}}}
#optionally, adjust StyleSheetTiddlersBar
!Tips
*Doubleclick on the tiddlers bar (where there is no tab) create a new tiddler.
*Tabs include a button to close {{{x}}} or save {{{!}}} their tiddler.
*By default, click on the current tab close all others tiddlers.
!Configuration options 
<<option chkDisableTabsBar>> Disable the tabs bar (to print, by example).
<<option chkHideTabsBarWhenSingleTab >> Automatically hide the tabs bar when only one tiddler is displayed. 
<<option txtSelectedTiddlerTabButton>> ''selected'' tab command button.
<<option txtPreviousTabKey>> previous tab access key.
<<option txtNextTabKey>> next tab access key.
!Code
***/
//{{{
config.options.chkDisableTabsBar = config.options.chkDisableTabsBar ? config.options.chkDisableTabsBar : false;
config.options.chkHideTabsBarWhenSingleTab  = config.options.chkHideTabsBarWhenSingleTab  ? config.options.chkHideTabsBarWhenSingleTab  : true;
config.options.txtSelectedTiddlerTabButton = config.options.txtSelectedTiddlerTabButton ? config.options.txtSelectedTiddlerTabButton : "closeOthers";
config.options.txtPreviousTabKey = config.options.txtPreviousTabKey ? config.options.txtPreviousTabKey : "";
config.options.txtNextTabKey = config.options.txtNextTabKey ? config.options.txtNextTabKey : "";
config.macros.tiddlersBar = {
	tooltip : "see ",
	tooltipClose : "click here to close this tab",
	tooltipSave : "click here to save this tab",
	promptRename : "Enter tiddler new name",
	currentTiddler : "",
	previousState : false,
	previousKey : config.options.txtPreviousTabKey,
	nextKey : config.options.txtNextTabKey,	
	tabsAnimationSource : null, //use document.getElementById("tiddlerDisplay") if you need animation on tab switching.
	handler: function(place,macroName,params) {
		var previous = null;
		if (config.macros.tiddlersBar.isShown())
			story.forEachTiddler(function(title,e){
				if (title==config.macros.tiddlersBar.currentTiddler){
					var d = createTiddlyElement(null,"span",null,"tab tabSelected");
					config.macros.tiddlersBar.createActiveTabButton(d,title);
					if (previous && config.macros.tiddlersBar.previousKey) previous.setAttribute("accessKey",config.macros.tiddlersBar.nextKey);
					previous = "active";
				}
				else {
					var d = createTiddlyElement(place,"span",null,"tab tabUnselected");
					var btn = createTiddlyButton(d,title,config.macros.tiddlersBar.tooltip + title,config.macros.tiddlersBar.onSelectTab);
					btn.setAttribute("tiddler", title);
					if (previous=="active" && config.macros.tiddlersBar.nextKey) btn.setAttribute("accessKey",config.macros.tiddlersBar.previousKey);
					previous=btn;
				}
				var isDirty =story.isDirty(title);
				var c = createTiddlyButton(d,isDirty ?"!":"x",isDirty?config.macros.tiddlersBar.tooltipSave:config.macros.tiddlersBar.tooltipClose, isDirty ? config.macros.tiddlersBar.onTabSave : config.macros.tiddlersBar.onTabClose,"tabButton");
				c.setAttribute("tiddler", title);
				if (place.childNodes) {
					place.insertBefore(document.createTextNode(" "),place.firstChild); // to allow break line here when many tiddlers are open
					place.insertBefore(d,place.firstChild); 
				}
				else place.appendChild(d);
			})
	}, 
	refresh: function(place,params){
		removeChildren(place);
		config.macros.tiddlersBar.handler(place,"tiddlersBar",params);
		if (config.macros.tiddlersBar.previousState!=config.macros.tiddlersBar.isShown()) {
			story.refreshAllTiddlers();
			if (config.macros.tiddlersBar.previousState) story.forEachTiddler(function(t,e){e.style.display="";});
			config.macros.tiddlersBar.previousState = !config.macros.tiddlersBar.previousState;
		}
	},
	isShown : function(){
		if (config.options.chkDisableTabsBar) return false;
		if (!config.options.chkHideTabsBarWhenSingleTab) return true;
		var cpt=0;
		story.forEachTiddler(function(){cpt++});
		return (cpt>1);
	},
	selectNextTab : function(){  //used when the current tab is closed (to select another tab)
		var previous="";
		story.forEachTiddler(function(title){
			if (!config.macros.tiddlersBar.currentTiddler) {
				story.displayTiddler(null,title);
				return;
			}
			if (title==config.macros.tiddlersBar.currentTiddler) {
				if (previous) {
					story.displayTiddler(null,previous);
					return;
				}
				else config.macros.tiddlersBar.currentTiddler=""; 	// so next tab will be selected
			}
			else previous=title;
			});		
	},
	onSelectTab : function(e){
		var t = this.getAttribute("tiddler");
		if (t) story.displayTiddler(null,t);
		return false;
	},
	onTabClose : function(e){
		var t = this.getAttribute("tiddler");
		if (t) {
			if(story.hasChanges(t) && !readOnly) {
				if(!confirm(config.commands.cancelTiddler.warning.format([t])))
				return false;
			}
			story.closeTiddler(t);
		}
		return false;
	},
	onTabSave : function(e) {
		var t = this.getAttribute("tiddler");
		if (!e) e=window.event;
		if (t) config.commands.saveTiddler.handler(e,null,t);
		return false;
	},
	onSelectedTabButtonClick : function(event,src,title) {
		var t = this.getAttribute("tiddler");
		if (!event) event=window.event;
		if (t && config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton])
			config.commands[config.options.txtSelectedTiddlerTabButton].handler(event, src, t);
		return false;
	},
	onTiddlersBarAction: function(event) {
		var source = event.target ? event.target.id : event.srcElement.id; // FF uses target and IE uses srcElement;
		if (source=="tiddlersBar") story.displayTiddler(null,'New Tiddler',DEFAULT_EDIT_TEMPLATE,false,null,null);
	},
	createActiveTabButton : function(place,title) {
		if (config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton]) {
			var btn = createTiddlyButton(place, title, config.commands[config.options.txtSelectedTiddlerTabButton].tooltip ,config.macros.tiddlersBar.onSelectedTabButtonClick);
			btn.setAttribute("tiddler", title);
		}
		else
			createTiddlyText(place,title);
	}
}

story.coreCloseTiddler = story.coreCloseTiddler? story.coreCloseTiddler : story.closeTiddler;
story.coreDisplayTiddler = story.coreDisplayTiddler ? story.coreDisplayTiddler : story.displayTiddler;

story.closeTiddler = function(title,animate,unused) {
	if (title==config.macros.tiddlersBar.currentTiddler)
		config.macros.tiddlersBar.selectNextTab();
	story.coreCloseTiddler(title,false,unused); //disable animation to get it closed before calling tiddlersBar.refresh
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

story.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle){
	story.coreDisplayTiddler(config.macros.tiddlersBar.tabsAnimationSource,tiddler,template,animate,unused,customFields,toggle);
	var title = (tiddler instanceof Tiddler)? tiddler.title : tiddler;  
	if (config.macros.tiddlersBar.isShown()) {
		story.forEachTiddler(function(t,e){
			if (t!=title) e.style.display="none";
			else e.style.display="";
		})
		config.macros.tiddlersBar.currentTiddler=title;
	}
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

var coreRefreshPageTemplate = coreRefreshPageTemplate ? coreRefreshPageTemplate : refreshPageTemplate;
refreshPageTemplate = function(title) {
	coreRefreshPageTemplate(title);
	if (config.macros.tiddlersBar) config.macros.tiddlersBar.refresh(document.getElementById("tiddlersBar"));
}

ensureVisible=function (e) {return 0} //disable bottom scrolling (not useful now)

config.shadowTiddlers.StyleSheetTiddlersBar = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .button {border:0}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .tab {white-space:nowrap}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar {padding : 1em 0.5em 2px 0.5em}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tabUnselected .tabButton, .tabSelected .tabButton {padding : 0 2px 0 2px; margin: 0 0 0 4px;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tiddler, .tabContents {border:1px [[ColorPalette::TertiaryPale]] solid;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar +="/*}}}*/";
store.addNotification("StyleSheetTiddlersBar", refreshStyles);

config.refreshers.none = function(){return true;}
config.shadowTiddlers.PageTemplate=config.shadowTiddlers.PageTemplate.replace(/<div id='tiddlerDisplay'><\/div>/m,"<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>\n<div id='tiddlerDisplay'></div>");

//}}}
/***
|''Name''|TiddlyKanban|
|''Description''|Renders tiddlers into a KANBAN and allows editing by drag-and-drop.|
|''Maintainer''|Tim Barnes|
|''Version''|0.9.0|
|''Status''|stable|
|''Source''|[[https://github.com/tim-barnes/TiddlyKanban]]|
|''License''|[[http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.5.0|
|''Feedback''|[[TiddlyWiki community|http://groups.google.com/group/TiddlyWiki]] |
|''Keywords''|kanban|
!Usage
{{{
<<kanban columncatagory1 columncatagory2 ...>>
}}}
Each {{{columncatagory}}} becomes a column in the kanban table.  Tiddlers tagged with {{{columncatagory}}} will be displayed as work cards in the column.
Each work card contains a link to the source tiddler and cards can be dragged and dropped between columns.
!!Examples
{{{<<kanban Backlog WIP Testing Complete>>}}}
will create and display a 4 column kanban.
!!Customising
Layout, colours and display of the kanban can be adjust by editing the StyleSheetKanbanPlugin shadow tiddler.
!Acknowledgements
TiddlyKanban was originally inspired by Stephan Schmidt's single page kanban ([[www.simple-kanban.com]]).
This plugin would not be possible without the excellent dragsort ([[http://dragsort.codeplex.com/]]) jQuery plugin.  
!Changelog
!!v0.9 (2011-11-20)
* initial release
!TODO
* Work card colours
* Work card tracking
!Known Issues
* Autoupdate does not work for tiddlers with spaces in the titles.
!Code
***/
//{{{
/*
!StyleSheet

.kanbantable {
	float:none;
	clear:both;
	display:block;
}

.kanbancolumndiv	{
	float:left;
	display:inline;
	margin: 0em 0em 0em 0.5em; 
}

.kanbancolumn {
	list-style: none; 
	margin: 0;
	padding: 0;
}
	
.kanbancolumnheader { 
	font-weight: bold; 
	height: 3em; 
	background-color: #e0e0e0; 
	color: #a0a0a0;
	border: 1px solid black; 
	align: center;
}

.kanbannewlink {
	align: right;
	color: #0000F0;
}

.kanbanworkitem { 
	font-size: 80%; 
	border: 1px solid black; 
	background-color: #e0ffe0; 
 	margin: 0.5em 0em 0.5em 0em;
}

!Code
*/
	
//Install the plugin
if(!version.extensions.TiddlyKanban) {
    version.extensions.TiddlyKanban = {installed:true};

	// jQuery List DragSort v0.4.3
	// License: http://dragsort.codeplex.com/license
	(function(b){b.fn.dragsort=function(k){var d=b.extend({},b.fn.dragsort.defaults,k),g=[],a=null,j=null;this.selector&&b("head").append("<style type='text/css'>"+(this.selector.split(",").join(" "+d.dragSelector+",")+" "+d.dragSelector)+" { cursor: pointer; }</style>");this.each(function(k,i){b(i).is("table")&&b(i).children().size()==1&&b(i).children().is("tbody")&&(i=b(i).children().get(0));var m={draggedItem:null,placeHolderItem:null,pos:null,offset:null,offsetLimit:null,scroll:null,container:i,init:function(){b(this.container).attr("data-listIdx", k).mousedown(this.grabItem).find(d.dragSelector).css("cursor","pointer");b(this.container).children(d.itemSelector).each(function(a){b(this).attr("data-itemIdx",a)})},grabItem:function(e){if(!(e.which!=1||b(e.target).is(d.dragSelectorExclude))){for(var c=e.target;!b(c).is("[data-listIdx='"+b(this).attr("data-listIdx")+"'] "+d.dragSelector);){if(c==this)return;c=c.parentNode}a!=null&&a.draggedItem!=null&&a.dropItem();b(e.target).css("cursor","move");a=g[b(this).attr("data-listIdx")];a.draggedItem= b(c).closest(d.itemSelector);var c=parseInt(a.draggedItem.css("marginTop")),f=parseInt(a.draggedItem.css("marginLeft"));a.offset=a.draggedItem.offset();a.offset.top=e.pageY-a.offset.top+(isNaN(c)?0:c)-1;a.offset.left=e.pageX-a.offset.left+(isNaN(f)?0:f)-1;if(!d.dragBetween)c=b(a.container).outerHeight()==0?Math.max(1,Math.round(0.5+b(a.container).children(d.itemSelector).size()*a.draggedItem.outerWidth()/b(a.container).outerWidth()))*a.draggedItem.outerHeight():b(a.container).outerHeight(),a.offsetLimit= b(a.container).offset(),a.offsetLimit.right=a.offsetLimit.left+b(a.container).outerWidth()-a.draggedItem.outerWidth(),a.offsetLimit.bottom=a.offsetLimit.top+c-a.draggedItem.outerHeight();var c=a.draggedItem.height(),f=a.draggedItem.width(),h=a.draggedItem.attr("style");a.draggedItem.attr("data-origStyle",h?h:"");d.itemSelector=="tr"?(a.draggedItem.children().each(function(){b(this).width(b(this).width())}),a.placeHolderItem=a.draggedItem.clone().attr("data-placeHolder",!0),a.draggedItem.after(a.placeHolderItem), a.placeHolderItem.children().each(function(){b(this).css({borderWidth:0,width:b(this).width()+1,height:b(this).height()+1}).html("&nbsp;")})):(a.draggedItem.after(d.placeHolderTemplate),a.placeHolderItem=a.draggedItem.next().css({height:c,width:f}).attr("data-placeHolder",!0));a.draggedItem.css({position:"absolute",opacity:0.8,"z-index":999,height:c,width:f});b(g).each(function(a,b){b.createDropTargets();b.buildPositionTable()});a.scroll={moveX:0,moveY:0,maxX:b(document).width()-b(window).width(), maxY:b(document).height()-b(window).height()};a.scroll.scrollY=window.setInterval(function(){if(d.scrollContainer!=window)b(d.scrollContainer).scrollTop(b(d.scrollContainer).scrollTop()+a.scroll.moveY);else{var c=b(d.scrollContainer).scrollTop();if(a.scroll.moveY>0&&c<a.scroll.maxY||a.scroll.moveY<0&&c>0)b(d.scrollContainer).scrollTop(c+a.scroll.moveY),a.draggedItem.css("top",a.draggedItem.offset().top+a.scroll.moveY+1)}},10);a.scroll.scrollX=window.setInterval(function(){if(d.scrollContainer!=window)b(d.scrollContainer).scrollLeft(b(d.scrollContainer).scrollLeft()+ a.scroll.moveX);else{var c=b(d.scrollContainer).scrollLeft();if(a.scroll.moveX>0&&c<a.scroll.maxX||a.scroll.moveX<0&&c>0)b(d.scrollContainer).scrollLeft(c+a.scroll.moveX),a.draggedItem.css("left",a.draggedItem.offset().left+a.scroll.moveX+1)}},10);a.setPos(e.pageX,e.pageY);b(document).bind("selectstart",a.stopBubble);b(document).bind("mousemove",a.swapItems);b(document).bind("mouseup",a.dropItem);d.scrollContainer!=window&&b(window).bind("DOMMouseScroll mousewheel",a.wheel);return!1}},setPos:function(e, c){var f=c-this.offset.top,h=e-this.offset.left;d.dragBetween||(f=Math.min(this.offsetLimit.bottom,Math.max(f,this.offsetLimit.top)),h=Math.min(this.offsetLimit.right,Math.max(h,this.offsetLimit.left)));this.draggedItem.parents().each(function(){if(b(this).css("position")!="static"&&(!b.browser.mozilla||b(this).css("display")!="table")){var a=b(this).offset();f-=a.top;h-=a.left;return!1}});if(d.scrollContainer==window)c-=b(window).scrollTop(),e-=b(window).scrollLeft(),c=Math.max(0,c-b(window).height()+ 5)+Math.min(0,c-5),e=Math.max(0,e-b(window).width()+5)+Math.min(0,e-5);else var l=b(d.scrollContainer),g=l.offset(),c=Math.max(0,c-l.height()-g.top)+Math.min(0,c-g.top),e=Math.max(0,e-l.width()-g.left)+Math.min(0,e-g.left);a.scroll.moveX=e==0?0:e*d.scrollSpeed/Math.abs(e);a.scroll.moveY=c==0?0:c*d.scrollSpeed/Math.abs(c);this.draggedItem.css({top:f,left:h})},wheel:function(e){if((b.browser.safari||b.browser.mozilla)&&a&&d.scrollContainer!=window){var c=b(d.scrollContainer),f=c.offset();e.pageX>f.left&& e.pageX<f.left+c.width()&&e.pageY>f.top&&e.pageY<f.top+c.height()&&(f=e.detail?e.detail*5:e.wheelDelta/-2,c.scrollTop(c.scrollTop()+f),e.preventDefault())}},buildPositionTable:function(){var a=this.draggedItem==null?null:this.draggedItem.get(0),c=[];b(this.container).children(d.itemSelector).each(function(d,h){if(h!=a){var g=b(h).offset();g.right=g.left+b(h).width();g.bottom=g.top+b(h).height();g.elm=h;c.push(g)}});this.pos=c},dropItem:function(){if(a.draggedItem!=null){b(a.container).find(d.dragSelector).css("cursor", "pointer");a.placeHolderItem.before(a.draggedItem);var e=a.draggedItem.attr("data-origStyle");a.draggedItem.attr("style",e);e==""&&a.draggedItem.removeAttr("style");a.draggedItem.removeAttr("data-origStyle");a.placeHolderItem.remove();b("[data-dropTarget]").remove();window.clearInterval(a.scroll.scrollY);window.clearInterval(a.scroll.scrollX);var c=!1;b(g).each(function(){b(this.container).children(d.itemSelector).each(function(a){parseInt(b(this).attr("data-itemIdx"))!=a&&(c=!0,b(this).attr("data-itemIdx", a))})});c&&d.dragEnd.apply(a.draggedItem);a.draggedItem=null;b(document).unbind("selectstart",a.stopBubble);b(document).unbind("mousemove",a.swapItems);b(document).unbind("mouseup",a.dropItem);d.scrollContainer!=window&&b(window).unbind("DOMMouseScroll mousewheel",a.wheel);return!1}},stopBubble:function(){return!1},swapItems:function(e){if(a.draggedItem==null)return!1;a.setPos(e.pageX,e.pageY);for(var c=a.findPos(e.pageX,e.pageY),f=a,h=0;c==-1&&d.dragBetween&&h<g.length;h++)c=g[h].findPos(e.pageX, e.pageY),f=g[h];if(c==-1||b(f.pos[c].elm).attr("data-placeHolder"))return!1;j==null||j.top>a.draggedItem.offset().top||j.left>a.draggedItem.offset().left?b(f.pos[c].elm).before(a.placeHolderItem):b(f.pos[c].elm).after(a.placeHolderItem);b(g).each(function(a,b){b.createDropTargets();b.buildPositionTable()});j=a.draggedItem.offset();return!1},findPos:function(a,b){for(var d=0;d<this.pos.length;d++)if(this.pos[d].left<a&&this.pos[d].right>a&&this.pos[d].top<b&&this.pos[d].bottom>b)return d;return-1}, createDropTargets:function(){d.dragBetween&&b(g).each(function(){var d=b(this.container).find("[data-placeHolder]"),c=b(this.container).find("[data-dropTarget]");d.size()>0&&c.size()>0?c.remove():d.size()==0&&c.size()==0&&(b(this.container).append(a.placeHolderItem.removeAttr("data-placeHolder").clone().attr("data-dropTarget",!0)),a.placeHolderItem.attr("data-placeHolder",!0))})}};m.init();g.push(m)});return this};b.fn.dragsort.defaults={itemSelector:"li",dragSelector:"li",dragSelectorExclude:"input, textarea, a[href]", dragEnd:function(){},dragBetween:!1,placeHolderTemplate:"<li>&nbsp;</li>",scrollContainer:window,scrollSpeed:5}})(jQuery);
	//End of dragsort code
	
    //--
    //-- Kanban Macro
    //--
    config.macros.kanban = {
    	init: function() {
			//Install the StyleSheetKanbanPlugin shadow tiddler
			var name = "StyleSheet" + tiddler.title;
			config.shadowTiddlers[name] = "/*{{{*/\n%0\n/*}}}*/".
			    format(store.getTiddlerText(tiddler.title + "##StyleSheet")); 
	
	        var style = store.getTiddlerText(name);
	        if (style) {
	            setStylesheet(style, name);
	        }
    		
    		//Add the update notification
    		store.addNotification(null, this.tiddler_changed);
    	},
    	
   		handler: function(place,macroName,params)
	    {
	    	//Guard against recursive kanbans....
	    	if (jQuery(place).closest(".kanbantable").length > 0) {
	    		createTiddlyError(place,"KanbanPlugin","Kanbans cannot be embedded in other kanbans!");
	    		return;
	    	}
	    	
	    	//Create the kanban
	    	var states = params;
	    	var table = createTiddlyElement(place, 'span', null, 'kanbantable', null);
			var ids = "";
			var width = (100 / states.length) - 1.5;
					
			for (j=0; j< states.length; j++) {
				var state = states[j];
				
				var stateDiv = createTiddlyElement(table, 'div', null, 'kanbancolumndiv', null);
				jQuery(stateDiv).css('width', width + "%");
				
				var header = createTiddlyElement(stateDiv, 'div', null, 'kanbancolumnheader', state);
				var column = createTiddlyElement(stateDiv, 'div', null, 'kanbancolumn', null);
				jQuery(column).attr("kanbanstate", state);
											
				var tiddlers = store.getTaggedTiddlers(state);
				
				ids += ".kanbancolumn[kanbanstate=" + state + "],";
				
				for (k = 0; k < tiddlers.length; k++) {
					this.create_workitem(tiddlers[k], column, state);
				}
				
				//Create a new tiddler link at the base of each Kanban column
				var newLink = "<<newTiddler tag:%0>>".format(state);
				wikify(newLink, stateDiv);				
			}
			
			//Enable drag and drop between columns
			jQuery(ids, table).dragsort({ 
				dragSelector: ".kanbanworkitem",
				dragBetween: true, 
				dragEnd: config.macros.kanban.itemDrop
				});
	    },
	    
	    //--
		//-- Renders a tiddler into a work item
		//--
		render_workitem: function(tiddler, cell)
		{
			//Render the tiddler to the cell
			wikify('[[' + tiddler.title + ']]', cell);
			wikify('----',cell)
			wikify(tiddler.text, cell);
		},
		
		//--
		//-- Creates the work item element
		//--
		create_workitem: function(tiddler, column, state)
		{
			//Create the cell
			var cell = createTiddlyElement(column, 'li', null, 'kanbanworkitem', null);
			
			jQuery(cell).attr("kanbanstate", state);
			jQuery(cell).attr("kanbanid", tiddler.title);
			
			this.render_workitem(tiddler, cell);
		},
	    
	    //--
		//-- Called on drop from the dragsort function
		//--
		itemDrop: function()
		{	
			try {
				var id = this.attr('kanbanid');
				var newParent = this.parent().attr('kanbanstate');
				
				//Get the tiddler from the store
				var tiddler = store.getTiddler(id);
				if (tiddler)
				{
					var oldTag = this.attr('kanbanstate');
					
					var tagIdx = tiddler.tags.indexOf(oldTag);
					tiddler.tags[tagIdx] = newParent;
					this.attr('kanbanstate', newParent);
					
					//Ensure the tiddler is saved
					tiddler.incChangeCount();
					tiddler.saveToDiv();
					store.setDirty(id, true);
					
					if (config.options.chkAutoSave == true)
					{
						saveChanges();
					}
					
					//Update all the kanbans
					config.macros.kanban.tiddler_changed(id);
				} else {
					//Error case
					alert("Something is wrong here: " + id + " could not be retrieved from the tiddler store!");
				}
			} 
        	catch(ex) {
        		pluginInfo.log.push("Exception thrown when updating tiddler: " + tiddlerTitle + "\nException was:  " + ex.name + "\n" + ex.message);
        	}
		},
		
		//--
        //-- Notification and change handler
        //--
        tiddler_changed: function(tiddlerTitle)
        {
        	//Guard against tiddler titles with spaces
        	//Not supported for now
        	if (tiddlerTitle.search(" ") != -1) {
        		return;
        	}
        	
        	try {
	         	var tiddler = store.getTiddler(tiddlerTitle);
	        	if (tiddler)
	        	{
	        		jQuery(".kanbancolumn").each(function (index) {
        				var state = jQuery(this).attr("kanbanstate");
        				
        				//Get all the matching workitems for this column
        				var workItems = jQuery(this).children(".kanbanworkitem[kanbanid=" + tiddlerTitle + "]");
        				
        				if (tiddler.isTagged(state)) {
	        				if (workItems.length > 0) {
	        					workItems.each(
					        		function (index) {
				        				jQuery(this).empty();
					        			config.macros.kanban.render_workitem(tiddler, this);
					        		});	
	        				} else {
	        					config.macros.kanban.create_workitem(tiddler, this, state);
	        				}
        				} else {
        					//Work item is not in this kanban state
        					workItems.remove();
        				}
        			});
	        	} 
	        	else
	        	{
	        		//Tiddler was deleted, remove all on display.
	  				jQuery(".kanbanworkitem[kanbanid=" + tiddlerTitle + "]").remove();
	        	}
        	} 
        	catch(ex) {
        		pluginInfo.log.push("Exception thrown when updating tiddler: " + tiddlerTitle + "\nException was:  " + ex.name + "\n" + ex.message);
        	}
        }
    };
}
//}}}
/%
!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");

//}}}
!!!Horario de tutorías 2011-12
* Primer cuatrimestre: sin docencia , previa cita en mcard"at"us.es
* Segundo cuatrimestre hasta el 22/06/12: martes de 11:30 a 13:00, miércoles de 9:30 a 12:00, jueves de 10:00 a 12:00 y viernes de 11:30 a 12:00.
* Segundo cuatrimestre del 22/06/12 al final del cuatrimestre: martes y miércoles de 9:30 a 12:30 
!!!Cursos 2011-12:
* Segundo cuatrimestre: [[Introduccion a la Topología Geométrica|http://intro2gt.tiddlyspot.com/]].
* Segundo cuatrimestre: [[Elementos de la Homología Clásica (Grupo B)|http://ehcuds.tiddlyspot.com/]].
* Segundo cuatrimestre: [[Teoría de Homotopía|http://udsth0910.tiddlyspot.com/]].
!!!Curso 2010-11 Horario de tutorías
* Primer cuatrimestre: sin docencia , previa cita en mcard"at"us.es
* Segundo cuatrimestre hasta el 20/06/11: lunes, miércoles y jueves de 9:00 a 9:30 y de 11:30 a 12:30 y martes de 9:30 a 11:00.
* Segundo cuatrimestre del 21/06/11 al final del cuatrimestre: martes y miércoles de 9:30 a 12:30.
!!!!Cursos:
* Segundo cuatrimestre: Introduccion a la Topología Geométrica.
* Segundo cuatrimestre: Elementos de la Homología Clásica (Grupo A).
* Segundo cuatrimestre: Topología.
<<tiddler UploadPluginDoc>>
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 29/11/2011 10:50:17 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 10:52:04 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 10:52:29 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://127.0.0.1/twmcard/store.php]] | . | [[tw.html | http://127.0.0.1/twmcard/tw.html]] | backup |
| 29/11/2011 10:53:03 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 10:53:37 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 10:58:29 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 10:59:59 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 11:08:55 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 11:17:57 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://localhost/twmcard/store.php]] | . | [[tw.html | http://localhost/twmcard/tw.html]] | backup |
| 29/11/2011 11:26:21 | Cárdenas | [[twmcard2.html|file:///home/olmy/Desktop/tiddly/twhomepage2/twmcard2.html]] | [[store.php|http://personal.us.es/mcard/store.php]] | . | [[tw2.html | http://personal.us.es/mcard/tw2.html]] | backup |
UploadPlugin uses the following sequence for finding parameters :
#''macro'' parameters
#''Options'' saved in cookies
#''Plugin'' default values
!Options used by UploadPlugin
| Option | Value | Default |
|Upload Username: |<<option txtUploadUserName>>| |
|Upload Password: |<<option pasUploadPassword>>| |
|Url of the UploadService script: |<<option txtUploadStoreUrl urlInput>>| store.php |
|Relative Directory where to store the file: |<<option txtUploadDir urlInput>>| . (the script directory) |
|Filename of the uploaded file: |<<option txtUploadFilename urlInput>>| index.html |
|Directory to backup file on webserver^^(1)^^: |<<option txtUploadBackupDir urlInput>>| //null// (none/no backup) |
|Log in UploadLog |<<option chkUploadLog>> Trace Upload| true |
|Maximum of lines in UploadLog |<<option txtUploadLogMaxLine>>| 10 |

^^(1)^^No backup if Backup Directory is empty, the previous file will be overwritten. Use a '.' to backup in the script directory.

<<upload>> with these options.

!Upload Macro parameters
{{{
<<upload [storeUrl [toFilename [backupDir [uploadDir [username]]]]]>>
 Optional positional parameters can be passed to overwrite UploadOptions. 
}}}

!UploadToFile Macro Macro parameters
{{{
<<uploadTofile [filename [tiddlerTitle]]>>
 tiddlerTitle, filename: if omitted the title of the current tiddler
}}}

<<uploadToFile allowedsites.txt allowedsites.txt>>
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.4|
|''Date:''|2008-08-11|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 4,
	date: new Date("2008-08-11"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

//
// Environment
//

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

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

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

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

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

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

//
// uploadOptions Macro
//

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

//
// upload functions
//

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

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

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

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

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

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

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

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

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

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

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

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

//
// Utilities
// 

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

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

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

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

//
// Initializations
//

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

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

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

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


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


//}}}

I'm pleased to announce UploadPlugin 4.1.

!!It works as it did ...
First this new version is a ''refactored version''. That is to say that UploadPlugin works as it did before. But thanks to a number of enhancements in TiddlyWiki <<version>>, now it is based on the core HTTP functions for the low level AJAX and it does no more core hijacking. It also uses only core functions for the HTML and RSS file generation. So UploadPlugin will stay compatible with future evolution of StoreArea, ExtendedFields, FileTemplates ... 

!!... but even better
In addition to the {{{<<upload>>}}} macro, an entry in Backstage is also provided. An experimental UploadToHomeMacro using HomeParameters shadowed tiddler is also released, for now, as a separate plugin.

A lot of small enhancements (better messages, debugMode ...) and better reliability.

And the good news are that UploadLog :
*is optional,
*is automatically truncated,
*stores only the last uploads.

This new release includes also new versions of : UploadOptions, UploadPluginDoc, UploadForm, UploadPluginLingoFR, UploadPluginLingoEN. All tagged <<tag Upload>>

UploadPlugin requires PasswordOptionPlugin in your TiddlyWiki and an UploadService on the WebServer to store the TiddlyWiki file. Even if UploadPlugin 4.1 is compatible with previous store scripts, the easiest script to set up is [[store.php]] version 1.6.0 

Since TiddlyWiki 2.2 is in beta stage, you will find this release at http://tiddlylab.bidix.info/#Upload and also in the SVN repository at http://trac.tiddlywiki.org/tiddlywiki/browser/Trunk/contributors/BidiX

Comments and suggestions are welcome.

Enjoy,

-- BidiX
http://tiddlywiki.bidix.info
//last update: UploadPlugin v 4.1.3//

!Description
UploadPlugin with <<tag UploadService>> extend TiddlyWiki with @@upload@@ and @@save to web@@ commands. 
UploadPlugin uses Username and Password from UploadOptions stored in cookies to authenticate itself to [[store.php]] or [[store.cgi]].
UploadPlugin requires PasswordOptionPlugin.
French translation available as a separate tiddler UploadPluginMsgFR

!!UploadPlugin
*If the TiddlyWiki is viewed @@from local disk@@ :
**{{{<<upload ...>>}}}
***display as '''upload'''
***after saving to disk, upload to a website.
*If the TiddlyWiki is viewed @@from a website@@ :
**{{{<<upload ...>>}}}
***display as '''save to web'''
***save to the same website.
*If GenerateAnRssFeed in AdvancedOptions is set :
**generate the content of the RSSFeed 
**upload the RssFile
**Caution : use the SiteUrl tiddler to specify the right url of the TiddlyWiki in the generated RssFile
*DisplayMessage
*If a backupDir is specified
**and if a file already exists in the uploadDir withe the same fielname, move it in the backup dir and rename it with a timestamp
*if UploadLog is activated every upload action is logged in UploadLog
**only the last maxLines are stored
**if maxLine = -1 no truncation will occured 
hint : if UploadLog is the first tiddler in the TimelineTab, no tiddler has been changed since last upload.

!![[store.php]]
*UserVariables to set :
//{{{
$AUTHENTICATE_USER = true; // true | false
$USERS = array(
 'UserName1'=>'Password1', 
 'UserName2'=>'Password2', 
 'UserName3'=>'Password3'); // set usernames and strong passwords
$DEBUG = false; // true | false
//}}}
*method GET
**display an information page
*method POST
**if $~AUTHENTICATE_USER is ''true''
***presence and value of user and password are checked with $USER and $PASSWORD 
**if toFilename already exists and backDir parameter specified
***rename toFilename to backupDir/toFilename.AAAAMMDD.HHSS.html
**copy temporaryUploadedFile toFilename
**return status

!![[store.cgi]]
*UserVariables to set :
//{{{
CONFIG = {
 :users => {
 'UserName1'=>'Password1', 
 'UserName2'=>'Password2', 
 'UserName3'=>'Password3')
 },
 :authenticateUser => true,
 :backupExistingFile => true,
 :withUploadDir => true
}
//}}}
*same processing as store.php above

!Usage : 
{{{
<<upload>>
 uses UploadOptions saved in cookies :
 txtUploadUserName: username
 pasUploadPassword : password
 txtUploadStoreUrl : store script
 txtUploadDir : relative path for upload directory
 txtUploadFilename : upload filename
 txtUploadBackupDir : relative path for backup directory

<<upload [storeUrl [toFilename [backupDir [uploadDir [username]]]]]>>
 Optional positional parameters can be passed to overwrite 
 UploadOptions. 
}}}

Suggestion: Install the {{{<<upload ... >>}}} macro in SideBarOptions just below {{{<<saveChanges>>}}} macro.


!User manual
See HowToUpload

!Installation :
*Install the UploadPlugin as usual
*[[Upload]] the [[store.php]] file on your php aware webserver in your TiddlyWiki directory
*Protect your server against malicious upload. Two approaches :
**set $~AUTHENTICATE_USER to true in the [[store.php]] script
***configure $USER and $PASSWORD in the [[store.php]] script on your webserver
***set UploadOptions in conformity with [[store.php]]
**Use server protection :
***for Apache web server ([[for detail see Apache documentation|http://httpd.apache.org/docs/1.3/howto/htaccess.html]]) : 
****configure and upload the [[.htaccess]] [[.passwd]]
***for other web servers see the appropriate documentation
*Configure an upload button, for example in the SideBarOptions
!Suppported Browser
*Firefox and Gecko based browser: tested Ok
*Internet Explorer : tested Ok
*Safari : tested ok on OS X
*Others : Not tested, please report status.

!Revision history
<<tiddler UploadPluginRevisionHistory>>
// null logger : no more UploadLog and no upload logging
// BidiX - 2006/11/8
//{{{
config.macros.upload.UploadLog = function() {return this;};
config.macros.upload.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {};
config.macros.upload.UploadLog.prototype.endUpload = function() {};
//}}}
UploadTiddlerPlugin and [[storeTiddler.php]] "upload" or "save to web" a single tiddler by updating, inserting or deleting a single tiddler in a TiddlyWiki file located on the web.

@@Now UploadTiddlerPlugin is able to Upload a Tiddler even if TiddlyWiki is located on a local file.@@

![[UploadTiddlerPlugin]]
*is activated by @@chkUploadTiddler option: <<option chkUploadTiddler>>@@
* to be abe to Upload a Tiddler even if the TiddlyWiki is located on local file@@chkUploadTiddlerFromFile option: <<option chkUploadTiddlerFromFile>>@@
*uses @@txtUploadTiddlerStoreUrl: <<option txtUploadTiddlerStoreUrl>>@@
*override TiddlyWiki.prototype.saveTiddler and deleteTiddler core functions
*uses the same options as UploadPlugin. 
*do an XmlHttpRequest POST to storeTiddler.php only with the corresponding tiddler in storeArea format.
![[storeTiddler.php]]
*Username and password are checked 
*[[storeTiddler.php]] parses TiddlyWiki file
*tiddler is updated, inserted or deleted in the tiddler array
*optionally create and clean backup file
*write updated TiddlyWiki file
!UploadTiddlerPlugin and UploadPlugin
*The paradigm of UploadTiddlerPlugin and [[storeTiddler.php]] is exactly the same as UploadPlugin and [[store.php]]
*No concurrency managed
*Full compatible with UploadPlugin
*[[storeTiddler.php]] can be use to remotly update a TiddlyWiki. storeTiddler.php
*a GET to [[storeTiddler.php]] display a form to upload a tiddler in a TiddlyWiki
/***
|''Name:''|UploadTiddlerMacro|
|''Description:''|Define a macro to upload a tiddler using UploadTiddlerPlugin (see UploadTiddlerPlugin for details).|
|''Version:''|1.0.0|
|''Date:''|2008-09-30|
|''Source:''|http://tiddlywiki.bidix.info/#UploadTiddlerMacro|
|''Usage:''|{{{<<uploadTiddler [tiddlerTitle]>>}}}<br>{{{tiddlerTitle: if omitted the title of the current tiddler}}}|
|''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:''|UploadTiddlerPlugin|
***/
//{{{
version.extensions.UploadTiddlerMacro = {
	major: 1, minor: 0, revision: 0, 
	date: new Date("2008-09-30"),
	source: 'http://tiddlywiki.bidix.info/#UploadTiddlerMacro',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

config.macros.uploadTiddler = {
	label: "uploadTiddler",
	prompt: "upload tiddler '%0' using UploadTiddlerOptions ",
	warning: "Are you sure you want to upload '%0'?",
	messages: {
		fileUploaded: "tiddler '%0' uploaded to file '%1'",
		fileNotUploaded: "tiddler '%0' NOT uploaded"
	},

	handler: function(place, macroName, params, wikifier,paramString, tiddler) {
		var tiddlerTitle = params[0];
		if (!tiddlerTitle) { 
			tiddlerTitle = tiddler.title;
		} else {
			tiddler = store.getTiddler(tiddlerTitle);
		}
		createTiddlyButton(place, this.label, this.prompt.format([tiddlerTitle]), 
			function () {
				config.macros.uploadTiddler.upload(tiddlerTitle, tiddler); 
				return false;}, 
			null, null, null);
	},

	upload:  function(tiddlerTitle, tiddler) {
		var saved_chkUploadTiddler = config.options.chkUploadTiddler;
		config.options.chkUploadTiddler = true; 
		bidix.uploadTiddler.upload(tiddlerTitle, tiddler,tiddlerTitle);
		config.options.chkUploadTiddler = saved_chkUploadTiddler;
	}
};

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

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

//
// Initializations
//

// require UploadTiddlerPlugin 1.2.2 or better
bidix.checkPlugin("UploadTiddlerPlugin", 1, 2, 2);


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

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

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

//
// Initializations
//

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

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

//optionsDesc
merge(config.optionsDesc,{
	txtUploadTiddlerStoreUrl: "Url of the UploadTiddlerService script (default: storeTiddler.php)",
	chkUploadTiddler: "Do per Tiddler upload using txtUploadTiddlerStoreUrl (default: false)",
	chkUploadTiddlerFromFile: "Upload tiddler even if TiddlyWiki is located on local file (default: false)"
});

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


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

//}}}

/***
|''Name:''|UploadToFileMacro|
|''Description:''|Upload a tiddler as a file using UploadPlugin context. Used with the SimonBaird's HideWhenPlugin ViewTemplate provides a new command in the tiddler toolbar.|
|''Version:''|2.0.1|
|''Date:''|Apr 21, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadToFileMacro|
|''Usage:''|{{{<<uploadTofile [filename [tiddlerTitle]]>>}}}<br>{{{tiddlerTitle, filename: if omitted the title of the current tiddler}}}|
|''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:''|UploadPlugin|
***/
//{{{
version.extensions.UploadToFileMacro = {
	major: 2, minor: 0, revision: 1, 
	date: new Date("Apr 21, 2007"),
	source: 'http://tiddlywiki.bidix.info/#UploadToFilePlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

// require UploadPlugin 4.0.0 or better
config.macros.uploadToFile = {
	label: "upload %0 to file %1",
	prompt: "upload tiddler '%0' to file '%1' ",
	warning: "Are you sure you want to upload '%0'?",
	messages: {
		fileUploaded: "tiddler '%0' uploaded to file '%1'",
		fileNotUploaded: "tiddler '%0' NOT uploaded"
	},

	handler: function(place, macroName, params, wikifier,paramString, tiddler) {
		// parameters initialization
		var toFilename = params[0];
		var tiddlerTitle = params[1];
		if (!tiddlerTitle) { 
			tiddlerTitle = tiddler.title;
		} else {
			tiddler = store.getTiddler(tiddlerTitle);
		}
		if (!toFilename) { 
			toFilename = tiddlerTitle;
		} 
		var prompt = this.prompt.format([tiddlerTitle, toFilename]);
		createTiddlyButton(place, this.label.format([params[1], params[0]]), this.prompt.format([tiddlerTitle, toFilename]), 
			function () {
				config.macros.uploadToFile.upload(tiddler, null, toFilename); 
				return false;}, 
			null, null, null);
	},

	upload:  function(tiddler, storeUrl, toFilename, uploadDir, backupDir, username, password) {
		if (!tiddler)	{
			alert("Tiddler not found.");
			return false;
		}
		var uploadIt = true; 
		if ((this.warning) && (!confirm(this.warning.format([tiddler.title])))) 
			return false;
		// parameters initialization
		storeUrl = (storeUrl ? storeUrl : config.options.txtUploadStoreUrl);
		toFilename = (toFilename ? toFilename : tiddler.title);
		backupDir = (backupDir ? backupDir : config.options.txtUploadBackupDir);
		uploadDir = (uploadDir ? uploadDir : config.options.txtUploadDir);
		username = (username ? username : config.options.txtUploadUserName);
		password = (password ? password :config.options.pasUploadPassword);
		var callback = function(status,params,responseText,url,xhr) {
			if (status) { 
				if (responseText.substring(0,1) == '0') {
					// 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:")));
					if (destfile.substring(0,2) == './') 
						destfile = destfile.substring(2);
					displayMessage(config.macros.uploadToFile.messages.fileUploaded.format([params[6],destfile]),
						bidix.dirname(url)+'/'+destfile);
				} else {
					alert(responseText);
					displayMessage(config.macros.uploadToFile.messages.fileNotUploaded.format([params[1]]));
				}
			} else {
				displayMessage("HTTP Error " + xhr.status + " in accessing " + url);
			}
		};
		var uploadParams = Array(storeUrl,toFilename,uploadDir,backupDir,username,password, tiddler.title);
		return bidix.upload.httpUpload(uploadParams,tiddler.text,callback,uploadParams);
		
	}
};

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"
	}
};

//
// Initializations
//

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

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

//
// Environment
//

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

//
// uploadUsing Macro
//

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

config.macros.uploadToHome.initAtLoad();

//}}}
    "Ends of properly 3-realizable groups" with F.F. Lasheras and A. Quintero.
    "Nerve Theorems for Locally Finite Complexes" with M. Ponce and A. Quintero.
    "A Dévissage Theorem for Waldhausen Categories."
    "Localization Sequences for Exact Categories: Deloop and Negative K-theory."
/***
|''Name:''|YourSearchPlugin|
|''Version:''|2.1.5 (2010-02-16)|
|''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-2010 [[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.5.js]] to get the readable source code.
***/
///%
if(!version.extensions.YourSearchPlugin){version.extensions.YourSearchPlugin={major:2,minor:1,revision:5,source:"http://tiddlywiki.abego-sof