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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

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

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser 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>>
Виктор Коленсников
взять жиру

Антон Богданов

Unit 7,13,14
ДЗ
18 60 
/***
|Name|AliasPlugin|
|Source|http://www.TiddlyTools.com/#AliasPlugin|
|Documentation|http://www.TiddlyTools.com/#AliasPluginInfo|
|Version|1.1.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|Create text-substitution macros|
Define macros for abbreviations and other "aliases", and then embed them in the rest of your tiddler content to quickly insert common terms, phrases and links without a lot of repetitive typing.
!!!!!Documentation
> see [[AliasPluginInfo]]
!!!!!Revisions
<<<
2009.09.09 1.1.1 'tiddler' arg passed to wikify() so aliases containing macros render with correct context
| Please see [[AliasPluginInfo]] for previous revision details |
2005.08.12 1.0.0 initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.AliasPlugin= {major: 1, minor: 1, revision: 1, date: new Date(2009,9,9)};
config.macros.alias= { };
config.macros.alias.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	var alias=params.shift(); if (!alias) return; alias=alias.replace(/ /g,"_"); // don't allow spaces in alias
	if (config.macros[alias]==undefined) { // create new macro (as needed)
		config.macros[alias] = { };
		config.macros[alias].handler =
			function (place,macroName,params,wikifier,paramString,tiddler)
				{ wikify(config.macros[macroName].text.format(params),place,null,tiddler); }
	}
	config.macros[alias].text = params[0]?params.join(' '):alias;	// set alias text
}
//}}}
/***
|Name|AliasPlugin|
|Source|http://www.TiddlyTools.com/#AliasPlugin|
|Documentation|http://www.TiddlyTools.com/#AliasPluginInfo|
|Version|1.1.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for AliasPlugin|
Define macros for abbreviations and other "aliases", and then embed them in the rest of your tiddler content to quickly insert common terms, phrases and links without a lot of repetitive typing.
!!!!!Usage
<<<
{{{
<<alias keyword "content to display">>
}}}
Select a short keyword or other abbreviated term that is easily input with just a few keystrokes.  When the {{{<<alias>>}}} macro is processed, it creates a new macro for you to embed in tiddler content, using the specified alias keyword as the name for that new macro.  You can choose any keyword you like, but don't include any spaces, as macro names must not contain spaces.

In order to ensure that your aliases are always defined and available for use, you should add your definitions to a tiddler that you are certain will be displayed when your TW is first loaded (e.g., [[MainMenu]]).  The {{{<<alias>>}}} macro itself won't actually produce any visible output, so it can be safely added to practically any tiddler without producing a change in that tiddler's appearance.

To use the aliases you have defined, simply invoke them as you would any other TiddlyWiki macro, e.g.,
{{{<<keyword>>}}}.  If you include parameters when you invoke the macro -- {{{<<keyword param param param...>>}}} -- they can be inserted direclty into the output by replacing corresponding substitution markers, indicated by using "%0" through "%9" in the "text to display" parameter used when the alias was defined.  For example, to define a quick alias for inserting a link to any given subject on www.wikipedia.com, you can write:
{{{
<<alias wikipedia "[[Wikipedia:%0|http://www.wikipedia.com/wiki/%0]]">>
}}}
which allows you to then write:
{{{
<<wikipedia TiddlyWiki>>
}}}
which is processed as if you wrote:
{{{
[[Wikipedia:TiddlyWiki|http://www.wikipedia.com/wiki/TiddlyWiki]]
}}}
and is displayed this way:
><<alias wikipedia "[[Wikipedia:%0|http://www.wikipedia.com/wiki/%0]]">><<wikipedia TiddlyWiki>>

Another interesting example uses the substitution markers to automatically display a reference to a TiddlerSlice value:
{{{
<<alias describe {{"|\<\<tiddler [[%0::Description]]\>\>|\n"}}>>
}}}
which allows you to then write:
{{{
<<describe AliasPlugin>>
}}}
which is processed as if you wrote:
{{{
|<<tiddler [[AliasPlugin::Description]]>>|
}}}
and is displayed this way:
<<alias describe {{"|\<\<tiddler [[%0::Description]]\>\>|\n"}}>><<describe AliasPlugin>>
<<<
!!!!!Revisions
<<<
2009.09.09 1.1.1 'tiddler' arg passed to wikify() so aliases containing macros render with correct context
2008.03.11 [*.*.*] plugin size reduction - documentation moved to [[AliasPluginInfo]]
2007.03.21 1.1.0 added support for parameter substitution into alias macros, using format() method and%0..%9 markers
2005.10.09 1.0.3 combined documentation and code into a single tiddler
2005.08.12 1.0.0 initial release
<<<
a simple macro button for creating custom-named backup files
!Planned Features
* custom timestamp format for backups
* an optional edit summary can be added to the filename
!Implementation
* based upon Eric's [[NewDocumentPlugin|http://www.tiddlytools.com/#NewDocumentPlugin]] and/or [[LessBackupsPlugin|http://lessbackupsplugin.tiddlyspot.com]]
* edit summary via a simple input box ({{{prompt()}}})
!!Issues
* potentially dangerous characters need to be excluded from the edit summary
/***
|''Name:''|BackupOptionsPlugin|
|''Version:''|1.0.3 (2011-02-23)|
|''Source:''|http://rumkin.com/tools/tiddlywiki/#BackupOptionsPlugin|
|''Author:''|Tyler Akins|
|''Licence:''|Public domain|
|''TiddlyWiki:''|2.0+|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|

!Description
Tired of having thousands of backups made due to saving every minor edit?  Do you only want one backup per hour, day, or just one backup ever?  Not a problem.

This plugin lets you define a file format that you want to use when saving backups.  Because backups will overwrite each other if they have the same name, you can now control how often new backup files are created.  If you want one created every day, just include the year, month, and day in your format and avoid using the hours, minutes, seconds, and milliseconds.  If you want only one backup, set a static name and it will just keep overwriting the old file.

!Configuration
Select what attributes you want to include in the backup filename in the order you like.  Dates are all in UTC format.  If the format field is left blank, it defaults to what the backups would normally be named:  {{{%N.%Y%M%D.%h%m%s%n.html}}}

{{wideInput{<<option txtBackupOptionsFormat 40>>}}}

|!Code|!Description|!Example|
| ''%D'' |Day of month, two digits| 18 |
| ''%h'' |Hour, two digits, 24 hour format| 21 |
| ''%M'' |Month number, two digits| 11 |
| ''%m'' |Minute, two digits| 59 |
| ''%N'' |Base name of the wiki| TiddlyWiki |
| ''%n'' |Millisecond, four digits| 8441 |
| ''%s'' |Seconds, two digits| 06 |
| ''%Y'' |Year, four digits| 2006 |
| ''%y'' |Year, two digits| 06 |
| ''%%'' |A percent symbol| % |

!Examples
Based on a base filename of "TiddlyWiki.html", and a date of 2006-11-18 21:59:06.8441, here are a few format options:

|!''Format''|!Description|
|!//Sample//|~|
| ''%N.bak'' |Saves only one backup, ever.  Always overwrites the .bak file with a new backup, keeping just one file around.|
| //TiddlyWiki.bak// |~|
| ''%N.%Y%M%D.%h%m%s%n.html'' |This is the default format that TiddlyWiki uses when making a new backup.|
| //TiddlyWiki.20061118.2159068441.html// |~|
| ''%N-%Y-%M-%D.html'' |Keep around only one backup per day.  When a new backup is made, it will overwrite any other backups made on that day.|
| //TiddlyWiki-2006-11-18.html// |~|
| ''Backups\%Y%M\%N-%D-%h%m.bak'' |Save all backups in a set of directories, with one directory that contains all, then another subdirectory that holds a year and month, and then the backup file.|
| //Backups\200611\TiddlyWiki-18-2159.bak// |~|
| ''%N-%(5).html'' |Saves up to the specified number (5 in this example) of backups in a rolling fashion.  Will start at 1 and proceed up to the maximum number set, then starts over with 1.  A great way to limit the total number of backsup.|
| //TiddlyWiki-1.html//, ..., //TiddlyWiki-5.html// |~|

!Revision history
* v1.0.3 (2011-02-23)
** Fixed %M format, thanks to John Antony
** Fixed version number and date
* v1.0.2 (2011-02-21)
** Addded %(5) format, courtesy of Jaufré Devosse
* v1.0.1 (?)
** Bugfixes to work with newer TiddlyWiki version
* v1.0.0 (2007-09-29)
** Initial release

!Code
***/
//{{{
//============================================================================
//                           BackupOptionsPlugin

// Ensure that the BackupOptionsPlugin is only installed once.
//

if (!version.extensions.BackupOptionsPlugin) {

setStylesheet(".wideInput input { width:30em; }","BackupOptionsStylesheet");

version.extensions.BackupOptionsPlugin = {
    major: 1, minor: 0, revision: 3,
    date: new Date(2011, 2, 23), 
    type: 'plugin',
    source: "http://rumkin.com/tools/tiddlywiki/#BackupOptionsPlugin"
};


if (!config.options.txtBackupOptionsFormat)
	config.options.txtBackupOptionsFormat = "%N.%Y%M%D.%h%m%s%n.html"; // Same as default format
if (!config.options.txtBackupCount)
	config.options.txtBackupCount = 1;  // Counter starts at 1
if (config.optionsDesc) {
	config.optionsDesc.txtBackupOptionsFormat = "Filename format for backups."
	config.optionsDesc.txtBackupCount = "Backup counter to generate filenames";
}

if (version.major < 2) alertAndThrow("BackupOptionsPlugin requires TiddlyWiki 2.0 or newer.");

//============================================================================
// Overwrite the built-in functions

getBackupPath = function(localPath) {
	var formatString = config.options['txtBackupOptionsFormat'];
	var counter = config.options.txtBackupCount;
	if (formatString == undefined || ! formatString || formatString == '')
		formatString = '%N.%Y%M%D.%h%m%s%n.html';
	var backSlash = true;
	var dirPathPos = localPath.lastIndexOf("\\");
	if (dirPathPos == -1)
	{
		dirPathPos = localPath.lastIndexOf("/");
		backSlash = false;
	}
	var backupFolder = config.options.txtBackupFolder;
	if (! backupFolder || backupFolder == '')
		backupFolder = '.';
	backupFolder += (backSlash ? "\\" : '/');
	var backupPath = localPath.substr(0, dirPathPos) + (backSlash ? "\\" : '/') + backupFolder;
	var backupBase = localPath.substr(dirPathPos)
	backupBase = backupBase.substr(0, backupBase.lastIndexOf('.'));
	var d = new Date()
	while (formatString.length > 0)
	{
		var formatHandled = 0;
		if (formatString.length > 1 && formatString.charAt(0) == '%')
		{
			formatHandled = 1;
			switch (formatString.charAt(1))
			{
				case 'D':
					backupPath += String.zeroPad(d.getUTCDate(), 2);
					break;
				case 'h':
					backupPath += String.zeroPad(d.getUTCHours(), 2);
					break;
				case 'M':
					backupPath += String.zeroPad(d.getUTCMonth() + 1, 2);
					break;
				case 'm':
					backupPath += String.zeroPad(d.getUTCMinutes(), 2);
					break;
				case 'N':
					backupPath += backupBase;
					break;
				case 'n':
					backupPath += String.zeroPad(d.getUTCMilliseconds(), 4);
					break;
				case 's':
					backupPath += String.zeroPad(d.getUTCSeconds(), 4);
					break;
				case 'Y':
					backupPath += String.zeroPad(d.getUTCFullYear(), 4);
					break;
				case 'y':
					backupPath += String.zeroPad(d.getUTCFullYear() % 100, 4);
					break;
				case '%':
					backupPath += '%';
					break;
				case '(':
					var result = formatString.match(/%\((\d+)\)/);
					if (result) {
						if (counter <= 0 || counter >= result[1]) {
							counter = 1;
						}
						backupPath += config.options.txtBackupCount;
						config.options.txtBackupCount = counter + 1;
						saveOption("txtBackupCount");
						formatString = formatString.substr(result[0].length - 2);  // -2 because of later substring
					} else {
						formatHandled = 0;
					}
					break;
				default:
					formatHandled = 0;
			}
			if (formatHandled) {
				formatString = formatString.substr(2);
			}
		}
		if (! formatHandled) {
			backupPath += formatString.charAt(0);
			formatString = formatString.substr(1);
		}
	}

	return backupPath;
}


} // of "install only once"
//}}}
/***

!Licence and Copyright
You are free to use this however you like.  I place this code into the public domain.
***/
#!/bin/sh
#number of seconds in a minute
sinm=60
#number of seconds in an hour
sinh=3600
#number of seconds in a day
sind=86400

#Calculate the date diff in seconds
startDate=`date -d "11 Jun 2010" +%s`
currentDate=`date +%s`
datediff=$(($startDate-$currentDate))

minutes=$(($datediff/$sinm))
echo "number of minutes to kick off $minutes"
hours=$(($datediff/$sinh))
echo "number of hours to kick off $hours"
days=$(($datediff/$sind))
echo "number of days to kick off $days"

#calulate end date and show in human readable format
endDate=$(($startDate+($sind*60)))
strEndDate=`awk 'BEGIN {print strftime("%Y-%m-%d",$endDate)}'`
echo "End date is $strEndDate"
http://www.cyberciti.biz/faq/bash-for-loop/
http://www.faqs.org/docs/abs/HTML/wrapper.html
http://www.perlmonks.org/?node_id=46168

/***
|''Name''|BlockCollapseMacro|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#BlockCollapseMacro]]|
|''Version''|0.3|
|''Author''|FND|
|''License''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|macro for collapsing/expanding block elements' height on click|
!Usage Notes
* two options:
** add {{{<<blockCollapse [class] [tag]>>}}} to the desired tiddler(s)
** add as a macro to ViewTemplate: {{{<span macro='blockCollapse [class] [tag]'></span>}}}
!!Example
{{{<<blockCollapse "footer" "h1">>}}} <<blockCollapse "footer" "h1">> /% DEBUG: not working here %/
!Revision History
!!v0.3 (2007-08-17)
* adapted from [[TableHighlightMacro|http://devpad.tiddlyspot.com/#TableHighlightMacro]]
!To Do
* rename plugin => also rename dependencies (macro name, default class and style sheet)
* fix/remove DEBUG flags
* adjust Description and Usage Notes
!Code
***/
//{{{
config.macros.blockCollapse = {}
config.macros.blockCollapse.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	// process parameters
	var collapseClass = (params[0] && params[0] != "") ? params[0] : "blockCollapse";
	var targetElement = (params[1] && params[1] != "") ? params[1] : "pre";
	// toggle collapsing
	var els = story.findContainingTiddler(place).getElementsByTagName(targetElement);
	for(var i = 0; i < els.length; i++) {
		els[i].onclick = function() {
			config.macros.blockCollapse.toggleCollapse(this, collapseClass);
		};
	}
}

config.macros.blockCollapse.toggleCollapse = function(el, customClass) {
	if(!hasClass(el, customClass)) {
		addClass(el, customClass);
		//el.style.height = "1em !important"; // DEBUG
		//el.style.border = "10px dashed #F00 !important"; // DEBUG 
	} else {
		removeClass(el, customClass);
		//el.style.height = ""; // DEBUG
		//el.style.border = ""; // DEBUG
	}
}

// set default styles
setStylesheet(".blockCollapse { "
	+ "height: 1em !important; "
	+ "border: 10px dashed #0F0 !important; " // DEBUG
	+ "overflow: hidden !important; " // DEBUG
	+ "}",
	"StyleSheetBlockCollapse");
//}}}
!Decriptions of Params
|!Params |%0|%1|%2|%3|%4|%5|
|!Descriptions|title|url|selections|descriptions|rererence|tags|
!Lingos of command button
{{{
''text:'' Bookmarks
''tooltip:'' Bookmark this tiddlers to ...
''popupNone:'' There are no bookmark services
}}}
!List of Services
{{{
''Services:'' Del.icio.us,Digg,Google,Yahoo,Furl,HemiDemi,MyShare,Baidu,Youpus,Technorati
}}}
!Definition of Services
{{{
''HemiDemi:''<br/>[[HemiDemi|http://www.hemidemi.com/user_bookmark/new?title=%0&url=%1&quotes=%2&description=%3&via=%4&tag_string=%5]]
''MyShare:''<br/>[[MyShare|http://myshare.url.com.tw/index.php?func=newurl&from=mysharepop&url=%1&desc=%0&contents=%3]]
''Baidu:''<br/>[[Baidu|http://cang.baidu.com/do/add?iu=%1&it=%0&dc=%3]]
''Google:''<br/>[[Google|http://www.google.com/bookmarks/mark?op=add&title=%0&bkmk=%1&annotation=%3&labels=%5]]
''Yahoo:''<br/>[[Yahoo|http://tw.myweb2.search.yahoo.com/myresults/bookmarklet?t=%1&u=%0&d=%3&ei=UTF-8]]
''Del.icio.us:''<br/>[[Del.icio.us|http://del.icio.us/post?title=%0&url=%1&notes=%3&tags=%5]]
''Digg:''<br/>[[Digg|http://digg.com/submit?phase=2&url=%0&title=%1&bodytext=%3]]
''Technorati:''<br/>[[Technorati|http://technorati.com/faves?add=%1&title=%0]]
''Furl:''<br/>[[Furl|http://www.furl.net/storeIt.jsp?t=%0&u=%1&r=%4&c=%2&p=1]]
''Youpush:''<br/>[[Youpush|http://www.youpush.net/submit.php?url=%1]]
}}}
/***
|''Name''|ButtonMemoryMacro|
|''Version''|0.2|
|''Status''|@@experimental@@|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#ButtonMemoryMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|creates a list of buttons and remembers the order they were clicked in|
!Usage
{{{
<<btnmem "[button 1 label];[button 2 label];[button 3 label] ...">>
}}}
!!Example
<<btnmem "foo;bar;baz">>
!Revision History
!!v0.1 (2007-12-20)
* initial release
!!v0.2 (2007-12-21)
* added configuration options
* changed parameter processing
* selection buttons now update output
!To Do
* rename
* named macro parameters for config items
* code sanitzing
* documentation
* allow for more than one instance at a time (due to global selection array and output container)
!Code
***/
//{{{
config.macros.btnmem = {
	resetLabel: "reset",
	submitLabel: "submit",
	itemSeparator: ";",
	itemPrefix: "* ",
	itemSuffix: "\n",
	outputID: "btnMemOutput",
	itemButtonClass: "button btnMemItemBtn",
	functionButtonClass: "button btnMemFunctionBtn",
	selectionBoxClass: "btnMemSelectionBox",
	functionBoxClass: "btnMemFunctionBox",
	selection: []
};

config.macros.btnmem.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	// create selection buttons
	if(params[0]) var items = params[0].split(this.itemSeparator);
	var e = createTiddlyElement(place, "div", null, this.selectionBoxClass);
	for(var i = 0; i < items.length; i++) {
		createTiddlyButton(e, items[i], null,
			function() { config.macros.btnmem.extendSelection(this.firstChild.nodeValue); },
			this.itemButtonClass);
	}
	// create function buttons
	e = createTiddlyElement(place, "div", null, this.functionBoxClass);
	createTiddlyButton(e, this.resetLabel, null,
		function() { config.macros.btnmem.resetResults(); },
		this.functionButtonClass);
	createTiddlyButton(e, this.submitLabel, null,
		function() { config.macros.btnmem.submitResults(); },
		this.functionButtonClass);
	// create output container -- DEBUG: reuse place instead!?
	config.macros.btnmem.output = createTiddlyElement(place, "div", this.outputID);
}

config.macros.btnmem.extendSelection = function(str) {
	this.selection.push(str);
	var output = "";
	var e = document.getElementById(this.outputID);
	if(e) {
		e.innerHTML = "";
		for(var i = 0; i < this.selection.length; i++) {
			output += this.itemPrefix + this.selection[i] + this.itemSuffix;
		}
		wikify(output.trim(), e);
	}
}

config.macros.btnmem.resetResults = function() {
	this.selection = [];
	var e = document.getElementById(this.outputID);
	if(e) e.innerHTML = "";
}

config.macros.btnmem.submitResults = function() {
	var output = config.macros.btnmem.selection;
	this.resetResults();
	var e = document.getElementById(this.outputID);
	if(e) wikify("submitting selection:\n" + output.join(), e);
}
//}}}
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|Add checkboxes to your tiddler content|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content.  Checkbox states are preserved by:
* by setting/removing tags on specified tiddlers,
* or, by setting custom field values on specified tiddlers,
* or, by saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler content (deprecated)
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data.  In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Documentation
>see [[CheckboxPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global "window.place" to current checkbox element when processing checkbox clicks.  This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)".  Also, wrap handlers in "function()" so "return" can be used within handler code.
|please see [[CheckboxPluginInfo]] for additional revision details|
2005.12.07 [0.9.0] initial BETA release
<<<
!!!!!Code
***/
//{{{
version.extensions.CheckboxPlugin = {major: 2, minor: 4, revision:0 , date: new Date(2008,1,5)};
//}}}
//{{{
config.checkbox = { refresh: { tagged:true, tagging:true, container:true } };
config.formatters.push( {
	name: "checkbox",
	match: "\\[[xX_ ][\\]\\=\\(\\{]",
	lookahead: "\\[([xX_ ])(=[^\\s\\(\\]{]+)?(\\([^\\)]*\\))?({[^}]*})?({[^}]*})?({[^}]*})?\\]",
	handler: function(w) {
		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
		lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			// get params
			var checked=(lookaheadMatch[1].toUpperCase()=="X");
			var id=lookaheadMatch[2];
			var target=lookaheadMatch[3];
			if (target) target=target.substr(1,target.length-2).trim(); // trim off parentheses
			var fn_init=lookaheadMatch[4];
			var fn_clickBefore=lookaheadMatch[5];
			var fn_clickAfter=lookaheadMatch[6];
			var tid=story.findContainingTiddler(w.output);  if (tid) tid=tid.getAttribute("tiddler");
			var srctid=w.tiddler?w.tiddler.title:null;
			config.macros.checkbox.create(w.output,tid,srctid,w.matchStart+1,checked,id,target,config.checkbox.refresh,fn_init,fn_clickBefore,fn_clickAfter);
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
		}
	}
} );
config.macros.checkbox = {
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!(tiddler instanceof Tiddler)) { // if no tiddler passed in try to find one
			var here=story.findContainingTiddler(place);
			if (here) tiddler=store.getTiddler(here.getAttribute("tiddler"))
		}
		var srcpos=0; // "inline X" not applicable to macro syntax
		var target=params.shift(); if (!target) target="";
		var defaultState=params[0]=="checked"; if (defaultState) params.shift();
		var id=params.shift(); if (id && !id.length) id=null;
		var fn_init=params.shift(); if (fn_init && !fn_init.length) fn_init=null;
		var fn_clickBefore=params.shift();
		if (fn_clickBefore && !fn_clickBefore.length) fn_clickBefore=null;
		var fn_clickAfter=params.shift();
		if (fn_clickAfter && !fn_clickAfter.length) fn_clickAfter=null;
		var refresh={ tagged:true, tagging:true, container:false };
		this.create(place,tiddler.title,tiddler.title,0,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter);
	},
	create: function(place,tid,srctid,srcpos,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter) {
		// create checkbox element
		var c = document.createElement("input");
		c.setAttribute("type","checkbox");
		c.onclick=this.onClickCheckbox;
		c.srctid=srctid; // remember source tiddler
		c.srcpos=srcpos; // remember location of "X"
		c.container=tid; // containing tiddler (may be null if not in a tiddler)
		c.tiddler=tid; // default target tiddler 
		c.refresh = {};
		c.refresh.container = refresh.container;
		c.refresh.tagged = refresh.tagged;
		c.refresh.tagging = refresh.tagging;
		place.appendChild(c);
		// set default state
		c.checked=defaultState;
		// track state in config.options.ID
		if (id) {
			c.id=id.substr(1); // trim off leading "="
			if (config.options[c.id]!=undefined)
				c.checked=config.options[c.id];
			else
				config.options[c.id]=c.checked;
		}
		// track state in (tiddlername|tagname) or (fieldname@tiddlername)
		if (target) {
			var pos=target.indexOf("@");
			if (pos!=-1) {
				c.field=pos?target.substr(0,pos):"checked"; // get fieldname (or use default "checked")
				c.tiddler=target.substr(pos+1); // get specified tiddler name (if any)
				if (!c.tiddler || !c.tiddler.length) c.tiddler=tid; // if tiddler not specified, default == container
				if (store.getValue(c.tiddler,c.field)!=undefined)
					c.checked=(store.getValue(c.tiddler,c.field)=="true"); // set checkbox from saved state
			} else {
				var pos=target.indexOf("|"); if (pos==-1) var pos=target.indexOf(":");
				c.tag=target;
				if (pos==0) c.tag=target.substr(1); // trim leading "|" or ":"
				if (pos>0) { c.tiddler=target.substr(0,pos); c.tag=target.substr(pos+1); }
				if (!c.tag.length) c.tag="checked";
				var t=store.getTiddler(c.tiddler);
				if (t && t.tags)
					c.checked=t.isTagged(c.tag); // set checkbox from saved state
			}
		}
		// trim off surrounding { and } delimiters from init/click handlers
		if (fn_init) c.fn_init="(function(){"+fn_init.trim().substr(1,fn_init.length-2)+"})()";
		if (fn_clickBefore) c.fn_clickBefore="(function(){"+fn_clickBefore.trim().substr(1,fn_clickBefore.length-2)+"})()";
		if (fn_clickAfter) c.fn_clickAfter="(function(){"+fn_clickAfter.trim().substr(1,fn_clickAfter.length-2)+"})()";
		c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie
	},
	onClickCheckbox: function(event) {
		window.place=this;
		if (this.init && this.fn_init) // custom function hook to set initial state (run only once)
			{ try { eval(this.fn_init); } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }
		if (!this.init && this.fn_clickBefore) // custom function hook to override changes in checkbox state
			{ try { eval(this.fn_clickBefore) } catch(e) { displayMessage("Checkbox onClickBefore error: "+e.toString()); } }
		if (this.id)
			// save state in config AND cookie (only when ID starts with 'chk')
			{ config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }
		if (this.srctid && this.srcpos>0 && (!this.id || this.id.substr(0,3)!="chk") && !this.tag && !this.field) {
			// save state in tiddler content only if not using cookie, tag or field tracking
			var t=store.getTiddler(this.srctid); // put X in original source tiddler (if any)
			if (t && this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed
				t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);
				if (!story.isDirty(t.title)) story.refreshTiddler(t.title,null,true);
				store.setDirty(true);
			}
		}
		if (this.field) {
			if (this.checked && !store.tiddlerExists(this.tiddler))
				store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
			// set the field value in the target tiddler
			store.setValue(this.tiddler,this.field,this.checked?"true":"false");
			// DEBUG: displayMessage(this.field+"@"+this.tiddler+" is "+this.checked);
		}
		if (this.tag) {
			if (this.checked && !store.tiddlerExists(this.tiddler))
				store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
			var t=store.getTiddler(this.tiddler);
			if (t) {
				var tagged=(t.tags && t.tags.indexOf(this.tag)!=-1);
				if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }
				if (!this.checked && tagged) { t.tags.splice(t.tags.indexOf(this.tag),1); store.setDirty(true); }
			}
			// if tag state has been changed, update display of corresponding tiddlers (unless they are in edit mode...)
			if (this.checked!=tagged) {
				if (this.refresh.tagged) {
					if (!story.isDirty(this.tiddler)) // the TAGGED tiddler in view mode
						story.refreshTiddler(this.tiddler,null,true); 
					else // the TAGGED tiddler in edit mode (with tags field)
						config.macros.checkbox.refreshEditorTagField(this.tiddler,this.tag,this.checked);
				}
				if (this.refresh.tagging)
					if (!story.isDirty(this.tag)) story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler
			}
		}
		if (!this.init && this.fn_clickAfter) // custom function hook to react to changes in checkbox state
			{ try { eval(this.fn_clickAfter) } catch(e) { displayMessage("Checkbox onClickAfter error: "+e.toString()); } }
		// refresh containing tiddler (but not during initial rendering, or we get an infinite loop!) (and not when editing container)
		if (!this.init && this.refresh.container && this.container!=this.tiddler)
			if (!story.isDirty(this.container)) story.refreshTiddler(this.container,null,true); // the tiddler CONTAINING the checkbox
		return true;
	},
	refreshEditorTagField: function(title,tag,set) {
		var tagfield=story.getTiddlerField(title,"tags");
		if (!tagfield||tagfield.getAttribute("edit")!="tags") return; // if no tags field in editor (i.e., custom template)
		var tags=tagfield.value.readBracketedList();
		if (tags.contains(tag)==set) return; // if no change needed
		if (set) tags.push(tag); // add tag
		else tags.splice(tags.indexOf(tag),1); // remove tag
		for (var t=0;t<tags.length;t++) tags[t]=String.encodeTiddlyLink(tags[t]);
		tagfield.value=tags.join(" "); // reassemble tag string (with brackets as needed)
		return;
	}
}
//}}}
|Name|CheckboxPluginInfo|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for CheckboxPlugin|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content.  Checkbox states are preserved by:
* setting/removing tags on specified tiddlers,
* or, setting custom field values on specified tiddlers,
* or, saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler source content (deprecated).
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data.  In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Inline (wiki syntax) Usage
<<<
//{{{
[ ]or[_] and [x]or[X]
//}}}
Simple checkboxes using 'Inline X' storage.  The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked).  When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets.
>//''NOTE: 'Inline X' syntax has been deprecated...''  This storage format only works properly for checkboxes that are directly embedded and accessed from content in a single tiddler.  However, if that tiddler is 'transcluded' into another (by using the {{{<<tiddler TiddlerName>>}}} macro), the 'Inline X' will be ''erroneously stored in the containing tiddler's source content, resulting in corrupted content in that tiddler.''  For anything but the most simple of "to do list" uses, you should select from the various alternative storage methods described below...//
//{{{
[x=id]
//}}}
Assign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}.  If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value).  If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.
//{{{
[x(title|tag)] or [x(title:tag)]
//}}}
Initializes and tracks the current checkbox state by setting or removing a particular tag value from a specified tiddler.  If you omit the tiddler title (and the | or : separator), the specified tag is assigned to the current tiddler.  If you omit the tag value, as in {{{(title|)}}}, the default tag, {{{checked}}}, is assumed.  Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler.  When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state.  If a tiddler title named in the tag does not exist, the checkbox state defaults to the "inline X" value.  If this value is //checked//, or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the tag to it.  //''NOTE: beginning with version 2.1.2 of this plugin, the "|" separator is the preferred separator between the title and tag name, as it avoids syntactic ambiguity when ":" is used within tiddler titles or tag names.''//
//{{{
[x(field@tiddler)]
//}}}
Initializes and tracks the current checkbox state by setting a particular custom field value from a specified tiddler.  If you omit the tiddler title (but not the "@" separator), the specified field on the current tiddler is used.  If you omit the field name, as in {{{(@tiddler)}}}, a default fieldname of {{{checked}}} is assumed.  Omitting both the field and the tiddler title, {{{(@)}}}, defaults to setting the "checked" field on the current tiddler.  When field tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state.  If the tiddler title named in the parameter does not exist, the checkbox state defaults to the "inline X" value.  If this value is //checked// or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the field to it.
//{{{
[x{javascript}{javascript}{javascript}]
//}}}
You can define optional javascript code segments to add custom initialization and/or 'onClick' handlers to a checkbox.  The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to a globally-defined context object, "place" (which can also be referenced as "window.place").

The first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state.  The second code segment (if present) is executed whenever the checkbox is clicked, but //before the regular checkbox processing in performed// ("onClickBefore"), so that you can apply programmed responses or intercept and override the checkbox state based on custom logic.  The third code segment (if present) is executed whenver the checkbox is clicked, //after the regular checkbox processing has completed// ("onClickAfter"), so that you can include "side-effect" processing based on the checkbox state just applied.

>Note: if you want to use the default checkbox initialization processing with a custom onClickBefore/After function, use this syntax:
>{{{[x(tag){}{javascript}]}}} or {{{[x(tag){}{}{javascript}]}}}
<<<
!!!!!Macro usage
<<<
In addition to embedded checkboxes using the wiki syntax described above, a ''macro-based syntax'' is also provided, for use in templates where wiki syntax cannot be directly used.  This macro syntax can also be used in tiddler content, as an alternative to the wiki syntax.  When embedded in [[PageTemplate]], [[ViewTemplate]], or [[EditTemplate]] (or custom alternative templates), use the following macro syntax:
//{{{
<span macro="checkbox target checked id onInit onClickBefore onClickAfter"></span>
//}}}
or, when embedded in tiddler content, use the following macro syntax:
//{{{
<<checkbox target checked id onInit onClickBefore onClickAfter>>
//}}}
where:
''target''
>is either a tag reference (e.g., ''tagname|tiddlername'') or a field reference (e.g. ''fieldname@tiddlername''), as described above.
''checked'' (optional)
>is a keyword that sets the initial state of the checkbox to "checked".  When omitted, the default checkbox state is "unchecked".
''id'' (optional)
>specifies an internal config.options.* ID, as described above.  If the ID begins with "chk", a cookie-based persistent value will be created to track the checkbox state in between sessions.
''onInit'' (optional)
>contains a javascript event handler to be performed when the checkbox is initially rendered (see details above).
''onClickBefore'' and/or ''onClickAfter'' (optional)
>contains a javascript event handler to be performed each time the checkbox is clicked (see details above).  //note: to use the default onInit handler with a custom onClickBefore/After handler, use "" (empty quotes) or {} (empty function) as a placeholder for the onInit and/or onClickBefore parameters//
<<<
!!!!!Examples
<<<
''checked and unchecked static default ("inline X") values:''
//{{{
[X] label
[_] label
//}}}
>[X] label
>[_] label
''document-based value (id='demo', no cookie):''
//{{{
[_=demo] label
//}}}
>[_=demo] label
''cookie-based value  (id='chkDemo'):''





//{{{
[_=chkDemo] label
//}}}
>[_=chkDemo] label
''tag-based value (TogglyTagging):''
//{{{
[_(CheckboxPluginInfo|demotag)]
[_(CheckboxPluginInfo|demotag){place.refresh.tagged=place.refresh.container=false}]
//}}}
>[_(CheckboxPluginInfo|demotag)] toggle 'demotag' (and refresh tiddler display)
>[_(CheckboxPluginInfo|demotag){place.refresh.tagged=place.refresh.container=false}] toggle 'demotag' (no refresh)
''field-based values:''
//{{{
[_(demofield@CheckboxPluginInfo)] demofield@CheckboxPluginInfo
[_(demofield@)] demofield@ (equivalent to demonfield@ current tiddler)
[_(checked@CheckboxPluginInfo)] checked@CheckboxPluginInfo
[_(@CheckboxPluginInfo)] @CheckboxPluginInfo
[_(@)] @ (equivalent to checked@ current tiddler)
//}}}
>[_(demofield@CheckboxPluginInfo)] demofield@CheckboxPluginInfo
>[_(demofield@)] demofield@ (current tiddler)
>[_(checked@CheckboxPluginInfo)] checked@CheckboxPluginInfo
>[_(@CheckboxPluginInfo)] @CheckboxPluginInfo
>[_(@)] toggle field: @ (defaults to "checked@here")
>click to view current: <<toolbar fields>>
''custom init and onClick functions:''
//{{{
[X{place.checked=true}{alert(place.checked?"on":"off")}] message box with checkbox state
//}}}
>[X{place.checked=true}{alert(place.checked?"on":"off")}] message box with checkbox state
''retrieving option values:''
>config.options['demo']=<script>return config.options['demo']?"true":"false";</script>
>config.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>
<<<
!!!!!Configuration
<<<
Normally, when a checkbox state is changed, the affected tiddlers are automatically re-rendered, so that any checkbox-dependent dynamic content can be updated.  There are three possible tiddlers to be re-rendered, depending upon where the checkbox is placed, and what kind of storage method it is using.
*''container'': the tiddler in which the checkbox is displayed. (e.g., this tiddler)
*''tagged'': the tiddler that is being tagged (e.g., "~MyTask" when tagging "~MyTask:done")
*''tagging'': the "tag tiddler" (e.g., "~done" when tagging "~MyTask:done")
You can set the default refresh handling for all checkboxes in your document by using the following javascript syntax either in a systemConfig plugin, or as an inline script.  (Substitute true/false values as desired):
{{{config.checkbox.refresh = { tagged:true, tagging:true, container:true };}}}

You can also override these defaults for any given checkbox by using an initialization function to set one or more of the refresh options.  For example:
{{{[_{place.refresh.container=false}]}}}
<<<
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 2.4.0 set global "window.place" to current checkbox element when processing checkbox clicks.  This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)".  Also, wrap handlers in "function()" so "return" can be used within handler code.
2008.01.02 2.3.0 split optional custom onClick handling into separate onClickBefore and onClickAfter handlers.  The onClickBefore handler permits interception of the click BEFORE the checkbox is set.  onClickAfter allows follow-on 'side-effect' processing to occur AFTER the checkbox is set.
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.08.06 2.2.5 supress automatic refresh of any tiddler that is currently being edited.  Ensures that current tiddler edit sessions are not prematurely discarded (losing any changes).  However, if checkbox changes a tag on a tiddler being edited, update the "tags" input field (if any) so that saving the edited tiddler correctly reflects any changes due to checkbox activity... see refreshEditorTagField().
2007.07.13 - 2.2.4 in handler(), fix srctid reference (was "w.tiddler", should have been "w.tiddler.title").  This fixes broken 'inline X' plus fatal macro error when using PartTiddlerPlugin.  Thanks to cmari for reporting the problem and UdoBorkowski for finding the code error.
2007.06.21 - 2.2.3 suppress automatic refresh of tiddler when using macro-syntax to prevent premature end of tiddler editing session.
2007.06.20 - 2.2.2 fixed handling for 'inline X' when checkboxes are contained in a 'trancluded' tiddler.  Now, regardless of where an inline X checkbox appears, the X will be placed in the originating source tiddler, rather than the tiddler in which the checkbox appears.
2007.06.17 - 2.2.1 Refactored code to add checkbox //macro// syntax for use in templates (e.g., {{{macro="checkbox ..."}}}. Also, code cleanup of existing tag handling.
2007.06.16 - 2.2.0 added support for tracking checkbox states using tiddler fields via "(fieldname@tiddlername)" syntax.
2006.05.04 - 2.1.3 fix use of findContainingTiddler() to check for a non-null return value, so that checkboxes won't crash when used outside of tiddler display context (such as in header, sidebar or mainmenu)
2006.03.11 - 2.1.2 added "|" as delimiter to tag-based storage syntax (e.g. "tiddler|tag") to avoid parsing ambiguity when tiddler titles or tag names contain ":".   Using ":" as a delimiter is still supported but is deprecated in favor of the new "|" usage.  Based on a problem reported by JeffMason.
2006.02.25 - 2.1.0 added configuration options to enable/disable forced refresh of tiddlers when toggling tags
2006.02.23 - 2.0.4 when toggling tags, force refresh of the tiddler containing the checkbox.
2006.02.23 - 2.0.3 when toggling tags, force refresh of the 'tagged tiddler' so that tag-related tiddler content (such as "to-do" lists) can be re-rendered.
2006.02.23 - 2.0.2 when using tag-based storage, allow use [[ and ]] to quote tiddler or tag names that contain spaces:
{{{[x([[Tiddler with spaces]]:[[tag with spaces]])]}}}
2006.01.10 - 2.0.1 when toggling tags, force refresh of the 'tagging tiddler'.  For example, if you toggle the "systemConfig" tag on a plugin, the corresponding "systemConfig" TIDDLER will be automatically refreshed (if currently displayed), so that the 'tagged' list in that tiddler will remain up-to-date.
2006.01.04 - 2.0.0 update for ~TW2.0
2005.12.27 - 1.1.2 Fix lookAhead regExp handling for {{{[x=id]}}}, which had been including the "]" in the extracted ID.  
Added check for "chk" prefix on ID before calling saveOptionCookie()
2005.12.26 - 1.1.2 Corrected use of toUpperCase() in tiddler re-write code when comparing {{{[X]}}} in tiddler content with checkbox state. Fixes a problem where simple checkboxes could be set, but never cleared.
2005.12.26 - 1.1.0 Revise syntax so all optional parameters are included INSIDE the [ and ] brackets.  Backward compatibility with older syntax is supported, so content changes are not required when upgrading to the current version of this plugin.   Based on a suggestion by GeoffSlocock
2005.12.25 - 1.0.0 added support for tracking checkbox state using tags ("TogglyTagging")
Revised version number for official post-beta release.
2005.12.08 - 0.9.3 support separate 'init' and 'onclick' function definitions.
2005.12.08 - 0.9.2 clean up lookahead pattern
2005.12.07 - 0.9.1 only update tiddler source content if checkbox state is actually different.  Eliminates unnecessary tiddler changes (and 'unsaved changes' warnings)
2005.12.07 - 0.9.0 initial BETA release
<<<
/***
|Name:|CloseOnCancelPlugin|
|Description:|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open|
|Version:|3.0.1a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#CloseOnCancelPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.commands.cancelTiddler,{

  handler_mptw_orig_closeUnsaved: config.commands.cancelTiddler.handler,

  handler: function(event,src,title) {
    this.handler_mptw_orig_closeUnsaved(event,src,title);
    if (!story.isDirty(title) && !store.tiddlerExists(title) && !store.isShadowTiddler(title))
      story.closeTiddler(title,true);
    return false;
  }

});

//}}}
/***
|Name|CollapseTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#CollapseTiddlersPlugin|
|Version|2.0.0|
|Author|Eric Shulman|
|OriginalAuthor|Bradley Meck - http://gensoft.revhost.net/Collapse.html|
|License|unknown|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|CollapsedTemplate|
|Description|show/hide content of a tiddler while leaving tiddler title visible|
This plugin provides commands to quickly switch a rendered tiddler between its current ViewTemplate display and a minimal display (title and toolbar) defined by a separate CollapsedTemplate.
!!!Usage
<<<
In [[ToolbarCommands::ViewToolbar|ToolbarCommands]], add:
{{{
collapseTiddler collapseOthers
}}}
you can also embed the following macros in tiddler content:
*{{{<<collapseAll>>}}} - adds 'collapse all' command that applies CollapsedTemplate to each displayed tiddler
*{{{<<expandAll>>}}} - adds 'expand all' command that re-applies ViewTemplate (or equivalent custom template) to each displayed tiddler
*{{{<<foldFirst>>}}} - immediately apply CollapsedTemplate to a given tiddler, as soon as it is displayed.
<<<
!!!Revisions
<<<
2009.05.04 [2.0.0] standardized documentation and added version #
2008.10.05 collapseAll() and expandAll(): added "return false" to button handlers to prevent IE page transition
2008.03.06 refactored all code for size reduction, readability, and I18N/L10N-readiness.  Also added 'folded' flag to tiddler elements (for use by other plugins that need to know if tiddler is folded (e.g., [[SinglePageModePlugin]]
2007.10.11 moved [[FoldFirst]] inline script and converted to {{{<<foldFirst>>}}} macro
2007.12.09 suspend/resume SinglePageMode (SPM/TPM/BPM) when folding/unfolding tiddlers
2007.05.06 add "return false" at the end of each command handler to prevent IE 'page transition' problem.
2007.03.30 add a shadow definition for CollapsedTemplate.  Tweak ViewTemplate shadow so "fold/unfold" and "focus" toolbar items automatically appear when using default templates.  Remove error check for "CollapsedTemplate" existence, since shadow version will now always work as a fallback.
2006.02.24 added fallback to "CollapsedTemplate" if "WebCollapsedTemplate" is not found
2006.02.06 added check for 'readOnly' flag to use alternative "WebCollapsedTemplate"
<<<
!!!Code
***/
//{{{
version.extensions.CollapseTiddlersPlugin= {major: 2, minor: 0, revision: 0, date: new Date(2009,5,4)};

config.shadowTiddlers.CollapsedTemplate=
	"<!--{{{-->\
	<div class='toolbar' macro='toolbar expandTiddler collapseOthers closeTiddler closeOthers +editTiddler permalink references jump'></div>\
	<div class='title' macro='view title'></div>\
	<!--}}}-->";

// automatically tweak shadow ViewTemplate to add "collapseTiddler collapseOthers" commands
config.shadowTiddlers.ViewTemplate=config.shadowTiddlers.ViewTemplate.replace(/closeTiddler/,"collapseTiddler collapseOthers closeTiddler");

config.commands.collapseTiddler = {
	text: "fold",
	tooltip: "Collapse this tiddler",
	collapsedTemplate: "CollapsedTemplate",
	webCollapsedTemplate: "WebCollapsedTemplate",
	handler: function(event,src,title) {
		var e = story.findContainingTiddler(src); if (!e) return false;
		// don't fold tiddlers that are being edited!
		if(story.isDirty(e.getAttribute("tiddler"))) return false;
		var t=config.commands.collapseTiddler.getCollapsedTemplate();
		config.commands.collapseTiddler.saveTemplate(e);
		config.commands.collapseTiddler.display(title,t);
		e.setAttribute("folded","true");
		return false;
	},
	getCollapsedTemplate: function() {
		if (readOnly&&store.tiddlerExists(this.webCollapsedTemplate))
			return this.webCollapsedTemplate;
		else
			return this.collapsedTemplate
	},
	saveTemplate: function(e) {
		if (e.getAttribute("savedTemplate")==undefined)
			e.setAttribute("savedTemplate",e.getAttribute("template"));

	},
	// fold/unfold tiddler with suspend/resume of single/top/bottom-of-page mode
	display: function(title,t) {
		var opt=config.options;
		var saveSPM=opt.chkSinglePageMode; opt.chkSinglePageMode=false;
		var saveTPM=opt.chkTopOfPageMode; opt.chkTopOfPageMode=false;
		var saveBPM=opt.chkBottomOfPageMode; opt.chkBottomOfPageMode=false;
		story.displayTiddler(null,title,t);
		opt.chkBottomOfPageMode=saveBPM;
		opt.chkTopOfPageMode=saveTPM;
		opt.chkSinglePageMode=saveSPM;
	}
}

config.commands.expandTiddler = {
	text: "unfold",
	tooltip: "Expand this tiddler",
	handler: function(event,src,title) {
		var e = story.findContainingTiddler(src); if (!e) return false;
		var t = e.getAttribute("savedTemplate");
		config.commands.collapseTiddler.display(title,t);
		e.setAttribute("folded","false");
		return false;
	}
}

config.macros.collapseAll = {
	text: "collapse all",
	tooltip: "Collapse all tiddlers",
	handler: function(place,macroName,params,wikifier,paramString,tiddler){
		createTiddlyButton(place,this.text,this.tooltip,function(){
			story.forEachTiddler(function(title,tiddler){
				if(story.isDirty(title)) return;
				var t=config.commands.collapseTiddler.getCollapsedTemplate();


				config.commands.collapseTiddler.saveTemplate(tiddler);
				config.commands.collapseTiddler.display(title,t);
				tiddler.folded=true;
			});
			return false;
		})
	}
}

config.macros.expandAll = {
	text: "expand all",
	tooltip: "Expand all tiddlers",
	handler: function(place,macroName,params,wikifier,paramString,tiddler){
		createTiddlyButton(place,this.text,this.tooltip,function(){
			story.forEachTiddler(function(title,tiddler){
				var t=config.commands.collapseTiddler.getCollapsedTemplate();
				if(tiddler.getAttribute("template")!=t) return; // re-display only if collapsed
				var t=tiddler.getAttribute("savedTemplate");
				config.commands.collapseTiddler.display(title,t);
				tiddler.folded=false;
			});
			return false;
		})
	}
}

config.commands.collapseOthers = {
	text: "focus",
	tooltip: "Expand this tiddler and collapse all others",
	handler: function(event,src,title) {
		var e = story.findContainingTiddler(src); if (!e) return false;
		story.forEachTiddler(function(title,tiddler) {
			if(story.isDirty(title)) return;
			var t=config.commands.collapseTiddler.getCollapsedTemplate();
			if (e==tiddler) t=e.getAttribute("savedTemplate");
			config.commands.collapseTiddler.saveTemplate(tiddler);
			config.commands.collapseTiddler.display(title,t);
			tiddler.folded=(e!=tiddler);
		})
		return false;
	}
}

// {{{<<foldFirst>>}}} macro forces tiddler to be folded when *initially* displayed.
// Subsequent re-render does NOT re-fold tiddler, but closing/re-opening tiddler DOES cause it to fold first again.
config.macros.foldFirst = {
	handler: function(place,macroName,params,wikifier,paramString,tiddler){
		var e=story.findContainingTiddler(place);
		if (e.getAttribute("foldedFirst")=="true") return; // already been folded once
		var title=e.getAttribute("tiddler")
		var t=config.commands.collapseTiddler.getCollapsedTemplate();
		config.commands.collapseTiddler.saveTemplate(e);
		config.commands.collapseTiddler.display(title,t);
		e.setAttribute("folded","true");
		e.setAttribute("foldedFirst","true"); // only when tiddler is first rendered
		return false;
	}
}
//}}}
<!--{{{-->
<!--
|Name|CollapsedTemplate|
|Source|http://www.TiddlyTools.com/#CollapsedTemplate|
|Version||
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|template|
|Requires|ToolbarCommands|
|Description|alternative to ViewTemplate, used by CollapseTiddlersPlugin to display tiddler when 'folded'|
-->
<span class='toolbar' macro='toolbar [[ToolbarCommands::CollapsedToolbar]]'></span>
</span>
<span class='title'>
	<span class='floatleft' macro='tiddlerIcons' style='cursor:auto !important;'></span>
	<span macro='view title'></span>
</span>
<div class='tagClear'></div>
<!--}}}-->
/*{{{*/
Background: #dee4f6
Foreground: #080e20
PrimaryPale: #d6ddf4
PrimaryLight: #849be0
PrimaryMid: #3359cc
PrimaryDark: #0a1128
SecondaryPale: #e4f4d6
SecondaryLight: #b0e084
SecondaryMid: #7ccc33
SecondaryDark: #18280a
TertiaryPale: #f4ecd6
TertiaryLight: #e0c784
TertiaryMid: #cca333
TertiaryDark: #28200a
/*}}}*/
<<tiddler TemplateColorPaletteView with:ColorPalette>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','Background')}} Background>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','Foreground')}} Foreground>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','PrimaryPale')}} PrimaryPale>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','PrimaryLight')}} PrimaryLight>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','PrimaryMid')}} PrimaryMid>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','PrimaryDark')}} PrimaryDark>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','SecondaryPale')}} SecondaryPale>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','SecondaryLight')}} SecondaryLight>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','SecondaryMid')}} SecondaryMid>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','SecondaryDark')}} SecondaryDark>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','TertiaryPale')}} TertiaryPale>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','TertiaryLight')}} TertiaryLight>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','TertiaryMid')}} TertiaryMid>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','TertiaryDark')}} TertiaryDark>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('ColorPalette','Error')}} Error>>
/***
|''Name''|CommentsFormatter|
|''Description''|formatter adding comments syntax|
|''Author:''|FND|
|''Version''|0.1.2|
|''Status''|@@experimental@@|
|''Source''|http://devpad.tiddlyspot.com/#CommentsFormatter|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
!Usage
!!Examples
{{{
lorem /# foo
ipsum /# bar
}}}
<<<
lorem /# foo
ipsum /# bar
<<<
!Revision History
!!v0.1 (2009-05-06)
* initial release
!Code
***/
//{{{
(function(formatters) {

formatters.push({
	name: "comment",
	match: "\/#.*?(\n|$)",
	handler: function(w) {
		createTiddlyElement(w.output, "span", null, "comment", w.matchText);
		createTiddlyElement(w.output, "br");
	}
});

})(config.formatters);
//}}}
/***
|''Name''|ComputedStyleMacro|
|''Author''|FND|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#EvalMacro]]|
|''CodeRepository''|http://fnd.lewcid.org/svn/TiddlyWiki/|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Description''|retrieves parent container's computed CSS properties|
!Usage
{{{
<<calcStyle "CSS property">>
}}}
!!Examples
<<calcStyle "height">>
<<calcStyle "font-size">>
!Revision History
!!v0.1 (2008-03-31)
* initial release
!Code
***/
//{{{
config.macros.calcStyle = {};
config.macros.calcStyle.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	wikify("; " + params[0] + "\n" + ": " + getStyle(place, params[0]), place);
};

// retrieve computed CSS property
// by Inge J貧ensen (http://www.elektronaut.no/articles/2006/06/07/computed-styles)
function getStyle(element, cssRule) {
	if(document.defaultView && document.defaultView.getComputedStyle) {
		var value = document.defaultView.getComputedStyle(element, "").getPropertyValue(
			cssRule.replace(/[A-Z]/g, function(match, char) { 
				return "-" + char.toLowerCase(); 
			})
		);
	}
	else if(element.currentStyle)
		var value = element.currentStyle[cssRule];
	else
		var value = false;
	return value;
}
//}}}
/***
|''Name''|ConditionalTableFormattingMacro|
|''Description''|apply formatting based on table contents|
|''Author''|FND|
|''Version''|0.2|
|''Status''|@@experimental@@|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#EvalMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
!Usage
{{{
<<conditionalTableFormatting [cell|row] matchValue className>>
}}}
!!Parameters
|!Index|!Description|!Optional|!Default Value|
|1|case #1: value to search for|no|N/A|
|2|case #1: class to apply to matching elements|no|N/A|
|3|case #1: apply class to individual cells or the entire row|yes|cell|
|4|case #2: value to search for|yes|N/A|
|5|case #2: class to apply to matching elements|yes|N/A|
|6|case #2: apply class to individual cells or the entire row|yes|cell|
|7|...|yes|N/A|
|8|...|yes|N/A|
|9|...|yes|cell|
|10|case #//n//: value to search for|yes|N/A|
|11|case #//n//: class to apply to matching elements|yes|N/A|
|12|case #//n//: apply class to individual cells or the entire row|yes|cell|
!!Examples
<<<
|foo|bar|baz|
<<conditionalTableFormatting "" "bar" "header">>
<<<
<<<
|1|2|3|
|lorem|ipsum|dolor|
|foo|bar|baz|
<<conditionalTableFormatting "row" "lorem" "header" "cell" "2" "wizard">>
<<<
!Notes
The first table within the respective container (usually a tiddler) is used.
In order to target a different table, a CSS class wrapper can be used:
{{{
 {{dummyClass{
 |foo|bar|baz|
 }}}
}}}
!Revision History
!!v0.1 (2008-05-30)
* initial release
!!v0.2 (2008-06-01)
* significant changes to accommodate multiple cases per macro call
!To Do
* documentation
* option for combining matching conditions (boolean operators?)
* add option to target respective column
* add option for RegEx matching
!Code
***/
//{{{
config.macros.conditionalTableFormatting = {};

config.macros.conditionalTableFormatting.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	while(params.length) {
		// process parameters
		var target = (params.shift() === "row") ? "row" : "cell";
		var match = params.shift();
		var className = params.shift();
		// retrieve table cells
		var table = place.getElementsByTagName("table")[0];
		var cells = table.getElementsByTagName("td");
		for(var i = 0; i < cells.length; i++) {
			var text = cells[i].innerText || cells[i].textContent;
			// apply conditional formatting
			if(text === match) {
				addClass((target === "row") ? cells[i].parentNode : cells[i], className);
			}
		}
	}
};
//}}}
options.txtUserName:jon
macros.RandomColorPaletteButton.text:Ny FarvePalette
macros.RandomColorPaletteButton.tooltip:Generér en tilfældig
/***
Just some bits and pieces
***/
//{{{
config.messages.messageClose.text = "X"; // default is "close"
config.views.wikified.defaultText = ""; // default is "The tiddler '%0' doesn't yet exist. Double-click to create it"
//}}}
//{{{
//--
//-- Popup menu (improvements to be included in the core)
//--

var Popup = {
	stack: [] // Array of objects with members root: and popup:
	};

Popup.create = function(root,elem,theClass)
{
	var stackPosition = this.findStackPosition(root,"popup");
	Popup.remove(stackPosition+1);
	var popup = createTiddlyElement(document.body,elem ? elem : "ol","popup",theClass ? theClass : "popup");
	popup.stackPosition = stackPosition;
	Popup.stack.push({root: root, popup: popup});
	return popup;
};

Popup.onDocumentClick = function(e)
{
	if (!e) var e = window.event;
	var target = resolveTarget(e);
	if(e.eventPhase == undefined)
		Popup.remove();
	else if(e.eventPhase == Event.BUBBLING_PHASE || e.eventPhase == Event.AT_TARGET)
		Popup.remove();
	return true;
};

Popup.show = function(offset,unused1,unused2)
{
	var curr = Popup.stack[Popup.stack.length-1];
	this.place(curr.root,curr.popup,offset);
	addClass(curr.root,"highlight");
	if(config.options.chkAnimate && anim && typeof Scroller == "function")
		anim.startAnimating(new Scroller(curr.popup));
	else
		window.scrollTo(0,ensureVisible(curr.popup));
};

Popup.place = function(root,popup,offset)
{
	if(!offset) var offset = {x:0, y:0};
	if (popup.stackPosition>=0){
		offset.x = offset.x + 15;
		}
	var rootLeft = findPosX(root);
	var rootTop = findPosY(root);
	var rootHeight = root.offsetHeight;
	var popupLeft = rootLeft + offset.x;
	var popupTop = rootTop + rootHeight + offset.y;
	var winWidth = findWindowWidth();
	if(popup.offsetWidth > winWidth*0.75)
		popup.style.width = winWidth*0.75 + "px";
	var popupWidth = popup.offsetWidth;
	if(popupLeft + popupWidth > winWidth)
		popupLeft = winWidth - popupWidth;
	popup.style.left = popupLeft + "px";
	popup.style.top = popupTop + "px";
	popup.style.display = "block";
}

Popup.findStackPosition = function(item,node)
{
	var pointer = -1;
	for (var i=this.stack.length-1; i> -1; i--){
		if(isDescendant(item,this.stack[i][node])){
			pointer = i; 
		}
	}
	return pointer;
};

Popup.remove = function(pos)
{
	if (!pos) var pos = 0;
	if(Popup.stack.length > pos) {
		Popup.removeFrom(pos);
	}
};

Popup.removeFrom = function(from)
{
	for(var t=Popup.stack.length-1; t>=from; t--) {
		var p = Popup.stack[t];
		removeClass(p.root,"highlight");
		removeNode(p.popup);
	}
	Popup.stack = Popup.stack.slice(0,from);
};
//}}}
/***
|''Name''|CrossIndexingMacro|
|''Version''|0.7|
|''Status''|@@beta@@|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#CrossIndexingMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|[//TBD//]|
!Notes
Created [[for DaveG|http://groups.google.com/group/TiddlyWiki/browse_thread/thread/afa54bd105e791fa]]'s [[My Notes TiddlyWiki|http://www.giffmex.org/emptynotestw.html]].
!Usage
{{{
<<crossIndex [tag] [scope]>>
}}}
!Revision History
!!v0.5 (2008-02-08)
* initial release
!!v0.6 (2008-02-09)
* renamed to CrossIndexingMacro (from TiddlerHierarchyMacro)
* added listing of uncategorized items
* linkified headings
!!v0.7 (2008-02-10)
* added optional scope parameter
* fixed "uncategorized" listings
* minor code enhancements
!To Do
* rename
* documentation
* code sanitizing
!Code
***/
//{{{
config.macros.crossIndex = {};

config.macros.crossIndex.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var scope = params[1] || tiddler.title;
	var index = this.getIndex(scope, params[0]);
	var output = "";
	var i;
	for(topic in index) {
		if(index[topic].length > 0) {
			output += "![[" + topic + "]]\n";
			for(i = 0; i < index[topic].length; i++) {
				output += "* [[" + index[topic][i] + "]]\n";
			}
		}
	}
	wikify(output, place);
}

config.macros.crossIndex.getIndex = function(scope, category) {
	// retrieve topics
	var topics = store.getTaggedTiddlers(category).map(function(t) { return t.title });
	// generate index
	var index = {
		uncategorized: []
	};
	for(i = 0; i < topics.length; i++) {
		index[topics[i]] = [];
		store.forEachTiddler(function(title, tiddler) {
			if(tiddler.tags.containsAll([scope, topics[i]]))
				index[topics[i]].push(title);
			else if(tiddler.tags.contains(scope) && !tiddler.tags.containsAny(topics))
				index.uncategorized.pushUnique(title);
		});
	}
	return index;
}
//}}}
/***
|Name|DcTableOfContentsPlugin|
|Author|[[Doug Compton|http://www.zagware.com/tw/plugins.html#DcTableOfContentsPlugin]]|
|Contributors|[[Lewcid|http://lewcid.org]], [[FND|http://devpad.tiddlyspot.com]], [[ELS|http://www.tiddlytools.com]]|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com#DcTableOfContentsPlugin]]|
|Version|0.4.1|
|~CoreVersion|2.2|
<<showtoc>>
!Description
This macro will insert a table of contents reflecting the headings that are used in a tiddler and will be automatically updated when you make changes.  Each item in the table of contents can be clicked on to jump to that heading.  It can be used either inside of select tiddlers or inside a system wide template.

A parameter can be used to show the table of contents of a seperate tiddler, &lt;<showtoc tiddlerTitle>&gt;

It will also place a link beside each header which will jump the screen to the top of the current tiddler.  This will only be displayed if the current tiddler is using the &lt;<showtoc>&gt; macro.

The appearance of the table of contents and the link to jump to the top can be modified using CSS.  An example of this is given below.

!Usage
!!Only in select tiddlers
The table of contents above is an example of how to use this macro in a tiddler.  Just insert &lt;<showtoc>&gt; in a tiddler on a line by itself.

It can also display the table of contents of another tiddler by using the macro with a parameter, &lt;<showtoc tiddlerTitle>&gt;
!!On every tiddler
It can also be used in a template to have it show on every tiddler.  An example ViewTemplate is shown below.

//{{{
<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'>Created <span macro='view created date DD-MM-YY'></span>, updated <span macro='view modified date DD-MM-YY'></span></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class="toc" macro='showtoc'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
//}}}

!Examples
If you had a tiddler with the following headings:
{{{
!Heading1a
!!Heading2a
!!Heading2b
!!!Heading3
!Heading1b
}}}
this table of contents would be automatically generated:
* Heading1a
** Heading2a
** Heading2b
*** Heading3
* Heading1b
!Changing how it looks
To modifiy the appearance, you can use CSS similiar to the below.
//{{{
.dcTOC ul {
	color: red;
	list-style-type: lower-roman;
}
.dcTOC a {
	color: green;
	border: none;
}

.dcTOC a:hover {
	background: white;
	border: solid 1px;
}
.dcTOCTop {
	font-size: 2em;
	color: green;
}
//}}}

!Revision History
!!v0.1.0 (2006-04-07)
* initial release
!!v0.2.0 (2006-04-10)
* added the [top] link on headings to jump to the top of the current tiddler
* appearance can now be customized using CSS
* all event handlers now return false
!!v0.3.0 (2006-04-12)
* added the ability to show the table of contents of a seperate tiddler
* fixed an error when a heading had a ~WikiLink in it
!!v0.3.5 (2007-10-16)
* updated formatter object for compatibility with TiddlyWiki v2.2 (by Lewcid)
!!v0.4.0 (2007-11-14)
* added toggle button for collapsing/expanding table of contents element
* refactored documentation
!To Do
* code sanitizing/rewrite
* documentation refactoring
* use shadow tiddler for styles
!Code
***/
//{{{

version.extensions.DcTableOfContentsPlugin= {
	major: 0, minor: 4, revision: 0,
	type: "macro",
	source: "http://devpad.tiddlyspot.com#DcTableOfContentsPlugin"
};

// Replace heading formatter with our own
for (var n=0; n<config.formatters.length; n++) {
	var format = config.formatters[n];
	if (format.name == 'heading') {
		format.handler = function(w) {
			// following two lines is the default handler
			var e = createTiddlyElement(w.output, "h" + w.matchLength);
			w.subWikifyTerm(e, this.termRegExp); //updated for TW 2.2+

			// Only show [top] if current tiddler is using showtoc
			if (w.tiddler && w.tiddler.isTOCInTiddler == 1) {
				// Create a container for the default CSS values
				var c = createTiddlyElement(e, "div");
				c.setAttribute("style", "font-size: 0.5em; color: blue;");
				// Create the link to jump to the top
				createTiddlyButton(c, " [top]", "Go to top of tiddler", window.scrollToTop, "dcTOCTop", null, null);
			}
		}
		break;
	}
}

config.macros.showtoc = {
	handler: function(place, macroName, params, wikifier, paramString, tiddler) {
		var text = "";
		var title = "";
		var myTiddler = null;

		// Did they pass in a tiddler?
		if (params.length) {
			title = params[0];
			myTiddler = store.getTiddler(title);
		} else {
			myTiddler = tiddler;
		}

		if (myTiddler == null) {
			wikify("ERROR: Could not find " + title, place);
			return;
		}

		var lines = myTiddler .text.split("\n");
		myTiddler.isTOCInTiddler = 1;

		// Create a parent container so the TOC can be customized using CSS
		var r = createTiddlyElement(place, "div", null, "dcTOC");
		// create toggle button
		createTiddlyButton(r, "toggle", "show/collapse table of contents",
			function() { config.macros.showtoc.toggleElement(this.nextSibling); },
			"toggleButton")
		// Create a container so the TOC can be customized using CSS
		var c = createTiddlyElement(r, "div");

		if (lines != null) {
			for (var x=0; x<lines.length; x++) {
				var line = lines[x];
				if (line.substr(0,1) == "!") {
					// Find first non ! char
					for (var i=0; i<line.length; i++) {
						if (line.substr(i, 1) != "!") {
							break;
						}
					}
					var desc = line.substring(i);
					// Remove WikiLinks
					desc = desc.replace(/\[\[/g, "");
					desc = desc.replace(/\]\]/g, "");

					text += line.substr(0, i).replace(/[!]/g, '*');
					text += '<html><a href="javascript:;" onClick="window.scrollToHeading(\'' + title + '\', \'' + desc+ '\', event)">' + desc+ '</a></html>\n';
				}
			}
		}
		wikify(text, c);
	}
}

config.macros.showtoc.toggleElement = function(e) {
	if(e) {
		if(e.style.display != "none") {
			e.style.display = "none";
		} else {
			e.style.display = "";
		}
	}
};

window.scrollToTop = function(evt) {
	if (! evt)
		var evt = window.event;

	var target = resolveTarget(evt);
	var tiddler = story.findContainingTiddler(target);

	if (! tiddler)
		return false;

	window.scrollTo(0, ensureVisible(tiddler));

	return false;
};

window.scrollToHeading = function(title, anchorName, evt) {
	var tiddler = null;

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

	if (title) {
		story.displayTiddler(store.getTiddler(title), title, null, false);
		tiddler = document.getElementById(story.idPrefix + title);
	} else {
		var target = resolveTarget(evt);
		tiddler = story.findContainingTiddler(target);
	}

	if (tiddler == null)
		return false;
	
	var children1 = tiddler.getElementsByTagName("h1");
	var children2 = tiddler.getElementsByTagName("h2");
	var children3 = tiddler.getElementsByTagName("h3");
	var children4 = tiddler.getElementsByTagName("h4");
	var children5 = tiddler.getElementsByTagName("h5");

	var children = new Array();
	children = children.concat(children1, children2, children3, children4, children5);

	for (var i = 0; i < children.length; i++) {
		for (var j = 0; j < children[i].length; j++) {
			var heading = children[i][j].innerHTML;

			// Remove all HTML tags
			while (heading.indexOf("<") >= 0) {
				heading = heading.substring(0, heading.indexOf("<")) + heading.substring(heading.indexOf(">") + 1);
			}

			// Cut off the code added in showtoc for TOP
			heading = heading.substr(0, heading.length-6);

			if (heading == anchorName) {
				var y = findPosY(children[i][j]);
				window.scrollTo(0,y);
				return false;
			}
		}
	}
	return false
};
//}}}
/***
|Name|DebuggingPlugin|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#DebuggingPlugin]]|
|Version|0.5|
|Author|FND|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|provides a simple framework for debugging|
!Usage
* {{{showDebugBuffer(string)}}}
* {{{print_r(array, indentationPrefix)}}}
!Changelog
!!v0.5 (2007-05-29)
* initial release
!To Do
* use tiddler instead of a "raw" element
!Code
***/
//{{{
/* Styles (can be customized in the StyleSheetDEBUG shadow tiddler) */

config.shadowTiddlers.StyleSheetDEBUG = "/*{{{*/\n"
	+ "#DebugBuffer {\n\tmargin: 10em 1em 1em;\n\tpadding: 4px;\n\tborder: 1px solid #AAA;\n\tfont-size: 1.2em;\n\tbackground-color: #F8F8F8;\n}\n"
	+ "/*}}}*/";
store.addNotification("StyleSheetDEBUG", refreshStyles);

/* Functions */

// create pane for debugging outputs
function createDebugBuffer(text) {
	// initialize DEBUG buffer
	text = "******************\n"
	+ "** DEBUG BUFFER **\n"
	+ "******************\n\n"
	+ text;
	// create output element
	createTiddlyElement(document.body, "pre", "DebugBuffer", null, text);
}

// print_r() for JavaScript (http://www.phpbuilder.com/board/showthread.php?t=10294264)
function print_r(input, _indent) {
    if(typeof(_indent) == 'string') {
        var indent = _indent + '    ';
        var paren_indent = _indent + '  ';
    } else {
        var indent = '    ';
        var paren_indent = '';
    }
    switch(typeof(input)) {
        case 'boolean':
            var output = (input ? 'true' : 'false') + "\n";
            break;
        case 'object':
            if ( input===null ) {
                var output = "null\n";
                break;
            }
            var output = ((input.reverse) ? 'Array' : 'Object') + " (\n";
            for(var i in input) {
                output += indent + "[" + i + "] => " + print_r(input[i], indent);
            }
            output += paren_indent + ")\n";
            break;
        case 'number':
        case 'string':
        default:
            var output = "" + input  + "\n";
    }
    return output;
}
//}}}
/*{{{*/
// TiddlyWiki
config.options.txtUserName = "FND";
config.options.chkAutoSave = false;
config.options.chkSaveBackups = false;
config.options.txtBackupFolder = "Backup";
/*}}}*/
[[YAPC EUROPE RIGA]]
/%
!info
|Name|DigitalClock|
|Source|http://www.TiddlyTools.com/#DigitalClock|
|Version|2.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|display current time with automatic update|
Usage
<<<
{{{
<<tiddler DigitalClock with: format tick>>
}}}
*''format'' is any TiddlyWiki date/time formatting string
*''tick'' is the time in seconds between display updates (default=1sec)
<<<
Example
<<<
show hours, minutes and seconds, updated once per second:
{{{<<tiddler DigitalClock with: "hh:0mm:0ss" 1>>}}}
<<tiddler DigitalClock##show with: "hh:0mm:0ss" 1>>
<<<
!end
!show
<html><a href='javascript:;'></a></html><<tiddler {{
	window.DigitalClock_tick=function(id){
		var e=document.getElementById(id); if (!e) return;
		e.title='click to '+(e.paused?'RESUME':'PAUSE')+' clock display';
		if (e.paused) return;
		e.innerHTML=new Date().formatString(e.fmt);
		e.timer=setTimeout('window.DigitalClock_tick('+id+')',e.tick*1000);
	}
	var e=place.lastChild.firstChild;
	e.id=new Date().getTime()+Math.random();
	e.onclick=function(){this.paused=!this.paused;window.DigitalClock_tick(this.id);}
	e.style.cursor='pointer';
	e.fmt=('$1'=='$'+'1')?'hh12:0mm:0ss am':'$1';
	e.tick=('$2'=='$'+'2')?'1':'$2';
	if (e.timer===undefined) window.DigitalClock_tick(e.id);
'';}}>>
!end
%/<<tiddler {{'DigitalClock##'+(tiddler&&tiddler.title=='DigitalClock'?'info':'show');}}
	with: [[$1]] [[$2]]>>
/***
|''Name:''|DoBackupMacro|
|''Version:''|2.0 (9-Apr-2006)|
|''Author:''|[[Jack]]|
|''Type:''|Macro|
!Description
Creates a button which allows you to backup your TiddlyWiki on demand.
!Usage
Add the following command to your SideBarOptions tiddler:
{{{<<doBackup>>}}}
!Revision History
* Original by [[Jack]] 9-Apr-2006
!To Do
* List non-explicit links (e.g. from tagging macro)

!Code
***/
//{{{
version.extensions.doBackup= {major: 2, minor: 0, revision: 0, date: new Date("Apr 9, 2006")};
config.macros.doBackup={label: "backup", prompt: "Backup this TiddlyWiki"}
config.macros.doBackup.handler = function(place)
{
 if(!readOnly)
 createTiddlyButton(place,this.label,this.prompt,function ()
{doBackup(); return false;},null,null,this.accessKey);
}

doBackup = function() {
 var optSaveBackups = config.options.chkSaveBackups
 config.options.chkSaveBackups = true
 saveChanges()
 config.options.chkSaveBackups = optSaveBackups
}

//}}}
/***
|Name|EasyHighlightingPlugin|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#EasyHighlightingPlugin]]|
|Version|0.1|
|Author|FND|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|allow for simple highlighting by selecting text|
!Usage
[tbd]
!Changelog
!!v0.1 (2007-05-27)
* alpha version
!Issues / To Do
[tbd; cf [[[tw] discussion|http://groups.google.com/group/TiddlyWiki/t/349af49c41f8bf44]]]
''N.B.:'' development is currently ''ON HOLD'':
<<<
Since the text is selected from the formatted (wikified) output, I'll run into trouble as soon as there's any kind of wiki markup involved (e.g. trying to highlight "lorem ''ipsum'' dolor" would not be recognized -- or it might even strip the bold formatting).
<<<
!Code
***/
//{{{
/*
** Styles (can be customized in the StyleSheetEasyHighlighting shadow tiddler)
*/

config.shadowTiddlers.StyleSheetEasyHighlighting = "/*{{{*/\n"
	+ ".highlightDefault {\n\tbackground-color: #FF0;\n\tcursor: pointer;\n}\n"
	+ "/*}}}*/";
store.addNotification("StyleSheetEasyHighlighting", refreshStyles);

/*
** Macro Code
*/

config.macros.EasyHighlighting = { label: "Highlight", prompt: "Toggle highlighting" };
config.macros.EasyHighlighting.handler =
	function(place, macroName, params, wikifier, paramString, tiddler) {
		
}

/*
** Command Buttons
*/

/* Macro Button */
config.macros.EasyHighlighting = { label: "Highlight", prompt: "Toggle highlighting", accessKey: "h" }; // DEBUG: check accessKey usage
config.macros.EasyHighlighting.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	createTiddlyButton(place, this.label, this.prompt, function() { // DEBUG: how to pass current tiddler to function?
			// highlight selected text
			highlightPassage(place, tiddler, "highlightDefault"); // DEBUG: tiddler is undefined (see above)
			return false; // DEBUG: ?
		}, null, null, this.accessKey
	);
}

/* Toolbar Button */
config.commands.EasyHighlighting = { label: "Highlight", prompt: "Toggle highlighting" } // DEBUG: accessKey!?
config.commands.EasyHighlighting.handler = function() {
	// highlight selected text
	highlightPassage(place, tiddler, "highlightDefault");
	return false; // DEBUG: ?
}

/*
** Main Code
*/

highlightPassage = function(place, tiddler, className) {
	// get selection
	var selection = getSelText();
	if(selection == "") {
		alert("Error: No text selected.");
		return
	}
	// retrieve tiddler -- DEBUG: obsolete?! only necessary for macro button, because tiddler parameter is not working there (see Command Buttons section)
	var here = story.findContainingTiddler(place);
	if(!here) {
		alert("Error: No tiddler specified.");
		return;
	}
	var title = here.getAttribute("tiddler");
	var tiddler = store.getTiddler(title);
	// determine tiddler contents
	var tiddlerContents = tiddler.text;
	var tiddlerParts = tiddlerContents.split(selection);
	var preSelection = tiddlerParts[0]; // DEBUG: to do
	var postSelection = tiddlerParts[1]; // DEBUG: to do
	// highlight selected passage
	alert(tiddlerParts.length + "\n\npreSelection:\n" + preSelection + "\n\npostSelection:\n" + postSelection); // DEBUG
	tiddlerContents = preSelection + "{{" + className + "{" + selection + "}}}" + postSelection;
	alert("tiddlerContents:\n" + tiddlerContents); // DEBUG
	// store altered tiddler contents
	//wikify(tiddlerContents, place); // DEBUG'd
	// ??
	return false;
}

/*
** Support Functions
*/

// getSelText() by Jeff Anderson (http://www.codetoad.com/javascript_get_selected_text.asp)
function getSelText() {
	var txt = "";
	if (window.getSelection) {
		txt = window.getSelection();
	} else if (document.getSelection) {
		txt = document.getSelection();
	} else if (document.selection) {
		txt = document.selection.createRange().text;
	} else {
		return;
	}
	return txt;
}
//}}}
This is a test for the EasyHighlightingPlugin.
<<EasyHighlighting>>
<<<
Lorem ipsum dolor ''sit'' amet, consectetur adipisicing elit, sed do //eiusmod// tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea @@commodo@@ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse --cillum-- dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia __deserunt__ mollit anim id est laborum.
<<<
/***
<<EasyLayout>>
***/
//{{{
/*
** Macro Initialization
*/

config.macros.EasyLayout = {};
config.macros.EasyLayout.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	this.loadSettings();
	this.generateUI(place);
};

/*
** User Interface
*/

config.macros.EasyLayout.generateUI = function(parent) {
	// create root form
	var frm = createTiddlyElement(parent, "form", null, "easyLayout"); // DEBUG: requires action parameter
	frm.style.border = "1px solid #AAA"; // DEBUG: use shadow tiddler for styles
	frm.style.marginBottom = "1em"; // DEBUG: use shadow tiddler for styles
	frm.style.padding = "5px"; // DEBUG: use shadow tiddler for styles
	frm.style.overflow = "hidden"; // DEBUG: use shadow tiddler for styles
	frm.style.backgroundColor = "#EEE"; // DEBUG: use shadow tiddler for styles

	// create custom UI elements
	this.createUiElements(frm);

	// create control buttons
	var btns = createTiddlyElement(frm, "div");
	btns.style.textAlign = "right"; // DEBUG: use shadow tiddler for styles
	// preview
	var btn = createTiddlyElement(btns, "input");
	btn.setAttribute("type", "button");
	btn.setAttribute("value", "Apply");
	btn.onclick = function() {
		config.macros.EasyLayout.applyChanges(false);
		return false;
	}
	// save
	btn = createTiddlyElement(btns, "input");
	btn.setAttribute("type", "button");
	btn.setAttribute("value", "Save");
	btn.onclick = function() {
		config.macros.EasyLayout.applyChanges(true);
		return false;
	}
};

// DEBUG: read from JSON structure for easy modification
config.macros.EasyLayout.createUiElements = function(frm) {
	// initialize variables
	var fs = null; // fieldset
	var sc = null; // section

	/*
	** Header
	*/
	fs = this.createFieldset(frm, "Header");
	// height
	sc = this.createSection(fs);
	this.createInputField(sc, "input", "height");
	this.createOptions(sc, "headerHeight");
	// width
	sc = this.createSection(fs);
	this.createInputField(sc, "input", "width");
	this.createOptions(sc, "headerWidth");

	/*
	** Sidebar
	*/
	fs = this.createFieldset(frm, "Sidebar");
	// width
	sc = this.createSection(fs);
	this.createInputField(sc, "input", "width");
	this.createOptions(sc, "sidebarWidth");
	// offset
	sc = this.createSection(fs);
	this.createInputField(sc, "input", "offset");
	this.createOptions(sc, "sidebarOffset");
};

/*
** Layout Modification
*/

config.macros.EasyLayout.applyChanges = function(permanent) {
	alert("not implemented"); // DEBUG: to do
	if(permanent)
		this.saveSettings();
}

/*
** Settings
*/

config.macros.EasyLayout.saveSettings = function() {
	alert("permanent settings not implemented"); // DEBUG: to do -- options: slices in a dedicated tiddler, extended fields, JSON(?)
}

config.macros.EasyLayout.loadSettings = function() {
	alert("permanent settings not implemented"); // DEBUG: to do
}

/*
** DOM Utilities
*/

config.macros.EasyLayout.createFieldset = function(parent, label) {
	var e = createTiddlyElement(parent, "fieldset");
	e.style.marginBottom = "5px"; // DEBUG: use shadow tiddler for styles
	createTiddlyElement(e, "legend", null, null, label);
	return e;
};

config.macros.EasyLayout.createSection = function(parent) {
	var e = createTiddlyElement(parent, "DIV");
	e.style.marginBottom = "5px"; // DEBUG: use shadow tiddler for styles
	return e;
};

config.macros.EasyLayout.createInputField = function(parent, ID, description) {
	var e = createTiddlyElement(parent, "div", null, null, description + ":");
	e.style.fontWeight = "bold"; // DEBUG: use shadow tiddler for styles
	e.style.marginRight = "1em"; // DEBUG: use shadow tiddler for styles
	e = createTiddlyElement(parent, "input", ID);
	e.setAttribute("type", "text"); // DEBUG: might not work in IE; need to set attribute before appending node to document!?
	return e;
};

config.macros.EasyLayout.createOptions = function(parent, IdPrefix) { // DEBUG: dynamic arguments - e.g. createOptions("px", "em", "%")	
	parent.innerHTML = parent.innerHTML // innerHTML required due to IE bug
		+ "<input id='" + IdPrefix + "1' name='" + IdPrefix + "' type='radio'>"
		+ "<label for='" + IdPrefix + "1'>px</label>"
		+ "<input id='" + IdPrefix + "2' name='" + IdPrefix + "' type='radio'>"
		+ "<label for='" + IdPrefix + "2'>em</label>"
		+ "<input id='" + IdPrefix + "3' name='" + IdPrefix + "' type='radio'>"
		+ "<label for='" + IdPrefix + "3'>%</label>"
};
//}}}
free-floating edit window (non-disruptive edit mode)
edit mode as a (temporary) portlet instead of replacing the wikified tiddler view
cf. [[mock-up image|http://www.tiddlywiki.org/wiki/Image:EditPortlet.png]]
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<div class='editor' macro='edit text'></div>
<!--}}}-->

http://www.ldoceonline.com


/***
|''Name''|EvalMacro|
|''Version''|0.96|
|''Status''|stable|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#EvalMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|Allows executing JavaScript code to return computed values.|
!Usage
{{{
<<eval [code] [mode]>>
}}}
* {{{<<eval {{code}}>>}}}
** if no mode is specified, the first parameter's contents will be wikified
** through the use evaluated parameters, calculations can be performed within this parameter
* {{{<<eval [[code]] "scriptMode">>}}}
** if "scriptMode" is specified, the contents of the first parameter will be evaluated in place, proving access to local variables like the tiddler object
** no output is generated in this mode by default, though the {{{wikify()}}} function can be used for that
!!Examples
<<eval {{
	var dateFormat = "YYYY-0MM-0DD 0hh:0mm";
	var now = new Date;
	"time: " + now.formatString(dateFormat);
}}>>
<<eval
	[[
	var dateFormat = "YYYY-0MM-0DD";
	var title = tiddler.title;
	var author = tiddler.modifier;
	var date = tiddler.modified.formatString(dateFormat);
	wikify(title + ": " + author + ", " + date, place);
	]]
	"scriptMode"
>>
!Revision History
!!v0.9 (2007-10-14)
* initial release
!!v0.95 (2007-12-23)
* introduced script mode
!!v0.96 (2008-04-18)
* bugfix regarding type conversion
!Code
***/
//{{{
config.macros.eval = {};
config.macros.eval.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	if(params[1] == "scriptMode")
		eval(params[0]);
	else
		wikify(params[0].toString(), place);
}
//}}}
/***
|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:|ExtentTagButtonPlugin|
|Description:|Adds a New tiddler button in the tag drop down|
|Version:|3.2a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#ExtendTagButtonPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{

window.onClickTag_mptw_orig = window.onClickTag;
window.onClickTag = function(e) {
  window.onClickTag_mptw_orig.apply(this,arguments);
  var tag = this.getAttribute("tag");
  var title = this.getAttribute("tiddler");
  // Thanks Saq, you're a genius :)
  var popup = Popup.stack[Popup.stack.length-1].popup;
  createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
  wikify("<<newTiddler label:'New tiddler' tag:'"+tag+"'>>",createTiddlyElement(popup,"li"));
  return false;
}

//}}}
SELECT department_id,
MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct) "Worst",
MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct) "Best"
   FROM employees
   GROUP BY department_id;

http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions056.htm#i1000901
/***
|Name|ForEachTiddlerTest|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#FETTest]]|
|Version|0.1|
|Author|FND|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|just for testing/debugging purposes|
!Usage
Add {{{<<FET>>}}} to the desired tiddler(s).
<<FET>>
!Changelog
!!v0.1 (2007-05-21)
* initial release
!Issues / To Do
* ...
!Code
***/
//{{{
/*
** Command Button
*/

/* Macro Button */
// adapted from Jack's DoBackupMacro (http://groups.google.com/group/TiddlyWiki/browse_thread/thread/5f1123d08bdadeac/86245d5e4bbe846c)
config.macros.FET = { label: "FETTest", prompt: "ForEachTiddler Test" };
config.macros.FET.handler = function(place) {
	createTiddlyButton(place, this.label, this.prompt, function() {
			var tmp = FETTest().tiddlers;
			tmp = FETTest(tmp, "plugin"); // DEBUG: test for second run
			alert(FETTest(tmp, "systemConfig")); // DEBUG: test for third run
			return false; // DEBUG: ?
		}, null, null, this.accessKey
	); // DEBUG - to do: look up createTiddlyButton()'s parameters
}

/*
** Main Code
*/

FETTest = function(object, filter) {
	// initialize
	alert(object + "\n\n" + filter); // DEBUG
	var tiddlers = []; // title and tags[] for each tiddler
	var tags = []; // global tags list
	var results = {}; // object for return values
	if(object == null) { // use store if no object has been specified
		object = store;
	}
	// retrieve matching tiddlers
	object.forEachTiddler(
		function(title, tiddler) {
			if(filter == null || inArray(filter, tiddler.tags)) { // check whether tiddler is assigned the filter tag
				var t = {}; // DEBUG: viable container for using forEachTiddler on?
				t.title = title;
				t.tags = tiddler.tags;
				tiddlers.push(t);
				// add unique tags to global list
				for(var i = 0; i < tiddler.tags.length; i++) {
					tags.pushUnique(tiddler.tags[i]);
				}
			}
		}
	);
	// return results
	results.tiddlers = tiddlers;
	results.tags = tags;
	return results;
}

/*
** Support Functions
*/

function inArray(needle, haystack) {
    for(var i = 0; i < haystack.length; i++) {
        if(haystack[i] == needle) {
            return true;
        }
    }
    return false;
}
//}}}
http://www.geany.org/
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[Работа в Люксофт]] & [[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>>
/%
!info
|Name|HideTiddlerBackground|
|Source|http://www.TiddlyTools.com/#HideTiddlerBackground|
|Version|2.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|hide a tiddler's background and border (if any)|
Usage:
<<<
{{{
<<tiddler HideTiddlerBackground>>
<<tiddler HideTiddlerBackground with: TiddlerTitle>>
}}}
<<<
!end
!show
<<tiddler {{
	var title="$1";
	if (title=='$'+'1')
		title=(story.findContainingTiddler(place)||place).getAttribute('tiddler')||'';
	var t=story.getTiddler(title); if (t) {
		var e=t.getElementsByTagName('*');
		for (var i=0; i<e.length; i++) if (hasClass(e[i],'viewer')) {
			var s=e[i].style;
			s.backgroundImage='none';
			s.backgroundColor='transparent';
			s.border=s.margin=s.padding='0px';
			break;
		}
	}
'';}}>>
!end
%/<<tiddler {{
	var src='HideTiddlerBackground';
	src+(tiddler&&tiddler.title==src?'##info':'##show');}}
with: [[$1]]>>
/%
!info
|Name|HideTiddlerSubtitle|
|Source|http://www.TiddlyTools.com/#HideTiddlerSubtitle|
|Version|2.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|hide a tiddler's subtitle (date and author)|
Usage:
<<<
{{{
<<tiddler HideTiddlerSubtitle>>
<<tiddler HideTiddlerSubtitle with: TiddlerTitle>>
}}}
<<<
!end
!show
<<tiddler {{
	var title="$1";
	if (title=='$'+'1')
		title=(story.findContainingTiddler(place)||place).getAttribute('tiddler')||'';
	var t=story.getTiddler(title); if (t) {
		var e=t.getElementsByTagName('*');
		for (var i=0; i<e.length; i++)
			if (hasClass(e[i],'subtitle')) e[i].style.display='none';
	}
'';}}>>
!end
%/<<tiddler {{
	var src='HideTiddlerSubtitle';
	src+(tiddler&&tiddler.title==src?'##info':'##show');}}
with: [[$1]]>>
/%
!info
|Name|HideTiddlerTags|
|Source|http://www.TiddlyTools.com/#HideTiddlerTags|
|Version|2.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|hide a tiddler's 'tagged' and 'tagging' displays (if any)|
Usage:
<<<
{{{
<<tiddler HideTiddlerTags>>
<<tiddler HideTiddlerTags with: TiddlerTitle>>
}}}
<<<
!end
!show
<<tiddler {{
	var title="$1";
	if (title=='$'+'1') {
		var here=story.findContainingTiddler(place);
		if (here) title=here.getAttribute('tiddler');
	}
	var t=story.getTiddler(title); if (t) {
		var e=t.getElementsByTagName('*');
		for (var i=0; i<e.length; i++)
			if (hasClass(e[i],'tagging')||hasClass(e[i],'tagged'))
				e[i].style.display='none';
	}
'';}}>>
!end
%/<<tiddler {{
	var src='HideTiddlerTags';
	src+(tiddler&&tiddler.title==src?'##info':'##show');}}
with: [[$1]]>>
/%
!info
|Name|HideTiddlerTitle|
|Source|http://www.TiddlyTools.com/#HideTiddlerTitle|
|Version|2.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|hide a tiddler's title and subtitle (date and author)|
Usage:
<<<
{{{
<<tiddler HideTiddlerTitle>>
<<tiddler HideTiddlerTitle with: TiddlerTitle>>
}}}
<<<
!end
!show
<<tiddler {{
	var title="$1";
	if (title=='$'+'1')
		title=(story.findContainingTiddler(place)||place).getAttribute('tiddler')||'';
	var t=story.getTiddler(title); if (t) {
		var e=t.getElementsByTagName('*');
		for (var i=0; i<e.length; i++)
			if (hasClass(e[i],'title')||hasClass(e[i],'subtitle')) e[i].style.display='none';
	}
'';}}>>
!end
%/<<tiddler {{
	var src='HideTiddlerTitle';
	src+(tiddler&&tiddler.title==src?'##info':'##show');}}
with: [[$1]]>>
/%
!info
|Name|HideTiddlerToolbar|
|Source|http://www.TiddlyTools.com/#HideTiddlerToolbar|
|Version|2.0.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|hide a tiddler's toolbar (menu commands)|
Usage:
<<<
{{{
<<tiddler HideTiddlerToolbar>>
<<tiddler HideTiddlerToolbar with: TiddlerTitle>>
}}}
<<<
!end

!show
<<tiddler {{
	var title="$1";
	if (title=='$'+'1')
		title=(story.findContainingTiddler(place)||place).getAttribute('tiddler')||'';
	var t=story.getTiddler(title); if (t) {
		var e=t.getElementsByTagName('*');
		for (var i=0; i<e.length; i++)
			if (hasClass(e[i],'toolbar')) e[i].style.display='none';
	}
'';}}>>
!end
%/<<tiddler {{
	var src='HideTiddlerToolbar';
	src+(tiddler&&tiddler.title==src?'##info':'##show');
}} with [[$1]]>>
/***
|Name|HideTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#HideTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#HideTiddlersPlugin|
|Version|1.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|hide/show tiddlers instead of closing/re-opening them|
|Status|ALPHA EXPERIMENTAL - use with caution|
!!!!!Documentation
<<<
This plugin hijacks the core's displayTiddler() and closeTiddler() functions so that closing a tiddler //hides// it rather than removing it from the story column.  When the tiddler is re-opened, it is made visible again without needing to be re-rendered, which can significantly reduce the processing required by tiddlers that generate their content through use of complex macros or scripts.

Notes:
*hidden tiddlers are still re-rendered as needed when underlying information is changed or other page-wide refresh events occur, so that they will still be up-to-date if re-displayed.  This can, in some cases, trigger side-effect actions associated with those tiddlers that would normally not occur had they actually been closed, rather than merely hidden from view
*Using <<closeAll>> (or invoking the core {{{restart()}}} function) will always //close// the tiddlers rather than hiding them, regardless of the current plugin settings or tiddler tags
<<<
!!!!!Configuration
<<<
hide tiddlers instead of closing them:
<<option chkNoClose>>tiddlers tagged with <<option txtNoCloseTag>>
<<option chkNoCloseAll>>all tiddlers, regardless of tags
<<<
!!!!!Revisions
<<<
2009.10.04 [1.0.0] initial release.  Much thanks to Shviller for original concept.
<<<
!!!!!Code
***/
//{{{
version.extensions.HideTiddlersPlugin= {major: 1, minor: 0, revision: 0, date: new Date(2009,10,4)};

var co=config.options; //abbrev
if (co.chkNoClose===undefined)	  co.chkNoClose=true;
if (co.txtNoCloseTag===undefined) co.txtNoCloseTag='noClose';

if (Story.prototype.displayTiddler_save===undefined)
	Story.prototype.displayTiddler_save=Story.prototype.displayTiddler;
Story.prototype.displayTiddler=function(place,title) {
	var here=story.getTiddler(title);
	if (here) here.style.display='block';
	this.displayTiddler_save.apply(this,arguments);
}

if (Story.prototype.closeTiddler_save===undefined)
	Story.prototype.closeTiddler_save=Story.prototype.closeTiddler;
Story.prototype.closeTiddler=function(title) {
	var co=config.options; //abbrev
	var t=store.getTiddler(title);
	if (co.chkNoCloseAll || co.chkNoClose&&t&&t.isTagged(co.txtNoCloseTag)) {
		var here=story.getTiddler(title);
		if (here) here.style.display='none';
		forceReflow();
	} else this.closeTiddler_save.apply(this,arguments);
}

if (Story.prototype.closeAllTiddlers_save===undefined)
	Story.prototype.closeAllTiddlers_save=Story.prototype.closeAllTiddlers;
Story.prototype.closeAllTiddlers=function(title) {
	var co=config.options; //abbrev
	var t=co.chkNoClose;
	co.chkNoClose=false;
	this.closeAllTiddlers_save.apply(this,arguments);
	co.chkNoClose=t;
}
//}}}
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.2a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}

Warning: the showWhen and hideWhen macros will blindly eval paramString.
This could be used to execute harmful javascript from a tiddler.

(TODO: Make some effort to sanitize paramString. Perhaps disallow the equals sign?)
***/
//{{{

window.hideWhenLastTest = false;

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

merge(config.macros,{

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

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

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

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

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

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

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

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

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

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

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

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

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

});

//}}}
http://www.modernperlbooks.com/mt/2011/01/how-to-identify-a-good-perl-programmer.html
http://univertv.ru/video/informatika/programmirovanie/?mark=science1
http://www.mojolicious.org/
How to find large files in Linux

Solution
At the command line as root enter:

find / -size +102400k

This will find all files on the entire system that are bigger than 100 MB.
Use this one to see the sizes:
find / -size +103400k | xargs ls -laAh
Use "find ." to look only in the current directory.
find . -size +103400k | xargs ls -laAh


 find . -type f -maxdepth 1
http://irc.freenode.org/ Вортингтон
!Simple Images
{{{
[img[http://wikitext.tiddlyspace.com/fractalveg.jpg]]
}}}
Displays as:
[img[http://wikitext.tiddlyspace.com/fractalveg.jpg]]
!Tooltips for Images
{{{
[img[tooltip|http://wikitext.tiddlyspace.com/fractalveg.jpg]]
}}}
Displays as:
[img[tooltip|http://wikitext.tiddlyspace.com/fractalveg.jpg]]
!Image Links
{{{
[img[http://wikitext.tiddlyspace.com/fractalveg.jpg][http://www.flickr.com/photos/jermy/10134618/]]
}}}
Displays as:
[img[http://wikitext.tiddlyspace.com/fractalveg.jpg][http://www.flickr.com/photos/jermy/10134618/]]
!Floating Images with Text
{{{
[<img[http://wikitext.tiddlyspace.com/fractalveg.jpg]]
}}}
[<img[http://wikitext.tiddlyspace.com/fractalveg.jpg]]Displays as.
{{{
@@clear:both;display:block; @@
}}}
Will then clear the float.
@@clear:both;display:block;Like this@@
{{{
[>img[http://wikitext.tiddlyspace.com/fractalveg.jpg]]
}}}
[>img[http://wikitext.tiddlyspace.com/fractalveg.jpg]]Displays as.@@clear:both;display:block; @@
!See Also
[[Image Macro]]
/***
|''Name''|ImageMacroPlugin|
|''Version''|0.9.4|
|''Description''|Allows the rendering of svg images in a TiddlyWiki|
|''Author''|Osmosoft|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''Notes''|Currently only works in modern browsers (not IE)|
|''Requires''|BinaryTiddlersPlugin|
!Usage
{{{<<image SVG>>}}} will render the text of the tiddler with title SVG as an SVG image (but not in ie where it will fail silently)
!!Parameters
width/height: specify width/height parameters
link: make the image link to a given location
tiddlyLink: link to a tiddler

!Notes
Binary tiddlers in TiddlyWeb when passed through the wikifier will be shown as images.
eg. {{{<<view text wikified>>}}} on a binary tiddler will show the image.
{{{<<view fieldname image>>}}}
will render the value of the tiddler field 'fieldname' as an image. This field can contain a tid
{{{<<image SiteIcon>>}}}
will create an image tag where the tiddler has content type beginning image and not ending +xml
will attempt to create svg object in other scenarios
{{{<<image /photos/x.jpg>>}}}
will create an image tag with src /photos/x.jpg as long as there is not a tiddler called /photos/x.jpg in 
which case it will render that tiddler as an image. Note for the case of svg files it will attempt to render as an svg if possible via the image
tag. It doesn't embed the svg in the dom for security reasons as svg code can contain javascript.
!Code
***/
//{{{
(function($) {

var macro = config.macros.image = {
	shim: "/bags/common/tiddlers/shim",
	ieVersion: config.browser.isIE ? parseInt(config.browser.ieVersion[1], 10) : false,
	svgns: "http://www.w3.org/2000/svg",
	xlinkns: "http://www.w3.org/1999/xlink", 
	svgAvailable: document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"),
	_fixPrefix: 1,
	_external_cache: {},
	_image_tag_cache: {},
	_image_dimensions: {},
	locale: {
		badImage: "This image cannot be displayed."
	},
	handler: function(place, macroName, params, wikifier, paramString, tiddler){
		var imageSource = params[0];
		// collect named arguments
		var args = macro.getArguments(paramString, params);
		this.renderImage(place, imageSource, args);
	},
	init: function() {
		var startupImages = store.getTaggedTiddlers("systemImage");
		var place = $("<div />").attr("id", "systemImageArea").appendTo("body").hide()[0];
		for(var i = 0; i < startupImages.length; i++) {
			var image = startupImages[i];
			macro.renderImage(place, image.title, { idPrefix: "" });
		}
		var data = new Image();
		data.onload = function() {
			// note ie 8 only supports data uris up to 32k so cannot be relied on
			macro.supportsDataUris = this.width != 1 || this.height != 1 ? false : true;
			macro.supportsDataUris = macro.ieVersion && macro.ieVersion < 9 ? false : macro.supportsDataUris;
		};
		data.onerror = data.onload;
		data.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
	},
	refreshImage: function(src) {
		var elements = macro._image_tag_cache[src] ? macro._image_tag_cache[src] : [];
		if(macro._image_dimensions[src]) {
			macro._image_dimensions[src] = false;
		}
		for(var i = 0; i < elements.length; i++) {
			var el = $(elements[i]);
			var newSrc = "%0?nocache=%1".format(src, Math.random());
			el.attr("src", newSrc); // force reload
		}
	},
	isBinaryImageType: function(contentType) {
		return (contentType && contentType.indexOf("image") === 0 &&
			contentType.indexOf("+xml") != contentType.length - 4) ? true : false;
	},
	isImageTiddler: function(tiddler) {
		return macro.isSVGTiddler(tiddler) || macro.isBinaryImageTiddler(tiddler);
	},
	isSVGTiddler: function(tiddler) {
		var type = tiddler ? tiddler.fields['server.content-type'] : false;
		return type == "image/svg+xml";
	},
	isBinaryImageTiddler: function(tiddler) {
		return macro.isBinaryImageType(tiddler.fields['server.content-type']);
	},
	renderImage: function(place, imageSource, options) {
		var imageTiddler = store.getTiddler(imageSource);
		var container;
		var classes = ["image"];
		if(options.link) {
			classes = classes.concat(["imageLink", "externalLink"]);
			container = $("<a />").attr("href", options.link).appendTo(place)[0];
		} else if(options.tiddlyLink) {
			classes.push("imageLink");
			container = createTiddlyLink(place, options.tiddlyLink, false);
		} else {
			container = $("<span />").appendTo(place)[0];
		}
		$(container).addClass(classes.join(" "));

		options = options ? options : {};
		if(imageTiddler && macro.isBinaryImageTiddler(imageTiddler)) { // handle the case where we have an image url
			return macro._renderBinaryImageTiddler(container, imageTiddler, options);
		} else if(imageTiddler){ // handle the case where we have a tiddler
			return macro._renderSVGTiddler(container, imageTiddler, options);
		} else { // we have a string representing a url
			return macro._renderBinaryImageUrl(container, imageSource, options);
		}
	},
	_renderAlternateText: function(container, options) {
		var img;
		var src = options.src || "";
		if(options.width && options.height) {
			img = $("<img />").attr("src", src).addClass("svgImageText").attr("width", options.width).
				attr("height", options.height).appendTo(container);
		}
		var alt = options.alt;
		if(img && alt) {
			img.attr("alt", alt).attr("title", alt);
		} else if(alt) {
			$(container).addClass("svgImageText").text(alt);
		}
		macro._image_tag_cache[src] = img;
	},
	_renderSVGTiddler: function(place, tiddler, options) {
		if(!options) {
			options = {};
		}
		merge(options, { tiddler: tiddler, fix: true});

		if(macro.svgAvailable) {
			this._importSVG(place, options); // display the svg
		} else if(options.altImage) {
			var image = options.altImage;
			delete options.altImage;
			this._renderBinaryImageUrl(place, image, options);
		} else {
			this._renderAlternateText(place, options); // instead of showing the image show the alternate text.
		}
	},
	_renderBinaryImageTiddler: function(place, tiddler, options) {
		var resourceURI;
		var fields = tiddler.fields;
		if(fields["server.type"] == "tiddlyweb") { // construct an accurate url for the resource
			resourceURI = "%0/%1/tiddlers/%2".format(config.defaultCustomFields["server.host"],
				fields["server.workspace"], encodeURI(fields["server.title"]));
		} else { // guess the url for the resource
			resourceURI = tiddler.title;
		}
		var ctype = fields["server.content-type"] || tiddler.type;
		var text = tiddler.text;
		if(macro.supportsDataUris && ctype && text.indexOf("<html") == -1) {
			var uri = "data:%0;base64,%1".format(ctype, text);
			options.src = resourceURI;
			return macro._renderBinaryImageUrl(place, uri, options);
		} else if(options.src) {
			return macro._renderBinaryImageUrl(place, options.src, options);
		} else {
			return macro._renderBinaryImageUrl(place, resourceURI, options);
		}
	},
	_renderImageTag: function(container, src, width, height, options) {
		var img;
		img = $("<img />").appendTo(container);
		if(height) {
			img.attr("height", height);
		}
		if(width) {
			img.attr("width", width);
		}
		if(macro.ieVersion && macro.ieVersion < 7 && macro.shim && options.ie6png) {
			$(img).css({width: userW, height: userH,
					filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%0', sizingMethod='scale')".format(src)
				}).attr("src", macro.shim);
		} else {
			img.attr("src", src);
		}
		if(!macro._image_tag_cache[options.srcUrl]) {
			macro._image_tag_cache[options.srcUrl] = [];
		}
		img = $(img).addClass(options.imageClass)[0];
		macro._image_tag_cache[options.srcUrl].push(img);
		return img;
	},
	_getDimensions: function(realDimensions, reqDimensions, preserve) {
		var w = realDimensions.width;
		var h = realDimensions.height;
		var reqh = reqDimensions.height;
		var reqw = reqDimensions.width;
		var finalw = w, finalh = h;
		var ratiow = reqw / w, ratioh = reqh / h;
		var scaledw = ratioh * w;
		var scaledh = ratiow * h;
		if(!reqw && reqh) {
			finalw = scaledw;
			finalh = reqh;
		} else if(reqw && !reqh) {
			finalw = reqw;
			finalh = scaledh;
		} else if(reqh && reqw) {
			var preserveWidth = w > h ? true : false;
			if(preserve) {
				if(preserveWidth && scaledh < reqh) {
					finalh = scaledh;
					finalw = reqw;
				} else {
					finalh = reqh;
					finalw = scaledw;
				}
			} else {
				finalw = reqw;
				finalh = reqh;
			}
		}
		return { width: parseInt(finalw, 10), height: parseInt(finalh, 10) };
	},
	_renderBinaryImageUrl: function(container, src, options) {
		var srcUrl = options.src ? options.src : src;
		srcUrl = srcUrl.indexOf("/") === -1 ? "/%0".format(srcUrl) : srcUrl; // for IE. 
		var image_dimensions = macro._image_dimensions[srcUrl];
		var image = new Image(); // due to weird scaling issues where you use just a width or just a height
		var createImageTag = function(dimensions, error) {
			if(error) {
				var altImage = options.altImage;
				if(altImage) {
					delete options.altImage;
					macro._renderBinaryImageUrl(container, altImage, options);
				} else {
					options.src = src;
					macro._renderAlternateText(container, options);
				}
			} else {
				var dim = macro._getDimensions(dimensions, { 
					width: options.width, height: options.height }, options.preserveAspectRatio);
				options.srcUrl = srcUrl;
				macro._renderImageTag(container, src, dim.width, dim.height, options);
			}
		};

		if(!image_dimensions) {
			image.onload = function() {
				var dimensions = { width: image.width, height: image.height};
				macro._image_dimensions[srcUrl] = dimensions;
				createImageTag(dimensions);
			};
			image.onerror = function() {
				createImageTag(null, true);
			};
			image.src = src;
		} else {
			createImageTag(image_dimensions);
		}
	},
	_generateIdPrefix: function(){
		return "twsvgfix_" + (this._fixPrefix++).toString() + "_";
	},
	_fixSVG: function(childNodes, idPrefix) {
		var urlPattern = /url\(\#([^\)]*)\)*/ig;
		var fixes = [
		{ attr: "id", pattern: /^(.*)$/ig },
		{ attr: "href", namespace: macro.xlinkns, pattern: /^#(.*)$/ig }
		];
		var url_fixes = ["filter", "fill", "mask", "stroke", "style"];
		for(var i = 0; i < url_fixes.length; i++) {
			fixes.push({ attr: url_fixes[i], pattern: urlPattern });
		}
		for(var t = 0; t < childNodes.length; t++) {
			var node = childNodes[t];
			for(var a = 0; a < fixes.length; a++) {
				var fix = fixes[a];
				var attr = fix.attr;
				var ns = fix.namespace || "";
				if(node.hasAttributeNS && node.hasAttributeNS(ns, attr)) {
					var v = node.getAttributeNS(ns, attr);
					fix.pattern.lastIndex = 0;
					var match = fix.pattern.exec(v);
					if(match) {
						// Make sure replacement string doesn't contain any single dollar signs
						var toReplace = match[1];
						if(toReplace.indexOf(idPrefix) !== 0 && toReplace.indexOf("twglobal_") !== 0) {
							var replacement = (idPrefix + toReplace).replace("$", "$$$$"); 
							v = v.replace(match[1], replacement);
						}
						node.setAttributeNS(ns, attr,v);
					}
				}
			}
			var children = node.childNodes;
			if(children.length > 0) {
				this._fixSVG(children, idPrefix);
			}
		}
	},
	_importSVG: function(place, options){
		options = options ? options : {};
		var svgDoc, tiddlerText = options.tiddler.text;
		if (window.DOMParser) {
			svgDoc = new DOMParser().parseFromString(tiddlerText, "application/xml").documentElement;
			var idPrefix = options.idPrefix || this._generateIdPrefix();
			this._fixSVG([svgDoc], idPrefix);
			var el = document.importNode(svgDoc, true);
			var svgHolder = document.createElementNS(macro.svgns,"svg");
			var width = options.width;
			var height = options.height;
			if(width || height) {
				if(width && height) { // set view box of containing svg element based on the svg viewbox and width and height.
					var viewBox = el.getAttribute("viewBox");
					var topLeft = "0 0";
					if(viewBox) {
						topLeft = viewBox.replace(/([0-9]*) +([0-9]*) +([0-9]*) +([0-9]*) */gi,"$1 $2");
					}
					svgHolder.setAttributeNS(macro.svgns, "viewBox", "0 0 %0 %1".format(width, height));
				} else {
					if(!width) {
						width = el.getAttribute("width");
					}
					if(!height) {
						height = el.getAttribute("height");
					}
				}
				svgHolder.setAttribute("width", width);
				svgHolder.setAttribute("height", height);

				el.setAttribute("width", "100%");
				el.setAttribute("height", "100%");
				svgHolder.setAttribute("class", "svgImage svgIcon %0".format(options.imageClass || ""));
				svgHolder.appendChild(el);
				place.appendChild(svgHolder);
			}
			else {
				var existing = el.className ? el.className.baseVal : "";
				el.setAttribute("class","svgImage %0".format(existing));
				place.appendChild(el);
			}
			// if a tiddler attribute is set this is read as a link
			$("[tiddler], [tiddlyLink]", place).attr("refresh", "link").click(function(ev) {
				var tiddler = $(ev.target).attr("tiddlyLink");
				if(tiddler) {
					story.displayTiddler(ev.target, tiddler);
				}
			});
		}
	},
	getArguments: function(paramString, params) {
		var args = paramString.parseParams("name", null, true, false, true)[0];
		var options = {};
		for(var id in args) {
			if(true) {
				var p = args[id];
				if(id == "def") {
					options[id] = p;
				} else {
					options[id] = p[0];
				}
			}
		}
		var width = isNaN(params[1]) ? false : parseInt(params[1], 10);
		var height = isNaN(params[2]) ? false : parseInt(params[2], 10);

		options.width = macro.lookupArgument(options, "width", width);
		options.height = macro.lookupArgument(options, "height", height);
		options.preserveAspectRatio = args.preserveAspectRatio && 
			args.preserveAspectRatio[0] == "yes" ? true : false;
		options.tiddlyLink = macro.lookupArgument(options, "tiddlyLink", false);
		options.link = macro.lookupArgument(options, "link", false);
		return options;
	},
	lookupArgument: function(args, id, ifEmpty) {
		return args[id] ? args[id] : ifEmpty;
	}
};

// update views
var _oldwikifiedview = config.macros.view.views.wikified;
// update wikifier to check tiddler type before rendering
merge(config.macros.view.views, {
	wikified: function(value, place, params, wikifier, paramString, tiddler) {
		if(macro.isImageTiddler(tiddler) && params[0] == "text") {
			var newplace = $("<div />").addClass("wikifiedImage").appendTo(place)[0];
			macro.renderImage(newplace, tiddler.title, { alt: macro.locale.badImage });
		} else {
			_oldwikifiedview.apply(this, arguments);
		}
	},
	image: function(value, place, params, wikifier, paramString, tiddler) {
		// a field can point to another tiddler whereas text is the current tiddler.
		var title = params[0] == "text" ? tiddler.title : value;
		var args = macro.getArguments(paramString, params);
		macro.renderImage(place, title, args);
	}
});
config.shadowTiddlers.StyleSheetImageMacro = [".wikifiedImage svg, .wikifiedImage .image { width: 80%; }",
	".svgImageText { background-color:[[ColorPalette::Error]]; color:#ddd; display: inline-block; }",
	"span.svgImageText { display: inline-block; overflow: hidden; }"
].join("");
store.addNotification("StyleSheetImageMacro", refreshStyles);

})(jQuery);
//}}}
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
//}}}
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Version|1.6.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|Insert Javascript executable code directly into your tiddler content.|

''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Usage
<<<
When installed, this plugin adds new wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be treated as embedded javascript and executed each time the tiddler is rendered.

''Deferred execution from an 'onClick' link''
By including a {{{label="..."}}} parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered.  You may also include a {{{title="..."}}} parameter to specify the 'tooltip' text that will appear whenever the mouse is moved over the onClick link text

''External script source files:''
You can also load javascript from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}).  This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins.  The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.

''Display script source in tiddler output''
By including the keyword parameter "show", in the initial {{{<script>}}} marker, the plugin will include the script source code in the output that it displays in the tiddler.

''Defining javascript functions and libraries:''
Although the external javascript file is loaded while the tiddler content is being rendered, any functions it defines will not be available for use until //after// the rendering has been completed.  Thus, you cannot load a library and //immediately// use it's functions within the same tiddler.  However, once that tiddler has been loaded, the library functions can be freely used in any tiddler (even the one in which it was initially loaded).

To ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that will be rendered as soon as your TiddlyWiki document is opened.  For example, you could put your {{{<script src="..."></script>}}} syntax into a tiddler called LoadScripts, and then add {{{<<tiddler LoadScripts>>}}} in your MainMenu tiddler.

Since the MainMenu is always rendered immediately upon opening your document, the library will always be loaded before any other tiddlers that rely upon the functions it defines.  Loading an external javascript library does not produce any direct output in the tiddler, so these definitions should have no impact on the appearance of your MainMenu.

''Creating dynamic tiddler content''
An important difference between this implementation of embedded scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document:
* In a typical web document, you use the document.write() function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.
* However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and completely replaces the entire ~TiddlyWiki document in your browser window.
* To allow these scripts to work unmodified, the plugin automatically converts all occurences of document.write() so that the output is inserted into the tiddler content instead of replacing the entire ~TiddlyWiki document.

If your script does not use document.write() to create dynamically embedded content within a tiddler, your javascript can, as an alternative, explicitly return a text value that the plugin can then pass through the wikify() rendering engine to insert into the tiddler display.  For example, using {{{return "thistext"}}} will produce the same output as {{{document.write("thistext")}}}.

//Note: your script code is automatically 'wrapped' inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler.  To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.//

''Accessing the ~TiddlyWiki DOM''
The plugin provides one pre-defined variable, 'place', that is passed in to your javascript code so that it can have direct access to the containing DOM element into which the tiddler output is currently being rendered.

Access to this DOM element allows you to create scripts that can:
* vary their actions based upon the specific location in which they are embedded
* access 'tiddler-relative' information (use findContainingTiddler(place))
* perform direct DOM manipulations (when returning wikified text is not enough)
<<<
!!!!!Examples
<<<
an "alert" message box:
><script show>
	alert('InlineJavascriptPlugin: this is a demonstration message');
</script>
dynamic output:
><script show>
	return (new Date()).toString();
</script>
wikified dynamic output:
><script show>
	return "link to current user: [["+config.options.txtUserName+"]]";
</script>
dynamic output using 'place' to get size information for current tiddler:
><script show>
   if (!window.story) window.story=window;
   var title=story.findContainingTiddler(place).id.substr(7);
   return title+" is using "+store.getTiddlerText(title).length+" bytes";
</script>
creating an 'onclick' button/link that runs a script:
><script label="click here" title="clicking this link will show an 'alert' box" show>
   if (!window.story) window.story=window;
   alert("Hello World!\nlinktext='"+place.firstChild.data+"'\ntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");
</script>
loading a script from a source url:
>http://www.TiddlyTools.com/demo.js contains:
>>{{{function demo() { alert('this output is from demo(), defined in demo.js') } }}}
>>{{{alert('InlineJavascriptPlugin: demo.js has been loaded'); }}}
><script src="demo.js" show>
	return "loading demo.js..."
</script>
><script label="click to execute demo() function" show>
	demo()
</script>
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''InlineJavascriptPlugin'' (tagged with <<tag systemConfig>>)
<<<
!!!!!Revision History
<<<
''2007.02.19 [1.6.0]'' added support for title="..." to specify mouseover tooltip when using an onclick (label="...") script
''2006.10.16 [1.5.2]'' add newline before closing '}' in 'function out_' wrapper.  Fixes error caused when last line of script is a comment.
''2006.06.01 [1.5.1]'' when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly
''2006.04.19 [1.5.0]'' added 'show' parameter to force display of javascript source code in tiddler output
''2006.01.05 [1.4.0]'' added support 'onclick' scripts.  When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked.  'place' value is set to match the clicked button/link element.
''2005.12.13 [1.3.1]'' when catching eval error in IE, e.description contains the error text, instead of e.toString().  Fixed error reporting so IE shows the correct response text.  Based on a suggestion by UdoBorkowski
''2005.11.09 [1.3.0]'' for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content.  Based on a suggestion by BradleyMeck
''2005.11.08 [1.2.0]'' handle loading of javascript from an external URL via src="..." syntax
''2005.11.08 [1.1.0]'' pass 'place' param into scripts to provide direct DOM access 
''2005.11.08 [1.0.0]'' initial release
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]
<<<
!!!!!Code
***/
//{{{
version.extensions.inlineJavascript= {major: 1, minor: 6, revision: 0, date: new Date(2007,2,19)};

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

	handler: function(w) {
		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
		lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			if (lookaheadMatch[1]) { // load a script library
				// make script tag, set src, add to body to execute, then remove for cleanup
				var script = document.createElement("script"); script.src = lookaheadMatch[1];
				document.body.appendChild(script); document.body.removeChild(script);
			}
			if (lookaheadMatch[5]) { // there is script code
				if (lookaheadMatch[4]) // show inline script code in tiddler output
					wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
				if (lookaheadMatch[2]) { // create a link to an 'onclick' script
					// add a link, define click handler, save code in link (pass 'place'), set link attributes
					var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",lookaheadMatch[2]);
					link.onclick=function(){try{return(eval(this.code))}catch(e){alert(e.description?e.description:e.toString())}}
					link.code="function _out(place){"+lookaheadMatch[5]+"\n};_out(this);"
					link.setAttribute("title",lookaheadMatch[3]?lookaheadMatch[3]:"");
					link.setAttribute("href","javascript:;");
					link.style.cursor="pointer";
				}
				else { // run inline script code
					var code="function _out(place){"+lookaheadMatch[5]+"\n};_out(w.output);"
					code=code.replace(/document.write\(/gi,'place.innerHTML+=(');
					try { var out = eval(code); } catch(e) { out = e.description?e.description:e.toString(); }
					if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
				}
			}
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
		}
	}
} )
//}}}
/***
|Name:|InstantTimestampPlugin|
|Description:|A handy way to insert timestamps in your tiddler content|
|Version:|1.0.10a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#InstantTimestampPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
If you enter {ts} in your tiddler content (without the spaces) it will be replaced with a timestamp when you save the tiddler. Full list of formats:
* {ts} or {t} -> timestamp
* {ds} or {d} -> datestamp
* !ts or !t at start of line -> !!timestamp
* !ds or !d at start of line -> !!datestamp
(I added the extra ! since that's how I like it. Remove it from translations below if required)
!!Notes
* Change the timeFormat and dateFormat below to suit your preference.
* See also http://mptw2.tiddlyspot.com/#AutoCorrectPlugin
* You could invent other translations and add them to the translations array below.
***/
//{{{

config.InstantTimestamp = {

  // adjust to suit
  timeFormat: 'DD/0MM/YY 0hh:0mm',
  dateFormat: 'DD/0MM/YY',

  translations: [
    [/^!ts?$/img,  "'!!{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
    [/^!ds?$/img,  "'!!{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"],

    // thanks Adapted Cat
    [/\{ts?\}(?!\}\})/ig,"'{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
    [/\{ds?\}(?!\}\})/ig,"'{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"]

  ],

  excludeTags: [
    "noAutoCorrect",
    "noTimestamp",
    "html",
    "CSS",
    "css",
    "systemConfig",
    "systemConfigDisabled",
    "zsystemConfig",
    "Plugins",
    "Plugin",
    "plugins",
    "plugin",
    "javascript",
    "code",
    "systemTheme",
    "systemPalette"
  ],

  excludeTiddlers: [
    "StyleSheet",
    "StyleSheetLayout",
    "StyleSheetColors",
    "StyleSheetPrint"
    // more?
  ]

};

TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {

  tags = tags ? tags : []; // just in case tags is null
  tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags;
  var conf = config.InstantTimestamp;

  if ( !tags.containsAny(conf.excludeTags) && !conf.excludeTiddlers.contains(newTitle) ) {

    var now = new Date();
    var trans = conf.translations;
    for (var i=0;i<trans.length;i++) {
      newBody = newBody.replace(trans[i][0], eval(trans[i][1]));
    }
  }

  // TODO: use apply() instead of naming all args?
  return this.saveTiddler_mptw_instanttimestamp(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
}

// you can override these in StyleSheet
setStylesheet(".ts,.ds { font-style:italic; }","instantTimestampStyles");

//}}}
/***
|''Name''|JashMacro|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Author''|[[Billy Reisinger|http://www.billyreisinger.com]]|
|''Contributor''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#JashMacro]]|
|''License''|[[GNU General Public License|http://www.gnu.org/licenses/gpl.html]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|JavaScript shell console|
!Notes
This macro is entirely based upon (and dependent on) [[Jash|http://www.billyreisinger.com/jash/]] by [[Billy Reisinger|http://www.billyreisinger.com]].
It dynamically loads the required code from the online resource.
!Usage
{{{
<<Jash [label] [tooltip] [class] [access key]>>
}}}
<<Jash>>
!Revision History
!!v0.1 (2007-12-10)
* initial release
!Code
***/
//{{{
config.macros.Jash = {
	label: "Jash",
	prompt: "open Jash",
	buttonClass: "",
	accessKey: ""
};

config.macros.Jash.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var label = params[0] || this.label;
	var prompt = params[1] || this.prompt;
	var buttonClass = params[2] || this.buttonClass;
	var accessKey = params[3] || this.accessKey;
	createTiddlyButton(place, label, prompt, config.macros.Jash.toggle, buttonClass, null, accessKey);
}

config.macros.Jash.toggle = function(place, macroName, params, wikifier, paramString, tiddler) {
	document.body.appendChild(document.createElement("script")).src = "http://www.billyreisinger.com/jash/source/latest/Jash.js";
}
//}}}
/***
|''Name''|JashMacro|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Author''|[[Billy Reisinger|http://www.billyreisinger.com]]|
|''Contributor''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#JashMacro]]|
|''License''|[[GNU General Public License|http://www.gnu.org/licenses/gpl.html]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|JavaScript shell console|
!Notes
This macro is entirely based upon [[Jash|http://www.billyreisinger.com/jash/]] by [[Billy Reisinger|http://www.billyreisinger.com]].
!Usage
{{{
<<Jash [label] [tooltip] [class] [access key]>>
}}}
<<Jash>>
!Revision History
!!v0.1 (2007-12-10)
* initial release
!Code
***/
//{{{
config.macros.Jash = {
	label: "Jash",
	prompt: "open Jash",
	buttonClass: "",
	accessKey: ""
};

config.macros.Jash.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var label = params[0] || this.label;
	var prompt = params[1] || this.prompt;
	var buttonClass = params[2] || this.buttonClass;
	var accessKey = params[3] || this.accessKey;
	createTiddlyButton(place, label, prompt, config.macros.Jash.toggle, buttonClass, null, accessKey);
	config.macros.Jash.toggle(); // DEBUG: ugly hack to prevent Jash from being launched on startup
}

config.macros.Jash.toggle = function(place, macroName, params, wikifier, paramString, tiddler) {
	if("jash" in window) {
		window.jash.close();
	} else {
		window.jash = new Jash();
		window.jash.main();
	}
}

/*
** Jash.css
** http://www.billyreisinger.com/jash/source/latest/Jash.css
*/
config.shadowTiddlers.StyleSheetJash = "#JashParent {\n"+
 "	width: 581px;\n"+
 "	height: 450px;\n"+
 "	border: 1px solid gray;\n"+
 "	color: black;\n"+
 "	z-index: 10000;\n"+
 "	overflow: hidden;\n"+
 "	background: #ccc;\n"+
 "	opacity: 0.90;\n"+
 "	filter: alpha(opacity=90);\n"+
 "	position: absolute;\n"+
 "	left: 25%;\n"+
 "	color: black;\n"+
 "	font-family: monospace;\n"+
 "	margin: 0;\n"+
 "}\n"+
 "#JashParent div {\n"+
 "	margin: 0;\n"+
 "}\n"+
 "#JashParent a, #JashParent a:visited, #JashParent a:active, #JashParent a:hover {\n"+
 "	text-decoration: none;\n"+
 "	color: black;\n"+
 "}\n"+
 ".transparentMode {\n"+
 "	opacity: 0.20 !important;\n"+
 "	filter: alpha(opacity=20) !important;\n"+
 "}\n"+
 "#JashDragBar {\n"+
 "	BACKGROUND: gray;\n"+
 "	CURSOR: move;\n"+
 "	COLOR: white;\n"+
 "	font-family: monospace;\n"+
 "	font-weight: bold;\n"+
 "	text-indent: 4px;\n"+
 "	font-size: 14px;\n"+
 "	HEIGHT: 25px;\n"+
 "	TEXT-ALIGN: left;\n"+
 "	overflow: hidden;\n"+
 "	border: 1px outset white;\n"+
 "}\n"+
 ".JashXButton {\n"+
 "    border: 1px solid white;\n"+
 "    color: white !important;\n"+
 "    position: absolute;\n"+
 "    background: #bbb;\n"+
 "    width: 20px; \n"+
 "    text-align: center;\n"+
 "    display: block;\n"+
 "    right: 3px; _right: 1px;\n"+
 "    top: 4px; _top: 1px;\n"+
 "    font-family: Arial sans-serif;\n"+
 "    font-size: 18px;\n"+
 "    cursor: pointer;\n"+
 "}\n"+
 "a.JashXButton:hover {\n"+
 "	background: #ddd; \n"+
 "}\n"+
 "#JashTextareaWrap {\n"+
 "	width: 100%;\n"+
 "	_height: 420px;\n"+
 "}\n"+
 "html>body #JashTextareaWrap {\n"+
 "	height: 100%;\n"+
 "}\n"+
 "#JashOutput {\n"+
 "	border: 2px inset white;\n"+
 "	FONT-SIZE: 10px;\n"+
 "	font-family: \"Lucida Console\", monaco, monospace;\n"+
 "	BACKGROUND: black;\n"+
 "	width: 99%;\n"+
 "	COLOR: lightgreen;\n"+
 "	PADDING: 2px;\n"+
 "	height: 60%;\n"+
 "	height: expression(parseInt(this.parentNode.parentNode.offsetHeight * (3/5)) + 'px');\n"+
 "	\n"+
 "}\n"+
 "#JashInput {\n"+
 "	padding: 2px;\n"+
 "	WIDTH: 99%;\n"+
 "	border: 2px inset white;\n"+
 "	HEIGHT: 25%;\n"+
 "	font-family: monospace;\n"+
 "	font-size: 11px;\n"+
 "	height: expression(parseInt(this.parentNode.parentNode.offsetHeight * (3/13)) + 'px');\n"+
 "}\n"+
 "#JashParent .cssEntry {\n"+
 "	background: lightgreen;\n"+
 "	font-size: 11px;\n"+
 "	font-family: monospace;\n"+
 "}\n"+
 "#JashBottomBar {\n"+
 "	BACKGROUND: #ccc;\n"+
 "	POSITION: relative;\n"+
 "	HEIGHT: 20px;\n"+
 "	overflow: hidden;\n"+
 "	margin-top: 2px;\n"+
 "}\n"+
 "#JashBottomBar a {\n"+
 "	HEIGHT: 14px;\n"+
 "	font-size: 9px;\n"+
 "	font-weight: normal;\n"+
 "	font-family: arial;\n"+
 "	float: left;\n"+
 "	padding: 4px;\n"+
 "	background: #eee;\n"+
 "	cursor: pointer;\n"+
 "	border: 1px outset white;\n"+
 "	margin-right: 1px;\n"+
 "}\n"+
 "#JashBottomBar a:hover {\n"+
 "	padding-top: 3px;\n"+
 "	padding-bottom: 5px;\n"+
 "	background-color: white;\n"+
 "}\n"+
 "#JashBottomBar a:active, #JashBottomBar a:focus {\n"+
 "	padding-top: 5px;\n"+
 "	padding-bottom: 3px;\n"+
 "	background-color: #ddd;\n"+
 "}\n"+
 "#JashResizeButton {\n"+
 "	BORDER: 1px solid gray;\n"+
 "	BACKGROUND: #eee;\n"+
 "	WIDTH: 17px;\n"+
 "	height: 17px;\n"+
 "	line-height: 0;\n"+
 "	CURSOR: move;\n"+
 "	position: absolute;\n"+
 "	bottom: 0px;\n"+
 "	right: 0px;\n"+
 "	z-index: 2000;\n"+
 "}"
store.addNotification("StyleSheetJash", refreshStyles);

/*
** Jash.js
** http://www.billyreisinger.com/jash/source/latest/Jash.js
*/

function Jash(){this.jashRoot="http://www.billyreisinger.com/jash/source/latest/";this.domGetElFunctions={id:new Array("document.getElementById","$"),className:new Array("getElementsByClassName","$C")};var line="-------------------------------------------------";var _null="nooutput";this.revision="$Revision: 1.14 $".replace(/(\$|[A-Za-z]|\s|:)/g,'');this.version="$Name: REL_1_35_7 $".replace(/\$|Name:|\s|REL_/g,'').replace(/_/g,'.');this.versionDate="$Date: 2007/11/16 03:24:54 $";this.main=function(){this.browser=this.returnBrowserType();this.lineNumber=0;this.mainBlock;this.output=document.getElementById("JashOutput");this.input;this.outputHistory=new Array();this.cssEvalFlag=false;this.innerHtmlInspection=false;this.accessKeyText=this.getAccessKeyText();this.defaultText="Jash, v"+this.version+"\nEnter \"jash.help()\" for a list of commands.\n";this.cls=this.clear;this.tabIndexIndex=0;this.currentNode={};this.tips=["Did you know?\nThe DOM Inspector will automatically put\n an element with an ID in the input field for you.","Did you know?\nYou can tie this script into your own to jash scripts. Use 'jash.methodName' anywhere\n in your scripts, and pull\n up this window before executing to see\n the results.","Did you know?\nUse jash.stopWatch.start() and jash.stopWatch.stop() to\n time execution speeds! Handy for optimization.","Did you know?\nPress TAB to complete a function, method, or property name.\n If more than one match is found, a list of possible\n matches will appear.","Did you know?\nYou can use jash.show() to show a list of the names\nand types of an object's members.\nOn the other hand, jash.dump will show names and\n_values_ of an object's members.","Whoa ---- you can now tab-complete HTML element ids after typing document.getElementsById(' (or the '$' shorthand if using Prototype).  This also works with class names (i.e. document.getElementsByClassName)"]
this.defaultText+=line+"\n"+this.tips[(parseInt((Math.random()*10)%this.tips.length))]+"\n"+line+"\n";if(this.returnBrowserType()!="sa"){this.stylesheet=document.body.appendChild(document.createElement('link'));}else{this.stylesheet=document.getElementsByTagName("head")[0].appendChild(document.createElement("link"));}
this.stylesheet.type='text/css';this.stylesheet.rel='stylesheet';this.stylesheet.href=this.jashRoot+'Jash.css';this.create();Jash.TabComplete.prototype=this;this.tabComplete=new Jash.TabComplete();Jash.Evaluator.prototype=this;this.evaluation=new Jash.Evaluator();this.history=new Jash.History();var _self=this;window.setTimeout(function(){_self.input.focus();},500);if(typeof event!="undefined")delete event;}
this.returnBrowserType=function(){if(window.navigator.userAgent.toLowerCase().indexOf("opera")!=-1){return"op";}
if(window.navigator.userAgent.toLowerCase().indexOf("msie")!=-1){return"ie";}
if(window.navigator.userAgent.toLowerCase().indexOf("firefox")!=-1){return"ff";}
if(window.navigator.userAgent.toLowerCase().indexOf("safari")!=-1){return"sa";}}
this.returnOsType=function(){var ua=window.navigator.userAgent.toLowerCase();if(ua.indexOf("macintosh")!=-1){return"mac";}else if(ua.indexOf("windows")!=-1){return"win";}else if(ua.indexOf("linux i686")!=-1){return"linux";}}
this.getAccessKeyText=function(){var txt;var agt=this.returnOsType();switch(this.browser){case"ie":txt="Alt";break;case"ff":if(agt=="mac"){txt="Ctrl";}else if(agt=="linux"){txt="Alt";}else{txt="Alt-Shift";}
break;case"op":txt="Shift-Esc";break;case"sa":if(agt=="mac"){txt="Ctrl";}else{txt="Alt";}
break;default:txt="Alt";break;}
return txt;}
this.print=function(text,clear,suppressLineNumbers,autoscroll){clear=(typeof clear!="undefined")?clear:false;autoscroll=(typeof autoscroll!="undefined")?autoscroll:true;if(this.output==null||document.getElementById("JashParent")==null){this.create();this.output=document.getElementById("JashOutput");this.mainBlock=document.getElementById("JashParent");}
if(clear){this.clear();}
if(text!=""){if(typeof suppressLineNumbers!="undefined"&&!suppressLineNumbers){this.output.value+=this.lineNumber+". ";}
this.output.value+=text+"\n";if(autoscroll){this.output.scrollTop=this.output.scrollHeight;}
this.lineNumber++;}
return _null;}
this.show=function(obj){this.print(line,false,true);var out="";this.lineNumber=0;for(var p in obj){if(typeof obj[p]=="function"){var t=obj[p].toString();t=t.replace(/[\x0A\x0D]/g,"").replace(/\s+/g,"").replace(/\{.+\}/g,"{ ... }");t=t.replace(p,"");t=p+": "+t;}else{t=p+": "+typeof obj[p];}
out+=++this.lineNumber+". "+t+"\n";}
this.print(out,false,true);this.print(line,false,true);this.output.scrollTop=this.output.scrollHeight;return _null;}
this.dump=function(obj){if(typeof obj=="string"){this.print(obj);}else{this.print(line,false,true);var out=new Array();if(typeof obj.push=="undefined"){for(var th in obj){out.push(++this.lineNumber+". "+th+" = "+obj[th]);}}else{for(var i=0;i<obj.length;i++){out.push(++this.lineNumber+". "+obj[i]);}}
this.print(out.join("\n"),false,true);this.print(line,false,true);this.output.scrollTop=this.output.scrollHeight;}
return _null;}
this.clear=function(){this.outputHistory.push(this.output.value);this.output.value="";this.input.focus();return _null;}
this.showOutputHistory=function(){this.outputHistory.push(this.output.value);this.dump(this.outputHistory);}
this.assignInputKeyEvent=function(keyCode){if(keyCode==13){this.evaluation.evaluate(this.input.value);this.input.value="";return false;}else if(keyCode==38){if(this.browser!="op"){this.input.value=this.history.getPreviousInput();}
return false;}else if(keyCode==40){if(this.browser!="op"){this.input.value=this.history.getNextInput();}
return false;}else if(keyCode==9){this.tabComplete.tabComplete();return false;}}
this.getXBrowserYOffset=function(){var y;if(self.pageYOffset){y=self.pageYOffset;}else if(document.documentElement&&document.documentElement.scrollTop){y=document.documentElement.scrollTop;}else if(document.body){y=document.body.scrollTop;}
return y;}
this.getMouseXY=function(e){var tempX=0
var tempY=0
if(window.event){if(document.documentElement&&document.documentElement.scrollTop){tempX=window.event.clientX+document.documentElement.scrollLeft;tempY=window.event.clientY+document.documentElement.scrollTop;}else{tempX=window.event.clientX+document.body.scrollLeft;tempY=window.event.clientY+document.body.scrollTop;}}else{tempX=e.pageX;tempY=e.pageY;}
return{x:tempX,y:tempY};}
this.getDimensions=function(el){var dims={}
if(document.all){dims.x=el.offsetWidth;dims.y=el.offsetHeight;}else{dims.x=parseInt(document.defaultView.getComputedStyle(el,"").getPropertyValue("width"));dims.y=parseInt(document.defaultView.getComputedStyle(el,"").getPropertyValue("height"));}
return dims;}
this.addEvent=function(obj,eventName,func){if(obj.addEventListener)
return obj.addEventListener(eventName,func,true);else if(obj.attachEvent){obj.attachEvent("on"+eventName,func);return true;}
return false;}
this.findElementPosition=function(obj){var curleft=0;var curtop=0;if(obj.offsetParent){curleft=obj.offsetLeft
curtop=obj.offsetTop
while(obj=obj.offsetParent){curleft+=obj.offsetLeft
curtop+=obj.offsetTop}}
return[curleft,curtop];}
this.create=function(){if(document.getElementsByTagName("frameset").length>0){alert("Jash currently does not support pages with frames.");return;}
var self=this;var debugParent=document.createElement("div");var windowScrollY=0;if(document.documentElement&&document.documentElement.scrollTop){windowScrollY=document.documentElement.scrollTop;}else if(document.body){windowScrollY=document.body.scrollTop}else{windowScrollY=window.scrollY;}
debugParent.style.top=windowScrollY+50+"px";debugParent.id="JashParent";this.addEvent(document,"keydown",function(e){e=(typeof window.event!="undefined")?window.event:e;if(e.keyCode=="27"){if(typeof e.shiftKey=="undefined"||!e.shiftKey){self.close();}}});var textareaWrap=document.createElement("div");textareaWrap.id="JashTextareaWrap";var debugOutput=document.createElement("textarea");debugOutput.id="JashOutput";debugOutput.wrap="off";debugOutput.readOnly="true";debugOutput.value=this.defaultText;var inp=document.createElement("textarea");inp.id="JashInput";var last="";inp.onkeydown=function(e){e=(typeof window.event!="undefined")?window.event:e;return self.assignInputKeyEvent(e.keyCode);}
inp.onkeypress=function(e){e=(typeof window.event!="undefined")?window.event:e;var k=e.keyCode;if(!self.evaluation.cssEvalFlag){if(k==9||k==13||k==38||k==40){if(k!=40&&this.browser!="ie"){return false;}}}else if(k==9){return false;}}
var dragBut=document.createElement("div");dragBut.innerHTML="Jash";dragBut.id="JashDragBar";dragBut.onmousedown=function(e){e=(typeof window.event!="undefined")?window.event:e;var xplus=(typeof e.layerX=="undefined")?e.offsetX:e.layerX;var yplus=(typeof e.layerY=="undefined")?e.offsetY:e.layerY;document.onmousemove=function(e){var coords=self.getMouseXY(e);document.getElementById("JashParent").style.top=coords.y-yplus+"px";document.getElementById("JashParent").style.left=coords.x-xplus+"px";}
return false;}
document.onmouseup=function(){document.onmousemove=null;};dragBut.onclick=function(){return false;}
var xBut=document.createElement("a");xBut.className="JashXButton";xBut.innerHTML="X";xBut.href="#";xBut.onclick=function(){self.close();return false;}
var clearBut=document.createElement("a");clearBut.innerHTML="Clear ("+this.accessKeyText+"-C)";clearBut.accessKey="C";clearBut.className="JashButton";clearBut.onclick=function(){self.clear();return false;}
this.setCrossBrowserAccessKeyFunctionForAnchor(clearBut);var evalBut=document.createElement("a");evalBut.value="Evaluate ("+this.accessKeyText+"-Z)";evalBut.innerHTML="Evaluate ("+this.accessKeyText+"-Z)";evalBut.accessKey="Z";evalBut.className="JashButton";evalBut.title="Evaluate current input ("+this.accessKeyText+"-Z)";evalBut.onclick=function(){self.evaluation.evaluate(inp.value);if(!self.evaluation.cssEvalFlag){inp.value="";}
inp.focus();return false;}
this.setCrossBrowserAccessKeyFunctionForAnchor(evalBut);var helpBut=document.createElement("a");helpBut.innerHTML="Help";helpBut.className="JashButton";helpBut.title="Help: show list of commands (or type jash.help(); )";helpBut.onclick=function(){self.help();}
var domBut=document.createElement("a");domBut.innerHTML="Mouseover DOM ("+this.accessKeyText+"-X)";domBut.title="Mouseover DOM: toggle to turn on/off inspection of document nodes ("+this.accessKeyText+"-X)";domBut.className="JashButton";domBut.accessKey="X";domBut.tabIndex="4";this.domActive=false;domBut.onclick=function(){if(!self.domActive){document.body.onmouseover=function(e){if(typeof e=="undefined"){e=window.event;}
self.showNodes(e);}
self.setButtonVisualActiveState(domBut,"on");self.domActive=true;}else{document.body.onmouseover=function(){}
self.domActive=false;self.setButtonVisualActiveState(domBut,"off");}
return _null;}
this.setCrossBrowserAccessKeyFunctionForAnchor(domBut);var innerHtmlInspectBut=document.createElement("a");innerHtmlInspectBut.innerHTML="innerHTML Dump ("+this.accessKeyText+"-A)";innerHtmlInspectBut.title="innerHTML Inspect: toggle to turn on/off innerHTML inspection of document nodes ("+this.accessKeyText+"-A)";innerHtmlInspectBut.className="JashButton";innerHtmlInspectBut.accessKey="A";innerHtmlInspectBut.tabIndex="5";this.innerHtmlInspection=false;innerHtmlInspectBut.onclick=function(){self.innerHtmlInspection=!self.innerHtmlInspection;self.setButtonVisualActiveState(innerHtmlInspectBut,self.innerHtmlInspection?"on":"off");return _null;}
this.setCrossBrowserAccessKeyFunctionForAnchor(innerHtmlInspectBut);var cssBut=document.createElement("a");cssBut.innerHTML="CSS Input ("+this.accessKeyText+"-S)";cssBut.title="CSS Input: turn on CSS input to enter arbitrary CSS ("+this.accessKeyText+"-S)";cssBut.className="JashButton";cssBut.accessKey="S";cssBut.onclick=function(){if(!self.evaluation.cssEvalFlag){self.setButtonVisualActiveState(cssBut,"on");self.evaluation.cssEvalFlag=true;inp.className="cssEntry";if(document.getElementById("JashStyleInput")!=null){self.evaluation.styleInputTag.disabled=false;}
inp.value="";}else{self.setButtonVisualActiveState(cssBut,"off");inp.className="";self.evaluation.cssEvalFlag=false;if(document.getElementById("JashStyleInput")!=null){self.evaluation.styleInputTag.disabled=true;}
inp.value="";}
inp.focus();return _null;}
this.setCrossBrowserAccessKeyFunctionForAnchor(cssBut);var resizeBut=document.createElement("div");resizeBut.id="JashResizeButton";this.minDims={x:100,y:100};resizeBut.onmousedown=function(e){e=(typeof window.event!="undefined")?window.event:e;var originalDims=self.getDimensions(textareaWrap);var originMouseDims=self.getMouseXY(e);document.onmousemove=function(e){var newMouseDims=self.getMouseXY(e);var newWidth=originalDims.x+(newMouseDims.x-originMouseDims.x);if(newWidth<self.minDims.x){newWidth=self.minDims.x;}
textareaWrap.style.width=newWidth+"px";debugParent.style.width=newWidth+"px";var newHeight=originalDims.y+(newMouseDims.y-originMouseDims.y);if(newHeight<self.minDims.y){newHeight=self.minDims.y;}
textareaWrap.style.height=newHeight+"px";debugParent.style.height=newHeight+"px";}
document.onmouseup=function(){document.onmousemove="";}}
var bottomBar=document.createElement("div");bottomBar.id="JashBottomBar";debugParent.appendChild(dragBut);debugParent.appendChild(xBut);bottomBar.appendChild(evalBut);bottomBar.appendChild(cssBut);bottomBar.appendChild(domBut);bottomBar.appendChild(innerHtmlInspectBut);bottomBar.appendChild(clearBut);bottomBar.appendChild(helpBut);debugParent.appendChild(bottomBar);debugParent.appendChild(resizeBut);document.body.appendChild(debugParent);textareaWrap.appendChild(debugOutput);textareaWrap.appendChild(inp);debugParent.appendChild(textareaWrap);this.bottomBar=document.getElementById("JashBottomBar");this.dragBar=document.getElementById("JashDragBar")
this.output=document.getElementById("JashOutput");this.input=document.getElementById("JashInput");this.mainBlock=debugParent;this.addEvent(window,'scroll',function(){debugParent.style.top=50+self.getXBrowserYOffset()+'px';});}
this.setButtonVisualActiveState=function(button,state){if(state=="on"){button.style.backgroundColor="lightgreen";}else{button.style.backgroundColor="";}}
this.help=function(){var out=new Array();out.push(line);out.push("Jash v"+this.version+" "+this.versionDate.replace(/\$/g,''),true);out.push("http://www.billyreisinger.com/jash/documentation.html");out.push(line);out.push("METHODS");out.push(line);out.push("this.cls() - clear console and terminal");out.push("jash.print(str,clear) - output str to console ~~ str = string ~~ clear = true|false: clear console before output");out.push("this.close() - close this console");out.push("this.dump(obj) - output object and members to console");out.push("this.show(obj) - print out the names and types (only) of all members of obj");out.push("this.stopWatch.start() - start timer");out.push("this.stopWatch.stop() - end timer and return result in ms");out.push("this.kill(HTML Element) - remove an element from the page.");out.push("this.getDimensions(HTML Element) - get width, height dimensions of an html element. Returns an object [x,y]");out.push(line);out.push("KEYSTROKES");out.push(line);out.push("press up arrow in input field to retrieve last input");out.push("press ESC to show/hide console");out.push("press "+this.accessKeyText+"-Q to turn on/off Transparent mode, so you can see through the Jash.");out.push("press ENTER in input field to enter a command");out.push("press TAB to auto-complete input");out.push("press "+this.accessKeyText+"-Z to evaluate input");out.push("press "+this.accessKeyText+"-X to activate/deactivate DOM inspector");out.push("press "+this.accessKeyText+"-A to activate/deactivate innerHTML dump (only works w/ DOM inspector)");out.push("press "+this.accessKeyText+"-C to clear output and input");out.push("press "+this.accessKeyText+"-S to turn on/off CSS input mode. In CSS input mode, you can enter arbitrary CSS selectors and rules, as you would normally do in a CSS stylesheet.");this.print(out.join("\n"));return _null;}
this.close=function(){if(this.mainBlock.style.display=="none"){this.mainBlock.style.display="block";this.input.focus();}else{this.mainBlock.style.display="none";}}
this.setCrossBrowserAccessKeyFunctionForAnchor=function(el){var self=this;el.tabIndex=++this.tabIndexIndex;if(this.browser=="ie"){el.onfocus=function(){if(window.event.altKey){el.onclick();}
self.input.focus();}}}
this.stopWatch={t_start:0,t_end:0,t_total:0,start:function(){t_start=new Date().getTime();return t_start;},stop:function(){t_end=new Date().getTime();t_total=t_end-t_start;return(t_total);}}
this.showNodes=function(e){if(typeof e=="undefined")e=window.event;var el=typeof e.target=="undefined"?e.srcElement:e.target;this.currentNode=el;var childMost=this.identifyNode(el,false);var out="";var childmostTxt="childmost..... "+childMost.txt+"\n";while(el=el.parentNode){if(el.nodeName.toLowerCase()=="html"){out="parentmost.... <html>\n"+out;break;}
out=this.identifyNode(el).txt+"\n"+out;}
out="**** PRESS "+this.accessKeyText+"-X TO PAUSE / UNPAUSE ****\n"+out;out+=childmostTxt;this.print(out,true,true,false);if(this.innerHtmlInspection){this.print("INNER HTML");if(this.currentNode.innerHTML.indexOf("<")!=-1){this.print(Jash.Indenter.indent(this.currentNode.innerHTML),false,true,false);}else{this.print(this.currentNode.innerHTML,false,true,false);}}
if(!this.evaluation.cssEvalFlag){if(childMost.id!=""){if(typeof $!="undefined"){this.input.value='$("'+childMost.id+'")';}else{this.input.value='document.getElementById("'+childMost.id+'")';}}else{this.input.value="this.currentNode";}}}
this.identifyNode=function(el,showDots){showDots=typeof showDots=="boolean"?showDots:true;var out={txt:"",id:""};if(showDots)out.txt+=".............. ";out.txt+="<"+el.nodeName.toLowerCase();for(var i=0;i<el.attributes.length;i++){if((this.browser=="ie"&&el.attributes[i].specified===true)||this.browser!="ie"){out.txt+=" "+el.attributes[i].name;out.txt+="=\""+el.attributes[i].value+"\"";}}
out.txt+=">";return out;}
this.kill=function(){this.currentNode.parentNode.removeChild(this.currentNode);}}
Jash.Evaluator=function(){this.cssEvalFlag=false;var _null="nooutput";this.evaluate=function(input){if(input=="")return false;this.history.add(input);if(this.cssEvalFlag){this.evalCss(input);this.print(input);}else{var output=this.evalJs(input);if(typeof output!="undefined"){this.print(">> "+input);this.print(output);}}}
this.evalJs=function(input){try{var result;if(this.browser=="ie"){result=eval(input);}else{result=window.eval(input);}
if(result!=null&&result.toString()!=_null){return(result.toString());}else{return"null"}}catch(e){return(e.message);}}
this.evalCss=function(input){try{this.insertStyleRule(input);}catch(e){}
return input;}
this.insertStyleRule=function(rule){var lastStyleSheetIndex=document.styleSheets.length-1;if(document.getElementById("JashStyleInput")==null){this.styleInputTag=document.createElement("style");this.styleInputTag.id="JashStyleInput";this.styleInputTag.type="text/css";document.body.appendChild(this.styleInputTag);}
if(this.browser=="ff"||this.browser=="op"){this.styleInputTag.innerHTML+=rule+"\n";}else if(this.browser=="ie"||this.browser=="sa"){if(this.browser=="ie"){var i=0;}else if(this.browser="sa"){var i=document.styleSheets.length-1;}
var rulesArray=rule.split("}");for(var t=0;t<rulesArray.length;t++){var ruleSplit=rulesArray[t].split("{");var selectors=ruleSplit[0].split(",");for(var k=0;k<selectors.length;k++){document.styleSheets[i].addRule(selectors[k],ruleSplit[1]);}}}
return"";}
return this;}
Jash.History=function(){this.entries=new Array('');this.position=0;}
Jash.History.prototype={add:function(input){this.entries.push(input);this.position=this.entries.length-1;},getPreviousInput:function(){if(this.position<0){return'';}
var entry=typeof this.entries[this.position]!="undefined"?this.entries[this.position]:'';if(this.position>0){this.position--;}
return entry;},getNextInput:function(){if(this.position+1<this.entries.length){return this.entries[++this.position];}else{return'';}}}
Jash.Indenter={indentChar:"\t",nodesCommonlyUnclosed:new Array("link ","img ","meta ","!DOCTYPE ","input ","param","hr","br"),stringRepeat:function(stringToRepeat,times){var string=new Array();for(var i=0;i<times;i++){string.push(stringToRepeat);}
return string.join('');},closeUnclosedNode:function(str){for(var k=0;k<this.nodesCommonlyUnclosed.length;k++){var reg=new RegExp("^"+this.nodesCommonlyUnclosed[k].toLowerCase());if(str.toLowerCase().match(reg)){return str.replace(">","/>");}}
return str;},indentAndAdd:function(level,string,arr){var indents=this.stringRepeat(this.indentChar,level);arr.push(indents+string);return arr;},indent:function(source){var source=source;var arr=new Array();source=source.replace(/[\n\r\t]/g,'');source=source.replace(/>\s+/g,">");source=source.replace(/\s+</g,"<");var splitsrc=source.split("<");for(i=0;i<splitsrc.length;i++){splitsrc[i]=this.closeUnclosedNode(splitsrc[i]);}
source=splitsrc.join("<");var level=0;var sourceLength=source.length;var position=0;while(position<sourceLength){if(source.charAt(position)=='<'){var startedAt=position;var tagLevel=1;if(source.charAt(position+1)=='/'){tagLevel=-1;}
if(source.charAt(position+1)=='!'){tagLevel=0;}
while(source.charAt(position)!='>'){position++;}
if(source.charAt(position-1)=='/'){tagLevel=0;}
var tagLength=position+1-startedAt;if(tagLevel===-1){level--;}
arr=this.indentAndAdd(level,source.substr(startedAt,tagLength),arr);if(tagLevel===1){level++;}}
if((position+1)<sourceLength){if(source.charAt(position+1)!=='<'){startedAt=position+1;while(source.charAt(position)!=='<'&&position<sourceLength){position++;}
if(source.charAt(position)==='<'){tagLength=position-startedAt;arr=this.indentAndAdd(level,source.substr(startedAt,tagLength),arr);}}else{position++;}}else{break;}}
return arr.join("\n");}}
Jash.Profiler=function(func,onFinish){this.func=func;this.time=0;this.defaultOnFinish=function(){};this.results=new Array();this.onFinish=typeof onFinish!="function"?this.defaultOnFinish:onFinish;var self=this;this.reverseWhile=function(reps){this.stopWatch.start();while(reps>0){this.func();reps--;}
return this.stopWatch.stop();}
this.forLoop=function(reps){this.stopWatch.start();for(i=0;i<reps;i++){this.func();}
return this.stopWatch.stop();}
this.loop=function(kind,reps){if(!this.results[kind]){this.results[kind]=new Array();}
var repsMemberName="r_"+reps;if(!this.results[kind][repsMemberName]){this.results[kind][repsMemberName]=new Array();}
var time=this[kind](reps);this.results[kind][repsMemberName].push(time);}
this.runOnce=function(){if(!this.results.runOnce){this.results.runOnce=new Array();}
this.stopWatch.start();func();this.results.runOnce.push(this.stopWatch.stop());}
this.stopWatch={t_start:0,t_end:0,t_total:0,start:function(){t_start=new Date().getTime();return t_start;},stop:function(){t_end=new Date().getTime();t_total=t_end-t_start;self.time=t_total;return t_total;}}
this.average=function(arr){var sum=0;for(i=0;i<arr.length;i++){sum+=arr[i];}
return sum/arr.length}
this.multiPass=function(passes,type,reps){if(typeof type=="undefined"){type="runOnce";}else if(typeof this[type]=="undefined"){jash.print("Error: the loop type '"+type+"' does not exist");return false;}
var self=this;if(type=="runOnce"){if(passes<1){self.reportProfile(Math.round(this.average(this.results.runOnce)),type,reps);}else{window.setTimeout(function(){self.runOnce();self.multiPass(--passes,type);},50);}}else{if(passes<1){var repsMemberName="r_"+reps;self.reportProfile(Math.round(this.average(this.results[type][repsMemberName])),type,reps);}else{window.setTimeout(function(){self.loop(type,reps);self.multiPass(--passes,type,reps);},50);}}}
this.reportProfile=function(avgMs,type,reps){var line="-------PROFILER----------------------------------------------";var str=line+"\n"+this.func+"\n"+line+"\n";str+="Type of profile: "+type+"\n";if(typeof reps!="undefined"){str+="Loop iterations: "+reps+"\n";}
str+="Average execution time: "+avgMs+"ms"+"\n";if(type=="runOnce"){howManyTimes=this.results.runOnce.length;}else{repsMemberName="r_"+reps;howManyTimes=this.results[type][repsMemberName].length;}
str+="Average calculated from "+howManyTimes+" pass(es)\n";str+=line+"\n";jash.print(str);}}
Jash.TabComplete=function(){this.tabComplete=function(e){e=(typeof window.event!="undefined")?window.event:e;var inputText=this.input.value;var match=null;if(match=this.searchInputForDomGetElFunctions(inputText)){this.tabCompleteIdOrClassInJavascript(match.match[0],match.type);this.focusCaretAtEndOfInput();return false;}else if(this.evaluation.cssEvalFlag){this.tabCompleteIdOrClassInCss(inputText);this.focusCaretAtEndOfInput();return false;}else{this.tabCompleteJavascript(e,inputText);this.focusCaretAtEndOfInput();}}
this.focusCaretAtEndOfInput=function(){this.input.selectionEnd=this.input.selectionStart=this.input.value.length;}
this.tabCompleteJavascript=function(e,inputText){var words=inputText.split(/\s+/);var lastWord=words[(words.length-1)];var numOpeningParens=lastWord.split("(").length-1;var numClosingParens=lastWord.split(")").length-1;var scope;var sentinel=0;var diff=numOpeningParens-numClosingParens;if(diff>0){numClosingParens=lastWord.split("(")[numOpeningParens].split(")").length-1;var numRealDanglers=numOpeningParens-numClosingParens;scope=lastWord.split("(").slice(numRealDanglers).join("(");}else if(diff<0){this.print("error: too many closing parentheses");return false;}else{scope=lastWord;}
scope=scope.split(".");var fragment=scope.pop();scope=scope.join(".");if(scope=="")scope="window";var members=this.getMembers(scope);var results=this.findTextMatchesInArray(members,fragment);if(results==false){}else if(typeof results!="string"){this.dump(results);var bestMatch=this.findBestStringMatch(fragment,results);if(fragment!=''){fragReg=new RegExp(fragment+"$");this.input.value=this.input.value.replace(fragReg,bestMatch);}else{this.input.value+=bestMatch;}}else{var reggie=new RegExp(fragment+"$");this.input.value=this.input.value.replace(reggie,results);}
return false;}
this.doAllStringsInArrayHaveSameCharacterAtIndex=function(index,arr){var matched=0;if(!arr[0].charAt(index))return false;var character=arr[0].charAt(index);for(var i=1;i<arr.length;i++){if(!arr[i].charAt(index)||arr[i].charAt(index)!=character){return false;}}
return true;}
this.findBestStringMatch=function(str,arr){var fragLength=str.length;var matches=this.doAllStringsInArrayHaveSameCharacterAtIndex(fragLength,arr);while(matches){fragLength++;matches=this.doAllStringsInArrayHaveSameCharacterAtIndex(fragLength,arr);}
return arr[0].substr(0,fragLength);}
this.tabCompleteIdOrClassInJavascript=function(inputText,type){var query=inputText.split("(");query=query[query.length-1].replace(/\W/g,'');var matches=new Array();var els=document.getElementsByTagName("*");if(type=="id"){for(var i=0;i<els.length;i++){if(els[i].id&&els[i].id.indexOf(query)==0){matches.push(els[i].id);}}}else if(type=="class"){for(var i=0;i<els.length;i++){if(els[i].className&&els[i].className!=''){var classes=els[i].className.split(/\s/);for(var ii=0;ii<classes.length;ii++){if(classes[ii].indexOf(query)==0||query==''){if(matches.join("***").indexOf(classes[ii])==-1){matches.push(classes[ii]);}}}}}}
if(matches.length==1){this.input.value+=matches[0].split(query)[1];}else if(matches.length==0){this.print("no match");}else{this.dump(matches.sort());var bestMatch=this.findBestStringMatch(query,matches);if(query!=''){var replacement=inputText.split("(");replacement[replacement.length-1]=replacement[replacement.length-1].replace(query,bestMatch);this.input.value=this.input.value.replace(inputText,replacement.join("("));}else{this.input.value+=bestMatch;}}}
this.tabCompleteIdOrClassInCss=function(inputText){var selectors=inputText.replace(/(\.|#)/g,' $1').split(/\s+/);var lastSelector=selectors[selectors.length-1];var els=document.getElementsByTagName("*");var matches=new Array();if(lastSelector.match(/^\./)){for(var i=0;i<els.length;i++){if(els[i].className&&els[i].className!=''){var classes=els[i].className.split(/\s/);for(var ii=0;ii<classes.length;ii++){if(classes[ii].indexOf(lastSelector.substr(1))==0||lastSelector=="."){if(matches.join("***").indexOf(classes[ii])==-1){matches.push("."+classes[ii]);}}}}}}else if(lastSelector.match(/^#/)){for(var i=0;i<els.length;i++){if(els[i].id&&els[i].id.indexOf(lastSelector.substr(1))==0){matches.push("#"+els[i].id);}}}
if(matches.length==1){this.input.value+=matches[0].split(lastSelector)[1];}else if(matches.length==0){this.print("no match");}else{this.dump(matches.sort());var bestMatch=this.findBestStringMatch(lastSelector,matches);if(lastSelector!=''){this.input.value=this.input.value.replace(lastSelector,bestMatch);}else{this.input.value+=bestMatch;}}}
this.searchInputForDomGetElFunctions=function(inputText){for(var i=0;i<this.domGetElFunctions.id.length;i++){var selfct=new RegExp(this.domGetElFunctions.id[i].replace("\$","\\\$")+"\\\(['\"]\\w*$");if(inputText.match(selfct)){return{match:inputText.match(selfct),type:"id"};}}
for(var i=0;i<this.domGetElFunctions.className.length;i++){var selfct=new RegExp(this.domGetElFunctions.className[i].replace("\$","\\\$")+"\\\(['\"]\\w*$");if(inputText.match(selfct)){return{match:inputText.match(selfct),type:"class"};}}}
this.findTextMatchesInArray=function(arrayToTest,findMe){var resultsArray=new Array();var tester=new RegExp("^"+findMe);for(var i=0;i<arrayToTest.length;i++){if(tester.test(arrayToTest[i])){resultsArray.push(arrayToTest[i]);}}
if(resultsArray.length>1){resultsArray.sort();return resultsArray;}else if(resultsArray.length==1){return resultsArray[0];}else{return false;}}
this.getMembers=function(context){var members=new Array();for(memberName in eval(context)){members.push(memberName);}
return members;}
return this;}
new function(){if("jash"in window){window.jash.close();}else{window.jash=new Jash();window.jash.main();}}
//}}}
http://www.englishelp.ru/learn-english/grammar/176-used-to-be-used-to-get-used-to.html
!used to
!be used to
!get used to
Сравнение оборотов used to / be used to / get used to
Образование used to / be used to / get used to

Образование used to см. Оборот Used to.

Обороты be used to и get used to требуют после себя существительного или герундия:
I am used to this noise. -Я привык к этому шуму.
Will he get used to going to this school? -Он привыкнет ходить в эту школу?
Употребление used to / be used to / get used to

Used to используется при описании событий, которые регулярно происходили в прошлом, а потом прекратились: либо на время, либо насовсем (см. Оборот Used to).

Обороты be used to и get used to употребляются для выражения действий, ставших привычными:
I am used to waking up at 10 every day. – Я привык каждый день вставать в десять.
I was used to go to the dacha in summer. – Я привык ездить летом на дачу.
I had got used to doing morning exercises before having breakfast. – Делать зарядку по утрам стало для меня привычкой.
You've got to get used to it. — Придется тебе к этому привыкнуть.
Over time, he'll get used to it. — Со временем он к этому привыкнет.

Сравнительные предложения:
I used to play with Kate. – Раньше я играл с Катей. (а теперь больше с ней не играю)
I am used to playing with Kate./I get used to playing with Kate. – Я привык играть с Катей. (и теперь играю)
/***
|Name:|LessBackupsPlugin|
|Description:|Intelligently limit the number of backup files you create|
|Version:|3.0.1a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#LessBackupsPlugin|
|Author:|Simon Baird|
|Email:|simon.baird@gmail.com|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Description
You end up with just backup one per year, per month, per weekday, per hour, minute, and second.  So total number won't exceed about 200 or so. Can be reduced by commenting out the seconds/minutes/hours line from modes array
!!Notes
Works in IE and Firefox only.  Algorithm by Daniel Baird. IE specific code by by Saq Imtiaz.
***/
//{{{

var MINS  = 60 * 1000;
var HOURS = 60 * MINS;
var DAYS  = 24 * HOURS;

if (!config.lessBackups) {
  config.lessBackups = {
    // comment out the ones you don't want or set config.lessBackups.modes in your 'tweaks' plugin
    modes: [
      ["YYYY",  365*DAYS], // one per year for ever
      ["MMM",   31*DAYS],  // one per month
      ["ddd",   7*DAYS],   // one per weekday
      //["d0DD",  1*DAYS],   // one per day of month
      ["h0hh",  24*HOURS], // one per hour
      ["m0mm",  1*HOURS],  // one per minute
      ["s0ss",  1*MINS],   // one per second
      ["latest",0]         // always keep last version. (leave this).
    ]
  };
}

window.getSpecialBackupPath = function(backupPath) {

  var now = new Date();

  var modes = config.lessBackups.modes;

  for (var i=0;i<modes.length;i++) {

    // the filename we will try
    var specialBackupPath = backupPath.replace(/(\.)([0-9]+\.[0-9]+)(\.html)$/,
        '$1'+now.formatString(modes[i][0]).toLowerCase()+'$3')

    // open the file
    try {
      if (config.browser.isIE) {
        var fsobject = new ActiveXObject("Scripting.FileSystemObject")
        var fileExists  = fsobject.FileExists(specialBackupPath);
        if (fileExists) {
          var fileObject = fsobject.GetFile(specialBackupPath);
          var modDate = new Date(fileObject.DateLastModified).valueOf();
        }
      }
      else {
        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
        file.initWithPath(specialBackupPath);
        var fileExists = file.exists();
        if (fileExists) {
          var modDate = file.lastModifiedTime;
        }
      }
    }
    catch(e) {
      // give up
      return backupPath;
    }

    // expiry is used to tell if it's an 'old' one. Eg, if the month is June and there is a
    // June file on disk that's more than an month old then it must be stale so overwrite
    // note that "latest" should be always written because the expiration period is zero (see above)
    var expiry = new Date(modDate + modes[i][1]);
    if (!fileExists || now > expiry)
      return specialBackupPath;
  }
}

// hijack the core function
window.getBackupPath_mptw_orig = window.getBackupPath;
window.getBackupPath = function(localPath) {
  return getSpecialBackupPath(getBackupPath_mptw_orig(localPath));
}

//}}}
/***
|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
//}}}
http://linux.byexamples.com/archives/135/rename-multiple-files/

To rename *.txt to *.bak 
(e.g. to rename ham.txt to ham.bak)
for f in *.txt; do mv "$f" "${f%.txt}.bak"; done
To remove ‘new-’ from new-*
(e.g. to rename new-ham.txt to ham.txt)
for f in new-*; do mv "$f" "${f#new-}"; done
${variable%pattern} vs ${variable#pattern}
The funny-looking symbol, ${f%.txt} is a useful match-and-remove string operator:
If the pattern ‘.txt’ matches the end of variable $f, it will remove the matching part (that’s ‘.txt‘) and return the rest. Try this:
f=new-ham.txt      # define $f as 'new-ham.txt'
echo ${f%.txt}     # display 'new-ham'
What about ${f#new-}? It’s almost the same, but it matches the pattern at the beginning of the variable.
echo ${f#new-}     # display 'ham.txt'
[[main]]
<<tag "Программы">>
<<tag "Личные дела">>
<<tag "Perl">>
<<tag "Tiddlywiki">>
[[cal|https://www.google.com/calendar/render?tab=oc]]
<<search>>
[[скачать эту tiddiwiki c плагинами|perl6tiddwiki.zip]]
/***
|''Name''|MediaWikiTableFormatterPlugin|
|''Description''|Allows MediaWiki style tables in TiddlyWiki|
|''Author''|Martin Budden (mjbudden (at) gmail (dot) com)|
|''Contributors''|FND|
|''Version''|0.1.2|
|''Status''|stable|
|''Source''|http://devpad.tiddlyspot.com/#MediaWikiTableFormatterPlugin|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/formatters/MediaWikiTableFormatterPlugin.js|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.1.0|
!Description
Enables [[MediaWiki|http://www.mediawiki.org]]'s table markup in TiddlyWiki, allowing for multi-line contents within table cells.
(Note that all TiddlyWiki markup still applies.)
!Usage
Detailed documentation available at [[MediaWiki.org|http://www.mediawiki.org/wiki/Help:Tables]].
!!Examples
{{{
{|
! Heading 1
! Heading 2
! Heading 3
|-
| row 1, column 1
| row 1, column 2
| row 1, column 3
|-
| row 2, column 1
| row 2, column 2
| row 2, column 3
|}
}}}
{|
! Heading 1
! Heading 2
! Heading 3
|-
| row 1, column 1
| row 1, column 2
| row 1, column 3
|-
| row 2, column 1
| row 2, column 2
| row 2, column 3
|}
!Revision History
!!v0.1 (2008-10-31)
* initial release
!!v0.1.2 (2008-11-05)
* removed unnecessary code
!Code
***/
//{{{
if(!version.extensions.MediaWikiTableFormatterPlugin) { //# ensure that the plugin is only installed once
version.extensions.MediaWikiTableFormatterPlugin = {installed:true};

if(version.major < 2 || (version.major == 2 && version.minor < 1)) {
	alertAndThrow('MediaWikiTableFormatterPlugin requires TiddlyWiki 2.1 or later.');
}

config.formatters.push({
	name: 'enhancedTable',
	match: '^\\{\\|',
	handler: function(w) {
		var pair = MediaWikiTemplate.findTableBracePair(w.source,w.matchStart);
		if(pair.start==w.matchStart) {
			w.nextMatch = w.matchStart;
			var table = MediaWikiTemplate.createElement(w.output,'table');
			var tbody = MediaWikiTemplate.createElement(table,'tbody'); // required for IE
			var mwt = new MediaWikiTemplate();
			mwt.wikifyTable(tbody,w,pair);
		}
	}
});


MediaWikiTemplate = function()
{
	this.stack = [];
	this.error = false;
	this.tiddler = null;
};

MediaWikiTemplate.createElement = function(parent,element)
{
	return parent.appendChild(document.createElement(element));
}

MediaWikiTemplate.setAttributesFromParams = function(e,p)
{
	var re = /\s*(.*?)=(?:(?:"(.*?)")|(?:'(.*?)')|((?:\w|%|#)*))/mg;
	var match = re.exec(p);
	while(match) {
		var s = match[1].unDash();
		if(s == 'bgcolor') {
			s = 'backgroundColor';
		}
		try {
			if(match[2]) {
				e.setAttribute(s,match[2]);
			} else if(match[3]) {
				e.setAttribute(s,match[3]);
			} else {
				e.setAttribute(s,match[4]);
			}
		}
		catch(ex) {}
		match = re.exec(p);
	}
};

MediaWikiTemplate.findRawDelimiter = function(delimiter,text,start)
//# find a delimiter that is not enclosed by [[..]]
{
	var d = text.indexOf(delimiter,start);
	if(d==-1)
		return -1;
	var b = {start:-1,end:-1};
	var bs = text.indexOf('[[',start);
	if(bs==-1 || bs >d)
		return d;
	var s1 = -1;
	if(bs!=-1 && bs <d) {
		var be = text.indexOf(']]',bs);
		if(be!=-1) {
			b.start = bs;
			b.end = be;
		}
	}
	if(b.start!=-1 && d>b.start)
		s1 = b.end+2;
	return s1==-1 ? d : MediaWikiTemplate.findRawDelimiter(delimiter,text,s1);
};

MediaWikiTemplate.findTableBracePair = function(text,start)
{
	var ret = {start:-1,end:-1};
	var s = text.indexOf('{|',start);
	if(s==-1)
		return ret;
	var e = text.indexOf('\n|}',s+2);
	if(e==-1)
		return ret;
	e++;
	var s2 = text.indexOf('{|',s+2);
	if(s2==-1 || s2 > e)
		return {start:s,end:e};
	var tp = MediaWikiTemplate.findTableBracePair(text,s+2);
	while(tp.end!=-1 && e>tp.start && e<=tp.end) {
		//# intervening table brace pair, so skip over
		e = tp.end+2;
		tp = MediaWikiTemplate.findTableBracePair(text,e);
		e = text.indexOf('\n|}',e);
		if(e==-1)
			return ret;
		e++;
	}
	return {start:s,end:e};
};

MediaWikiTemplate.prototype.wikifyTable = function(table,w,pair)
{
	function lineEnd(w) {
		var r = w.source.indexOf('\n',w.nextMatch);
		while(r!=-1) {
			var n = w.source.substr(r+1,1);
			if(n=='|' || n=='!' || (n=='{' && w.source.substr(r+2,1)=='|'))
				break;
			r = w.source.indexOf('\n',r+1);
		}
		return r;
	}
	function subWikifyText(e,w,text) {
			var oldSource = w.source; var oldMatch = w.nextMatch;
			w.source = text; w.nextMatch = 0;
			w.subWikifyUnterm(e);
			w.source = oldSource; w.nextMatch = oldMatch;
	}
	//# skip over {|
	w.nextMatch += 2;
	var i = lineEnd(w);
	if(i>w.nextMatch) {
		MediaWikiTemplate.setAttributesFromParams(table.parentNode,w.source.substring(w.nextMatch,i));
		w.nextMatch = i;
	}
	w.nextMatch++;
	if(w.source.substr(w.nextMatch,2)=='|+') {
		var caption = MediaWikiTemplate.createElement(table,'caption');
		w.nextMatch += 2;
		i = lineEnd(w);
		var d = MediaWikiTemplate.findRawDelimiter('|',w.source,w.nextMatch);
		if(d!=-1 && d<i) {
			MediaWikiTemplate.setAttributesFromParams(caption,w.source.substring(w.nextMatch,d));
			w.nextMatch = d+1;
		}
		w.subWikifyTerm(caption,/(\n)/mg);
	}
	var tr = MediaWikiTemplate.createElement(table,'tr');
	if(w.source.substr(w.nextMatch,2)=='|-') {
		w.nextMatch += 2;
		i = lineEnd(w);
		if(i>w.nextMatch) {
			MediaWikiTemplate.setAttributesFromParams(tr,w.source.substring(w.nextMatch,i));
			w.nextMatch = i;
		}
		w.nextMatch++;
	}
	var x = w.source.substr(w.nextMatch,2);
	while(x!='|}') {
		if(x=='{|') {
			//# nested table
			var pair2 = MediaWikiTemplate.findTableBracePair(w.source,w.nextMatch);
			if(pair2.start==w.nextMatch) {
				var table2 = MediaWikiTemplate.createElement(cell,'table');
				this.wikifyTable(table2,w,pair2);
			}
		} else if(x=='|-') {
			//# new row
			tr = MediaWikiTemplate.createElement(table,'tr');
			w.nextMatch += 2;
			i = lineEnd(w);
			if(i==-1)
				break;
			if(i>w.nextMatch) {
				MediaWikiTemplate.setAttributesFromParams(tr,w.source.substring(w.nextMatch,i));
				w.nextMatch = i;
			}
			w.nextMatch++;
		} else if(x.substr(0,1)=='!') {
			//# header cell
			w.nextMatch++;
			i = lineEnd(w);
			if(i==-1)
				break;
			var cell = MediaWikiTemplate.createElement(tr,'th');
			var c = w.source.indexOf('!!',w.nextMatch);
			while(c!=-1 && c<i) {
				d = MediaWikiTemplate.findRawDelimiter('|',w.source,w.nextMatch);
				if(d!=-1 && d<c) {
					MediaWikiTemplate.setAttributesFromParams(cell,w.source.substring(w.nextMatch,d));
					w.nextMatch = d+1;
				}
				while(w.source.substr(w.nextMatch,1)==' ') {
					w.nextMatch++;
				}
				w.subWikifyTerm(cell,/(\!\!)/mg);
				cell = MediaWikiTemplate.createElement(tr,'th');
				c = w.source.indexOf('!!',w.nextMatch);
			}
			d = MediaWikiTemplate.findRawDelimiter('|',w.source,w.nextMatch);
			if(d!=-1 && d<i) {
				MediaWikiTemplate.setAttributesFromParams(cell,w.source.substring(w.nextMatch,d));
				w.nextMatch = d+1;
			}
			while(w.source.substr(w.nextMatch,1)==' ') {
				w.nextMatch++;
			}
			subWikifyText(cell,w,w.source.substring(w.nextMatch,i));
			w.nextMatch = i+1;
		} else if(x.substr(0,1)=='|') {
			//# cell
			w.nextMatch++;
			i = lineEnd(w);
			if(i==-1)
				break;
			cell = MediaWikiTemplate.createElement(tr,'td');
			c = w.source.indexOf('||',w.nextMatch);
			while(c!=-1 && c<i) {
				d = MediaWikiTemplate.findRawDelimiter('|',w.source,w.nextMatch);
				if(d!=-1 && d<c) {
					MediaWikiTemplate.setAttributesFromParams(cell,w.source.substring(w.nextMatch,d));
					w.nextMatch = d+1;
				}
				while(w.source.substr(w.nextMatch,1)==' ') {
					w.nextMatch++;
				}
				w.subWikifyTerm(cell,/(\|\|)/mg);
				cell = MediaWikiTemplate.createElement(tr,'td');
				c = w.source.indexOf('||',w.nextMatch);
			}
			d = MediaWikiTemplate.findRawDelimiter('|',w.source,w.nextMatch);
			if(d!=-1 && d<i) {
				MediaWikiTemplate.setAttributesFromParams(cell,w.source.substring(w.nextMatch,d));
				w.nextMatch = d+1;
			}
			while(w.source.substr(w.nextMatch,1)==' ') {
				w.nextMatch++;
			}
			subWikifyText(cell,w,w.source.substring(w.nextMatch,i));
			w.nextMatch = i+1;
		}
		x = w.source.substr(w.nextMatch,2);
	}
	w.nextMatch = pair.end + 3;
	return;
};

} //# end of 'install only once'
//}}}

Name: MptwBlack
Background: #000
Foreground: #fff
PrimaryPale: #333
PrimaryLight: #555
PrimaryMid: #888
PrimaryDark: #aaa
SecondaryPale: #111
SecondaryLight: #222
SecondaryMid: #555
SecondaryDark: #888
TertiaryPale: #222
TertiaryLight: #666
TertiaryMid: #888
TertiaryDark: #aaa
Error: #300

Name: MptwBlue
Background: #fff
Foreground: #000
PrimaryPale: #cdf
PrimaryLight: #57c
PrimaryMid: #114
PrimaryDark: #012
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

//{{{
// Pretty sure this is incomplete and experimental
// TODO: Fix it or remove it.

(function($){

merge(config.macros,{
  mptwCollapse: {
    handler: function(place,macroName,params) {
      createTiddlyButton(place, params[0] == '+' ? '\u25AD' : '\u25AC', 'collapse/uncollapse', function(){
        $(story.findContainingTiddler(place)).toggleClass('collapsed');
      });
    }
  }
});

/* this doesn't work unless you have a modified ViewTempate */
config.shadowTiddlers["MptwCollapsePluginStyles"] = ""
  +".collapsed .uncollapsedView { display:none;       }"
  +".collapsedView              { display:none;       }"
  +".collapsed .collapsedView   { display:block;      }"
  +".tiddler.collapsed          { padding-bottom:1em; }"
  +".tiddler.collapsed .title   { font-size:100%;     }"
;

store.addNotification("MptwCollapsePluginStyles",refreshStyles);

})(jQuery);

//}}}
/***
|Name:|MptwConfigPlugin|
|Description:|Miscellaneous tweaks used by MPTW|
|Version:|1.0a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
!!Note: instead of editing this you should put overrides in MptwUserConfigPlugin
***/
//{{{
var originalReadOnly = readOnly;
var originalShowBackstage = showBackstage;

config.options.chkHttpReadOnly = false;  // means web visitors can experiment with your site by clicking edit
readOnly = false;                        // needed because the above doesn't work any more post 2.1 (??)
showBackstage = true;                    // show backstage for same reason

config.options.chkInsertTabs = true;     // tab inserts a tab when editing a tiddler
config.views.wikified.defaultText = "";  // don't need message when a tiddler doesn't exist
config.views.editor.defaultText = "";    // don't need message when creating a new tiddler

config.options.chkSaveBackups = true;         // do save backups
config.options.txtBackupFolder = 'twbackup';  // put backups in a backups folder

config.options.chkAutoSave = (window.location.protocol == "file:"); // do autosave if we're in local file

config.mptwVersion = "2.5.3";

config.macros.mptwVersion={handler:function(place){wikify(config.mptwVersion,place);}};

if (config.options.txtTheme == '')
  config.options.txtTheme = 'MptwTheme';

// add to default GettingStarted
config.shadowTiddlers.GettingStarted += "\n\nSee also [[MPTW]].";

// add select theme and palette controls in default OptionsPanel
config.shadowTiddlers.OptionsPanel = config.shadowTiddlers.OptionsPanel.replace(/(\n\-\-\-\-\nAlso see \[\[AdvancedOptions\]\])/, "{{select{<<selectTheme>>\n<<selectPalette>>}}}$1");

// these are used by ViewTemplate
config.mptwDateFormat = 'DD/MM/YY';
config.mptwJournalFormat = 'Journal DD/MM/YY';

//}}}
Name: MptwGreen
Background: #fff
Foreground: #000
PrimaryPale: #9b9
PrimaryLight: #385
PrimaryMid: #031
PrimaryDark: #020
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

Name: MptwRed
Background: #fff
Foreground: #000
PrimaryPale: #eaa
PrimaryLight: #c55
PrimaryMid: #711
PrimaryDark: #500
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

|Name|MptwRounded|
|Description|Mptw Theme with some rounded corners (Firefox only)|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|PageTemplate|MptwTheme##PageTemplate|
|StyleSheet|##StyleSheet|

!StyleSheet
/*{{{*/

[[MptwTheme##StyleSheet]]

.tiddler,
.sliderPanel,
.button,
.tiddlyLink,
.tabContents
{ -moz-border-radius: 1em; }

.tab {
	-moz-border-radius-topleft: 0.5em;
	-moz-border-radius-topright: 0.5em;
}
#topMenu {
	-moz-border-radius-bottomleft: 2em;
	-moz-border-radius-bottomright: 2em;
}

/*}}}*/

Name: MptwSmoke
Background: #fff
Foreground: #000
PrimaryPale: #aaa
PrimaryLight: #777
PrimaryMid: #111
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

|Name|MptwStandard|
|Description|Mptw Theme with the default TiddlyWiki PageLayout and Styles|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
Name: MptwTeal
Background: #fff
Foreground: #000
PrimaryPale: #B5D1DF
PrimaryLight: #618FA9
PrimaryMid: #1a3844
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #f8f8f8
TertiaryLight: #bbb
TertiaryMid: #999
TertiaryDark: #888
Error: #f88
|Name|MptwTheme|
|Description|Mptw Theme including custom PageLayout|
|PageTemplate|##PageTemplate|
|ViewTemplate|##ViewTemplate|
|EditTemplate|##EditTemplate|
|StyleSheet|##StyleSheet|

http://mptw.tiddlyspot.com/#MptwTheme ($Rev: 1829 $)

!PageTemplate
<!--{{{-->
<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>
<!-- horizontal MainMenu -->
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
<!-- original MainMenu menu -->
<!-- <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>
<!--}}}-->

!ViewTemplate
<!--{{{-->
<div class="uncollapsedView">
[[MptwTheme##ViewTemplateToolbar]]

<div class="tagglyTagged" macro="tags"></div>

<div class='titleContainer'>
	<span class='title' macro='view title'></span>
	<span macro="miniTag"></span>
</div>

<div class='subtitle'>
	(updated <span macro='view modified date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>
	by <span macro='view modifier link'></span>)
	<!--
	(<span macro='message views.wikified.createdPrompt'></span>
	<span macro='view created date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>)
	-->
</div>

<div macro="showWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')">
	<div class='viewer'><pre macro='view text'></pre></div>
</div>
<div macro="else">
	<div class='viewer' macro='view text wikified'></div>
</div>

<div class="tagglyTagging" macro="tagglyTagging"></div>
</div>
<div class="collapsedView">
	<span class='toolbar'>
		<span macro='toolbar closeTiddler'></span>
		<span macro='mptwCollapse +'></span>
	</span>
	<span class='title' macro='view title'></span>
</div>

<!--}}}-->

!ViewTemplateToolbar
<!--{{{-->
<div class='toolbar'>
	<span macro="showWhenTagged systemConfig">
		<span macro="toggleTag systemConfigDisable . '[[disable|systemConfigDisable]]'"></span>
	</span>
	<span macro="showWhenTagged systemTheme"><span macro="applyTheme"></span></span>
	<span macro="showWhenTagged systemPalette"><span macro="applyPalette"></span></span>
	<span macro="showWhen tiddler.tags.contains('css') || tiddler.title == 'StyleSheet'"><span macro="refreshAll"></span></span>
	<span style="padding:1em;"></span>
	<span macro='toolbar closeTiddler closeOthers +editTiddler deleteTiddler > fields syncing permalink references jump'></span> <span macro='newHere label:"new here"'></span>
	<span macro='newJournalHere {{config.mptwJournalFormat?config.mptwJournalFormat:"MM/0DD/YY"}}'></span>
	<!--span macro='mptwCollapse -'></span-->
</div>
<!--}}}-->

!EditTemplate
<!--{{{-->
<div class="toolbar" macro="toolbar +saveTiddler saveCloseTiddler closeOthers -cancelTiddler cancelCloseTiddler deleteTiddler"></div>
<div class="title" macro="view title"></div>
<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>
<div macro='annotations'></div>
<div class="editLabel">Content</div><div class="editor" macro="edit text"></div>
<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>
<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>
<!--}}}-->

!StyleSheet
/*{{{*/

/* a contrasting background so I can see where one tiddler ends and the other begins */
body {
	background: [[ColorPalette::TertiaryLight]];
}

/* sexy colours and font for the header */
.headerForeground {
	color: [[ColorPalette::PrimaryPale]];
}
.headerShadow, .headerShadow a {
	color: [[ColorPalette::PrimaryMid]];
}

/* separate the top menu parts */
.headerForeground, .headerShadow {
	padding: 1em 1em 0;
}

.headerForeground, .headerShadow {
	font-family: 'Trebuchet MS', sans-serif;
	font-weight:bold;
}
.headerForeground .siteSubtitle {
	color: [[ColorPalette::PrimaryLight]];
}
.headerShadow .siteSubtitle {
	color: [[ColorPalette::PrimaryMid]];
}

/* make shadow go and down right instead of up and left */
.headerShadow {
	left: 1px;
	top: 1px;
}

/* prefer monospace for editing */
.editor textarea, .editor input {
	font-family: 'Consolas', monospace;
	background-color:[[ColorPalette::TertiaryPale]];
}


/* sexy tiddler titles */
.title {
	font-size: 250%;
	color: [[ColorPalette::PrimaryLight]];
	font-family: 'Trebuchet MS', sans-serif;
}

/* more subtle tiddler subtitle */
.subtitle {
	padding:0px;
	margin:0px;
	padding-left:1em;
	font-size: 90%;
	color: [[ColorPalette::TertiaryMid]];
}
.subtitle .tiddlyLink {
	color: [[ColorPalette::TertiaryMid]];
}

/* a little bit of extra whitespace */
.viewer {
	padding-bottom:3px;
}

/* don't want any background color for headings */
h1,h2,h3,h4,h5,h6 {
	background-color: transparent;
	color: [[ColorPalette::Foreground]];
}

/* give tiddlers 3d style border and explicit background */
.tiddler {
	background: [[ColorPalette::Background]];
	border-right: 2px [[ColorPalette::TertiaryMid]] solid;
	border-bottom: 2px [[ColorPalette::TertiaryMid]] solid;
	margin-bottom: 1em;
	padding:1em 2em 2em 1.5em;
}

/* make options slider look nicer */
#sidebarOptions .sliderPanel {
	border:solid 1px [[ColorPalette::PrimaryLight]];
}

/* the borders look wrong with the body background */
#sidebar .button {
	border-style: none;
}

/* this means you can put line breaks in SidebarOptions for readability */
#sidebarOptions br {
	display:none;
}
/* undo the above in OptionsPanel */
#sidebarOptions .sliderPanel br {
	display:inline;
}

/* horizontal main menu stuff */
#displayArea {
	margin: 1em 15.7em 0em 1em; /* use the freed up space */
}
#topMenu br {
	display: none;
}
#topMenu {
	background: [[ColorPalette::PrimaryMid]];
	color:[[ColorPalette::PrimaryPale]];
}
#topMenu {
	padding:2px;
}
#topMenu .button, #topMenu .tiddlyLink, #topMenu a {
	margin-left: 0.5em;
	margin-right: 0.5em;
	padding-left: 3px;
	padding-right: 3px;
	color: [[ColorPalette::PrimaryPale]];
	font-size: 115%;
}
#topMenu .button:hover, #topMenu .tiddlyLink:hover {
	background: [[ColorPalette::PrimaryDark]];
}

/* make 2.2 act like 2.1 with the invisible buttons */
.toolbar {
	visibility:hidden;
}
.selected .toolbar {
	visibility:visible;
}

/* experimental. this is a little borked in IE7 with the button 
 * borders but worth it I think for the extra screen realestate */
.toolbar { float:right; }

/* fix for TaggerPlugin. from sb56637. improved by FND */
.popup li .tagger a {
   display:inline;
}

/* makes theme selector look a little better */
#sidebarOptions .sliderPanel .select .button {
  padding:0.5em;
  display:block;
}
#sidebarOptions .sliderPanel .select br {
	display:none;
}

/* make it print a little cleaner */
@media print {
	#topMenu {
		display: none ! important;
	}
	/* not sure if we need all the importants */
	.tiddler {
		border-style: none ! important;
		margin:0px ! important;
		padding:0px ! important;
		padding-bottom:2em ! important;
	}
	.tagglyTagging .button, .tagglyTagging .hidebutton {
		display: none ! important;
	}
	.headerShadow {
		visibility: hidden ! important;
	}
	.tagglyTagged .quickopentag, .tagged .quickopentag {
		border-style: none ! important;
	}
	.quickopentag a.button, .miniTag {
		display: none ! important;
	}
}

/* get user styles specified in StyleSheet */
[[StyleSheet]]

/*}}}*/

|Name|MptwTrim|
|Description|Mptw Theme with a reduced header to increase useful space|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|StyleSheet|MptwTheme##StyleSheet|
|PageTemplate|##PageTemplate|

!PageTemplate
<!--{{{-->

<!-- horizontal MainMenu -->
<div id='topMenu' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<span refresh='content' tiddler='SiteTitle' style="padding-left:1em;font-weight:bold;"></span>:
<span refresh='content' tiddler='MainMenu'></span>
</div>
<div id='sidebar'>
	<div id='sidebarOptions'>
		<div refresh='content' tiddler='SideBarOptions'></div>
		<div style="margin-left:0.1em;"
			macro='slider chkTabSliderPanel SideBarTabs {{"tabs \u00bb"}} "Show Timeline, All, Tags, etc"'></div>
	</div>
</div>
<div id='displayArea'>
	<div id='messageArea'></div>
	<div id='tiddlerDisplay'></div>
</div>

/***
|Description:|A place to put your config tweaks so they aren't overwritten when you upgrade MPTW|
See http://www.tiddlywiki.org/wiki/Configuration_Options for other options you can set. In some cases where there are clashes with other plugins it might help to rename this to zzMptwUserConfigPlugin so it gets executed last.
***/
//{{{

// example: set your preferred date format
//config.mptwDateFormat = 'MM/0DD/YY';
//config.mptwJournalFormat = 'Journal MM/0DD/YY';

// example: set the theme you want to start with
//config.options.txtTheme = 'MptwRoundTheme';

// example: switch off autosave, switch on backups and set a backup folder
//config.options.chkSaveBackups = true;
//config.options.chkAutoSave = false;
//config.options.txtBackupFolder = 'backups';

// uncomment to disable 'new means new' functionality for the new journal macro
//config.newMeansNewForJournalsToo = false;

//}}}
{{links{
<<faviconLink link:'https://mail.yandex.ru/neo2' title:'ya'>><<faviconLink link:'http://delicious.com/dark.schakal/2read' title:'2read'>> <<faviconLink link:'https://mail.google.com/mail' title:'mail'>> <<faviconLink link:'http://www.google.com/reader/view' title:'rss'>> <<faviconLink link:'http://atamanenko.blogspot.com/' title:'blog'>> <<faviconLink link:'http://feedburner.google.com/fb/a/myfeeds' title:'feedburner'>> <<faviconLink link:'https://www.google.com/analytics/settings/' title:'analytics'>> <<faviconLink link:'http://wave.google.com' title:'wave'>> <<faviconLink link:'http://www.blogger.com/home' title:'blogger'>> <<faviconLink link:'http://twitter.com/' title:'twitter'>> <<faviconLink link:'https://www.dropbox.com/home#/' title:'dropbox'>> <<faviconLink link:'http://translate.google.com/toolkit/' title:'translator'>> <<faviconLink link:'http://sibir.megafon.ru/sendsms/' title:'SendSMS'>>
}}}
//{{{
// this part is not actually required but useful to other people using your plugin
version.extensions.HelloWorldMacro = { major: 1, minor: 0, revision: 3, date: new Date(2006,3,3),
	source: "http://simonbaird.com/mptw/#HelloWorldMacro"
};

config.macros.helloWorld = {};
config.macros.helloWorld.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
	var who = params.length > 0 ? params[0] : "world";
	wikify("Hello //" + who + "// from the '" + macroName + "' macro in tiddler [[" + tiddler.title + "]].", place);
}

// a one liner...
config.macros.shout = { handler: function(place,name,params) { wikify("//''@@font-size:5em;color:#696;"+ params[0] + "!@@''//", place); } };
//}}}
<<helloWorld 'all TiddlyWiki fans'>>
/***
|''Name''|NestedBrowserMacro|
|''Description''|Creates a browser pane inside a tiddler for viewing external pages.|
|''Version''|0.1.1|
|''Source''|[[Rodney's Corner|http://rodney.gotdns.com]] (mirror: [[FND's DevPad|http://devpad.tiddlyspot.com/#NestedBrowserMacro]])|
|''Author''|[[RodneyGomes]]|
|''Contributor''|FND|
|''Type''|Macro|
!Usage
A name must be specified for the browser window in order to give for the back and forward buttons to work. Also required are the URL, width and height for the browser pane.
{{{
<<browse frameName url width height>>
}}}
!!Example
{{{
<<browse "Google" "http://www.google.com" "100%" "100px">>
}}}
<<browse "Google" "http://www.google.com" "100%" "100px">>
!Limitations
Uses an //iframe//, which some browsers might not support.
!Revision History
!!v0.1.0 (2006-02-18)
* initial release 
!!v0.1.1 (2007-10-04)
* various adjustments of the meta description
* mirrored at [[FND's DevPad|http://devpad.tiddlyspot.com/#NestedBrowserMacro]] as the original source is not available anymore
!Code
***/
//{{{
config.macros.browse = {};

config.macros.browse.handler = function(place,macroName,params) {
	
	var frameName = params[0];
	var url = params[1];
	var width = params[2];
	var height = params[3];
	
	var myBackButton = document.createElement('a');
	myBackButton.href = "javascript:frames['" + frameName + "'].history.back()";
	var buttonText = document.createTextNode('[Back]');
	myBackButton.appendChild(buttonText);
	
	var myForwardButton = document.createElement('a');
	myForwardButton.href = "javascript:frames['" + frameName + "'].history.forward()";
	var buttonText = document.createTextNode('[Forward]');
	myForwardButton.appendChild(buttonText);
	
	var myIframe = document.createElement('iframe');	
	myIframe.name = frameName;
	myIframe.src = url;
	myIframe.style.width = width;
	myIframe.style.height = height;
	
	place.appendChild(myBackButton);
	place.appendChild(myForwardButton);
	place.appendChild(myIframe);
	
}
//}}}
<<allTags>>
Click the button to get a random color palette defined in hex.
<<RandomColorPaletteButton>>

Don't like hex? Want rgb instead. Use the rgb parameter ({{{<<RandomColorPaletteButton rgb:yes>>}}})
<<RandomColorPaletteButton rgb:yes>>

Want to seed it with a certain hue (0-360 degrees)? Then use the hue parameter... {{{<<RandomColorPaletteButton hue:0>>}}} ... note hue=0 corresponds to red color schemes.
<<RandomColorPaletteButton hue:0>>

Want a bright scheme? Use the lightness parameter {{{<<RandomColorPaletteButton lightness:0.9>>}}}
<<RandomColorPaletteButton lightness:0.9>> Bit of a goth? Seed it low.. {{{<<RandomColorPaletteButton lightness:0.2>>}}} <<RandomColorPaletteButton lightness:0.2>>

Want a heavily saturated scheme? Use the saturation parameter. {{{<<RandomColorPaletteButton saturation:0.8>>}}}
<<RandomColorPaletteButton saturation:0.8>>

Jons favourite settings..
<<RandomColorPaletteButton saturation:0.6 darkest:0.1 lightness:0.9 huevariance:1>>
!The macros
{{{<<RandomColorPalette>>}}} is a run once macro which picks a random colour scheme for your TiddlyWiki, saving a new ColorPalette tiddler on completion.
This is useful if you want the color palette to change when a certain tiddler is opened. If your particular whacky you could make it change every time you display a new tiddler by adding the macro to the ViewTemplate.

{{{<<RandomColorPaletteButton>>}}} gives you a button that you can be used to pick a random colour scheme.
/***
|''Name''|NewFromHereMacro|
|''Version''|0.9|
|''Status''|stable|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#NewFromHereMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|Creates a new tiddler, using the originating tiddler's title as a prefix.|
!Note
This macro is based upon the [[NewHerePlugin|http://mptw.tiddlyspot.com/#NewHerePlugin]].
!Usage
{{{
<<newFromHere [parameters]>>
}}}
Parameter handling is identical to the [[NewTiddler|http://www.tiddlywiki.com/#NewTiddlerMacro]] macro.
!!Example
<<newFromHere>>
<<newFromHere label:"new tiddler from here">>
!Revision History
!!v0.9 (2007-12-27)
* initial release
!To Do
* custom separator character
* optional default tag
!Code
***/
//{{{
config.macros.newFromHere = {
	separator: ": "
};

config.macros.newFromHere.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	wikify("<<newTiddler " + paramString + " title:[[" + tiddler.title + this.separator + "]]>>",
		place,null,tiddler);
};
//}}}
/***
|Name:|NewHerePlugin|
|Description:|Creates the new here and new journal macros|
|Version:|3.0a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.macros, {
  newHere: {
    handler: function(place,macroName,params,wikifier,paramString,tiddler) {
      wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
    }
  },
  newJournalHere: {
    handler: function(place,macroName,params,wikifier,paramString,tiddler) {
      wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
    }
  }
});

//}}}
/***
|Name:|NewMeansNewPlugin|
|Description:|If 'New Tiddler' already exists then create 'New Tiddler (1)' and so on|
|Version:|1.1.1a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/empty.html#NewMeansNewPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Note: I think this should be in the core
***/
//{{{

// change this or set config.newMeansNewForJournalsToo it in MptwUuserConfigPlugin
if (config.newMeansNewForJournalsToo == undefined) config.newMeansNewForJournalsToo = true;

String.prototype.getNextFreeName = function() {
  numberRegExp = / \(([0-9]+)\)$/;
  var match = numberRegExp.exec(this);
  if (match) {
  var num = parseInt(match[1]) + 1;
    return this.replace(numberRegExp," ("+num+")");
  }
  else {
    return this + " (1)";
  }
}

config.macros.newTiddler.checkForUnsaved = function(newName) {
  var r = false;
  story.forEachTiddler(function(title,element) {
    if (title == newName)
      r = true;
  });
  return r;
}

config.macros.newTiddler.getName = function(newName) {
  while (store.getTiddler(newName) || config.macros.newTiddler.checkForUnsaved(newName))
    newName = newName.getNextFreeName();
  return newName;
}


config.macros.newTiddler.onClickNewTiddler = function()
{
  var title = this.getAttribute("newTitle");
  if(this.getAttribute("isJournal") == "true") {
    title = new Date().formatString(title.trim());
  }

  // ---- these three lines should be the only difference between this and the core onClickNewTiddler
  if (config.newMeansNewForJournalsToo || this.getAttribute("isJournal") != "true")
    title = config.macros.newTiddler.getName(title);

  var params = this.getAttribute("params");
  var tags = params ? params.split("|") : [];
  var focus = this.getAttribute("newFocus");
  var template = this.getAttribute("newTemplate");
  var customFields = this.getAttribute("customFields");
  if(!customFields && !store.isShadowTiddler(title))
    customFields = String.encodeHashMap(config.defaultCustomFields);
  story.displayTiddler(null,title,template,false,null,null);
  var tiddlerElem = story.getTiddler(title);
  if(customFields)
    story.addCustomFields(tiddlerElem,customFields);
  var text = this.getAttribute("newText");
  if(typeof text == "string")
    story.getTiddlerField(title,"text").value = text.format([title]);
  for(var t=0;t<tags.length;t++)
    story.setTiddlerTag(title,tags[t],+1);
  story.focusTiddler(title,focus);
  return false;
};

//}}}
/***
|Name|OpenTaggedTiddlersMacro|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#OpenTaggedTiddlersMacro]]|
|Version|0.1.2|
|Author|[[one_each|http://groups.google.com/group/TiddlyWiki/browse_thread/t/77d70c4e01e7c6fa]]|
|Contributor|FND|
|License|public domain|
|~CoreVersion|1.2|
|Type|macro|
|Requires|N/A|
|Overrides|N/A|
|Description|open all tiddlers with a given tag|
!Usage
{{{
<<openAll [[tag]] ["title:..."] [closeAllFirst]>>
}}}
!Options
Although the tag is required as the first parameter, the options listed below are optional and may appear in any order.
|!Option|!Description|
|closeAllFirst|close all other tiddlers first|
|<nowiki>title:Title</nowiki>|button caption (enclose in quotation marks if the text contains spaces)|
!Examples
|!Code|!Output|
|{{{<<openAll systemConfig>>}}}|<<openAll systemConfig>>|
|{{{<<openAll systemConfig closeAllFirst>>}}}|<<openAll systemConfig closeAllFirst>>|
|{{{<<openAll systemConfig "title:Open system tiddlers">>}}}|<<openAll systemConfig "title:Open system tiddlers">>|
!Revision History
!!v0.1.1 (2005-09-01)
* initial release [[by one_each|http://groups.google.com/group/TiddlyWiki/browse_thread/t/77d70c4e01e7c6fa]] (named "openAll macro")
!!v0.1.2 (2005-06-30)
* minor code cleanup by FND
* removed {{{reverseOrder}}} parameter due to incompatibility with TiddlyWiki 2.2
* renamed to OpenTaggedTiddlersMacro
!Issues / To Do
* code cleanup / refactoring
!Code
***/
//{{{
version.extensions.openAll = {major: 0, minor: 1, revision: 1, date: new Date("Jun 30, 2007")};
config.macros.openAll = {}
config.macros.openAll.handler = function(place,macroName,params) {
	var title = "Open all " + params[0];
	var closeAllFirst = "false";
	for(var i = 1; i < params.length; i++) { // skip the first parameter
		if(params[i] == "closeAllFirst")
			closeAllFirst = "true";
		if(params[i].substring(0,6) == "title:")
			title = params[i].substring(6);
	}
	var btn = createTiddlyButton(place,title,null,onClickOpenAllMacro);
	btn.setAttribute("tag",params[0]);
	btn.setAttribute("closeAllFirst",closeAllFirst);
}

// Event handler for 'openAll' macro
function onClickOpenAllMacro(e)
{
	if (!e) var e = window.event;
	var tag = this.getAttribute("tag");
	var tagged = store.getTaggedTiddlers(tag);
	if(this.getAttribute("closeAllFirst") == "true")
		story.closeAllTiddlers();
	for(var t=tagged.length-1; t>=0; t--)
		displayTiddler(this,tagged[t].title,0,null,null,false,e.shiftKey || e.altKey);
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

http://habrahabr.ru/blogs/oracle/101003/

[[22 SQL for Modeling|http://download.oracle.com/docs/cd/B28359_01/server.111/b28313/sqlmodel.htm]]

<<rssfeed asHtml "http://sourceforge.net/export/rss2_projfiles.php?group_id=150646">>
http://padre.perlide.org/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span id='searchBar' macro="search"></span>
<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>
<!--}}}-->
/***
|''Name''|PaletteViewMacro|
|''Version''|0.2|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#PaletteViewMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|Displays color palettes.|
!Notes
There is also [[ViewPalettePlugin|http://simon.tiddlyspot.com/#ViewPalettePlugin]], which currently does not work with TiddlyWiki v2.2 though.
!Usage
{{{
<<paletteView [tiddler name]>>
}}}
!!Example
<<paletteView [[ColorPalette]]>>
!Revision History
!!v0.1 (2007-11-18)
* initial release
!!v0.2 (2007-11-20)
* limited processing to slices containing [[actual color values|http://www.w3.org/TR/CSS21/syndata.html#color-units]]
* changed fallback value to the tiddler the macro is called from (instead of using [[ColorPalette]])
!To Do
* selection list for all available palettes (tag-based)
* parameter for custom table class
* customizable column order
* documentation (e.g. using from within [[ViewTemplate]])
!Code
***/
//{{{
config.macros.paletteView = {};

config.macros.paletteView.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var title = params[0] || tiddler.title;
	//var palettes = store.getTaggedTiddlers(params[0]); // DEBUG: yet to be implemented
	var colors = store.calcAllSlices(title);
	var labels = [];
	for(var c in colors) {
		if(this.isColor(colors[c])) {
			labels.push(c);
		}
	}
	if(labels.length > 0) {
		var output = "|!Sample|!Value|!Name|h\n";
		for(var i = 0; i < labels.length; i++) {
			output += "|padding:0 4em;background-color:" + colors[labels[i]] + ";&nbsp;|"
				+ "{{{" + colors[labels[i]] + "}}}|"
				+ "[[" + labels[i] + "|" + title + "]]|\n";
		}
		wikify(output, place);
	}
};

config.macros.paletteView.isColor = function(s) {
	var colors = ["Black", "Green", "Silver", "Lime", "Gray", "Olive", "White", "Yellow",
		"Maroon", "Navy", "Red", "Blue", "Purple", "Teal", "Fuchsia", "Aqua", "Orange"];
	var match = s.match(/^#[0-9A-F]{3}$|^#[0-9A-F]{6}$|^RGB\([\d,\s]{5,}\)$/i);
	if(match) return true;
	if(colors.contains(s)) return true;
	return false;
};
//}}}
/***
|''Name''|ParagraphFormatter|
|''Description''|formatter modifying TiddlyWiki's handling of line breaks|
|''Author:''|FND|
|''Version''|0.1.1|
|''Status''|@@beta@@|
|''Source''|http://devpad.tiddlyspot.com/#ParagraphFormatter|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
!Description
This formatter modifies the way line breaks in wiki markup are rendered;
single line breaks are ignored, two line breaks result in a blank line being inserted.
!Usage
!!Examples
{{{
lorem
ipsum

dolor
sit
amet
}}}
<<<
lorem
ipsum

dolor
sit
amet
<<<
!Revision History
!!v0.1 (2008-12-03)
* initial release
!Code
***/
//{{{
(function(formatters) { //# set up alias

// modify line-break formatter
var lineBreak = formatters[formatters.findByField("name", "lineBreak")];
lineBreak.match = "<br ?/?>";
// create paragraph formatter
formatters.push({
	name: "paragraph",
	match: "\\n\\n",
	handler: function(w) {
		createTiddlyElement(w.output, "br");
		createTiddlyElement(w.output, "br");
	}
});

})(config.formatters); //# end of alias
//}}}

/***
|''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''|PasswordPromptMacro|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#PasswordPromptMacro]]|
|''Version''|0.8|
|''Author''|FND|
|''Contributors''|[[Lewcid|http://tw.lewcid.org]], [[BidiX|http://www.bidix.info]]|
|''License''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|create a prompt for password input|
<<<
''N.B.'' [[PasswordPromptMacro]] has been superseded by [[PasswordPromptPlugin]]
<<<
!Usage Notes
* styling can be customized in the [[StyleSheetPasswordPrompt]] shadow tiddler
!Revision History
!!v0.1 (2007-07-19)
* initial proof-of-concept implementation
!!v0.8 (2007-07-21)
* fixed IE issues (thanks Saq and BidiX)
* made ENTER/RETURN key trigger the password check
* various changes and improvements
!To Do
* {{{checkPassword()}}}: provide "interface" for other plugins to use this functionality (cf. {{{displayMessage()}}}) <br>&rArr; read/write password from/to custom variable ({{{config.macros.passwordPrompt.password}}}?) or use function call(??) instead of using macro parameter<br>&rArr; encryption issues!?
* fix positioning issue in IE (caused by negative margin)
* clean up code<br>&rArr; remove/fix {{{DEBUG}}} flags<br>&rArr; use {{{this}}} instead of {{{config.macros.passwordPrompt}}}
* documentation
!Code
***/
//{{{
/*
** Styles (can be customized in the StyleSheetPasswordPrompt shadow tiddler)
*/

config.shadowTiddlers.StyleSheetPasswordPrompt = "/*{{{*/\n"
	+ "#passwordPrompt {\n"
	+ "\tz-index: 100;\n"
	+ "\tposition: absolute;\n"
	+ "\ttop: 50%;\n"
	+ "\tleft: 50%;\n"
	+ "\twidth: 15em;\n"
	+ "\theight: 4.5em;\n"
	+ "\tline-height: 1.3em;\n"
	+ "\tmargin: -2em 0 0 -5em;\n"
	+ "\tborder: 2px solid #AAA;\n"
	+ "\tpadding: 10px;\n"
	+ "\ttext-align: center;\n"
	+ "\tbackground-color: #EEE;\n"
	+ "}\n"
	+ "/*}}}*/";
store.addNotification("StyleSheetPasswordPrompt", refreshStyles);

/*
** Macro Code
*/

config.macros.passwordPrompt = { label: "toggle prompt", prompt: "show/hide password prompt" };
config.macros.passwordPrompt.handler = 
function(place, macroName, params, wikifier, paramString, tiddler) {
	if(!readOnly) {
		createTiddlyButton(place, this.label, this.prompt, function() {
				// process parameters -- DEBUG: obsolete (for testing purposes only)?
				if (params[0]) {
					config.macros.passwordPrompt.password = params[0];
				} else {
					config.macros.passwordPrompt.password = "";
				}
				// toggle password prompt
				config.macros.passwordPrompt.togglePrompt(this);
				return false;
			}, null, null, this.accessKey
		);
	}
}

/*
** Main Code
*/

config.macros.passwordPrompt.togglePrompt = function() {
	var e = document.getElementById("passwordPrompt");
	if(!e) {
		// create display container for password prompt
		var r = createTiddlyElement(document.body, "form");
		r.setAttribute("id", "passwordPrompt");
		r.setAttribute("action", "");
		r.setAttribute("onsubmit", "return false"); // DEBUG: valid? obsolete (cf. i.onKeyPress)?
		// create label
		var l = createTiddlyElement(r, "label", null, null, "Enter password:");
		l.setAttribute("for", "passwordField");
		// create password field
		var i = document.createElement ("input");
		i.setAttribute("id", "passwordField");
		i.setAttribute("type","password");
		i.onkeypress = function(e) { e = e; return config.macros.passwordPrompt.checkEnter(e); };
		r.appendChild(i); // needs to be done *after* setting the type attribute
		// create separator
		createTiddlyElement(r, "br");
		// create submit button
		var b = document.createElement ("input");
		b.setAttribute("type","button");
		b.setAttribute("value", "ok");
		b.onclick = config.macros.passwordPrompt.checkPassword;
		r.appendChild(b); // needs to be done *after* setting the type attribute
		// select password field
		i.focus();
	} else {
		// remove input field
		e.parentNode.removeChild(e);
	}
}

config.macros.passwordPrompt.checkPassword = function() {
	var e = document.getElementById("passwordField");
	if(e.value === config.macros.passwordPrompt.password) {
		config.macros.passwordPrompt.togglePrompt();
		alert("password correct"); // DEBUG: for testing purposes only
	}
	else
		alert("password incorrect");
}

config.macros.passwordPrompt.checkEnter = function(e) {
	// retrieve key code
	if(!e)
		var e = window.event;
	if(e.keyCode)
		var code = e.keyCode;
	else if(e.which)
		var code = e.which;
	// check key code
	if(code == 13) // ENTER key
		this.checkPassword();
	return true;
}
//}}}
/***
|''Name''|PasswordPromptPlugin|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#PasswordPromptMacro]]|
|''Version''|0.95|
|''Author''|FND|
|''Contributors''|[[Lewcid|http://tw.lewcid.org]], [[BidiX|http://www.bidix.info]], [[Loic|http://dachary.org]]|
|''License''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|create a prompt for masked password inputs|
!Usage Notes
* {{{passwordPrompt.handler(promptString, callbackFunction);}}}, whereas the callback function takes the prompt's inputs as parameter
* styling can be customized in the [[StyleSheetPasswordPrompt]] shadow tiddler
!Revision History
!!v0.1 (2007-07-19)
* initial proof-of-concept implementation
!!v0.8 (2007-07-21)
* fixed IE issues (thanks Saq and BidiX)
* made ENTER/RETURN key trigger the password check
* various changes and improvements
!!v0.9 (2007-07-22)
* converted from a macro to a general-purpose component (function library)
!!v0.95 (2007-08-05)
* corrected callback usage (thanks Loic)
!To Do
* add cancel button
* clean up code<br>&rArr; remove/fix {{{DEBUG}}} flags<br>&rArr; use {{{this.}}} instead of {{{passwordPrompt.}}}
* documentation
* fix positioning issue in IE (not perfectly centered due to issues with negative margin)
!Code
***/
//{{{
/*
** Styles (can be customized in the StyleSheetPasswordPrompt shadow tiddler)
*/

config.shadowTiddlers.StyleSheetPasswordPrompt = "/*{{{*/\n"
	+ "#passwordPrompt {\n"
	+ "\tz-index: 100;\n"
	+ "\tposition: absolute;\n"
	+ "\ttop: 50%;\n"
	+ "\tleft: 50%;\n"
	+ "\twidth: 15em;\n"
	+ "\theight: 4.5em;\n"
	+ "\tline-height: 1.3em;\n"
	+ "\tmargin: -2em 0 0 -5em;\n"
	+ "\tborder: 2px solid #AAA;\n"
	+ "\tpadding: 10px;\n"
	+ "\ttext-align: center;\n"
	+ "\tbackground-color: #EEE;\n"
	+ "}\n\n"
	+ "#passwordPrompt label {\n"
	+ "\tdisplay: block;\n"
	+ "}\n\n"
	+ "* html #passwordPrompt { /* IE fix */\n"
	+ "\tmargin: 0;\n"
	+ "}\n"
	+ "/*}}}*/";
store.addNotification("StyleSheetPasswordPrompt", refreshStyles);

/*
** Password Prompt class
*/

passwordPrompt = {}

passwordPrompt.handler = function(promptString, callback) {
	passwordPrompt.togglePrompt(promptString, callback);
	return false; // DEBUG: obsolete/nonsense!?
}

passwordPrompt.togglePrompt = function(promptString, callback) {
	var e = document.getElementById("passwordPrompt");
	if(!e) {
		// create display container for password prompt
		var r = createTiddlyElement(document.body, "form");
		r.setAttribute("id", "passwordPrompt");
		r.setAttribute("action", "");
		r.setAttribute("onsubmit", "return false"); // DEBUG: valid? obsolete (cf. i.onKeyPress)?
		// create label
		var l = createTiddlyElement(r, "label", null, null, promptString);
		l.setAttribute("for", "passwordField");
		// create password field
		var i = document.createElement("input");
		i.setAttribute("id", "passwordField");
		i.setAttribute("type","password");
		i.onkeypress = function(e, callback) { e = e || window.event; return passwordPrompt.checkEnter(e, callback); }; // DEBUG: "e = e || window.event;"??
		r.appendChild(i); // needs to be done *after* setting the type attribute
		// create separator
		createTiddlyElement(r, "br");
		// create submit button
		var b = document.createElement ("input");
		b.setAttribute("type","button");
		b.setAttribute("value", "ok");
		b.onclick = function() { passwordPrompt.checkPassword(callback); }
		r.appendChild(b); // needs to be done *after* setting the type attribute
		// select password field
		i.focus();
	} else {
		// remove input field
		e.parentNode.removeChild(e);
	}
	return false; // DEBUG: obsolete/nonsense!?
}

passwordPrompt.checkPassword = function(callback) {
	var e = document.getElementById("passwordField");
	passwordPrompt.togglePrompt();
	return callback(e.value);
}

passwordPrompt.checkEnter = function(e, callback) {
	// retrieve key code
	if(!e)
		var e = window.event;
	if(e.keyCode)
		var code = e.keyCode;
	else if(e.which)
		var code = e.which;
	// check key code
	if(code == 13) // ENTER key
		this.checkPassword(callback);
	// do not suppress key presses
	return true;
}
//}}}
//{{{
passwordPrompt.handler("test", passwordPromptTest);

function passwordPromptTest(inputs) {
	if(inputs === null)
		alert("'inputs' is null");
	else if(inputs === "")
		alert("'inputs' is empty");
	else
		alert("'inputs' is\n" + inputs);
}
//}}}
This is the sandbox for testing the [[PasswordPromptMacro]].

/%<<passwordPrompt>> (password: none)%/
/%<<passwordPrompt "test">> (password: "test")%/
http://perlrussia.ru/article/brians-guide/
http://dev.perl.org/perl6/faq.html
http://perlgeek.de/blog-en/perl-6/
http://www.perlfoundation.org/perl6/index.cgi?perl_6
http://www.jnthn.net/articles.shtml слайды Вортингтона - супер
http://6guts.wordpress.com/
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.5 (2006-02-05)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''Macros:''|[[ForEachTiddlerMacro]] v1.0.5|
|''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.5
** 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) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// 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 "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 = "";
	for (var i = 0; i < count; i++) {
		var tiddler = tiddlers[i];
		text += func(tiddler, context, count, i);
	}
	   
	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
	};
};

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

	return tiddlyWiki;
};


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

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

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

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

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

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

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

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


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

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


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

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

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

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

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

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


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



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


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

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

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

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


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


} // of "install only once"

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


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

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

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

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

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

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
/***
|Name|HoverMenuPlugin|
|Created by|SaqImtiaz|
|Location|http://lewcid.googlepages.com/lewcid.html#HoverMenuPlugin|
|Version|1.11|
|Requires|~TW2.x|
!Description:
Provides a hovering menu on the edge of the screen for commonly used commands, that scrolls with the page.

!Demo:
Observe the hovering menu on the right edge of the screen.

!Installation:
Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.
To customize your HoverMenu, edit the HoverMenu shadow tiddler.

To customize whether the menu sticks to the right or left edge of the screen, and its start position, edit the HoverMenu configuration settings part of the code below. It's well documented, so don't be scared!

The menu has an id of hoverMenu, in case you want to style the buttons in it using css.

!Notes:
Since the default HoverMenu contains buttons for toggling the side bar and jumping to the top of the screen and to open tiddlers, the ToggleSideBarMacro, JumpMacro and the JumpToTopMacro are included in this tiddler, so you dont need to install them separately. Having them installed separately as well could lead to complications.

If you dont intend to use these three macros at all, feel free to remove those sections of code in this tiddler.

!To Do:
* rework code to allow multiple hovering menus in different positions, horizontal etc.
* incorporate code for keyboard shortcuts that correspond to the buttons in the hovermenu

!History:
*03-08-06,  ver 1.11: fixed error with button tooltips
*27-07-06, ver 1.1 : added JumpMacro to hoverMenu
*23-07-06

!Code
***/

/***
start HoverMenu plugin code
***/
//{{{
config.hoverMenu={};
//}}}

/***
HoverMenu configuration settings
***/
//{{{
config.hoverMenu.settings={
               align: 'right',    //align menu to right or left side of screen, possible values are 'right' and 'left'               
               x: 1,              // horizontal distance of menu from side of screen, increase to your liking.
               y: 158            //vertical distance of menu from top of screen at start, increase or decrease to your liking
               };
//}}}

//{{{
//continue HoverMenu plugin code
config.hoverMenu.handler=function()
{
               var theMenu = createTiddlyElement(document.getElementById("contentWrapper"), "div","hoverMenu");
               theMenu.setAttribute("refresh","content");
               theMenu.setAttribute("tiddler","HoverMenu");
               var menuContent = store.getTiddlerText("HoverMenu");
               wikify(menuContent,theMenu);

	       var Xloc = this.settings.x;
	       Yloc =this.settings.y;
	       var ns = (navigator.appName.indexOf("Netscape") != -1);
	       function SetMenu(id)
                        {
		        var GetElements=document.getElementById?document.getElementById(id):document.all?document.all[id]:document.layers[id];
		        if(document.layers)GetElements.style=GetElements;
		        GetElements.sP=function(x,y){this.style[config.hoverMenu.settings.align]=x +"px";this.style.top=y +"px";};
		        GetElements.x = Xloc;
		        GetElements.y = findScrollY();
		        GetElements.y += Yloc;
		        return GetElements;
	                }
               window.LoCate_XY=function()
                        {
		        var pY =  findScrollY();
                        ftlObj.y += (pY + Yloc - ftlObj.y)/15;
		        ftlObj.sP(ftlObj.x, ftlObj.y);
		        setTimeout("LoCate_XY()", 10);
	                }
               ftlObj = SetMenu("hoverMenu");
	       LoCate_XY();
};

window.old_lewcid_hovermenu_restart = restart;
restart = function()
{
               window.old_lewcid_hovermenu_restart();
               config.hoverMenu.handler();
};

setStylesheet(
"#hoverMenu  .button, #hoverMenu  .tiddlyLink {border:none; font-weight:bold; background:#18f; color:#FFF; padding:0 5px; float:right; margin-bottom:4px;}\n"+
"#hoverMenu .button:hover, #hoverMenu .tiddlyLink:hover {font-weight:bold; border:none; color:#fff; background:#000; padding:0 5px; float:right; margin-bottom:4px;}\n"+
"#hoverMenu .button {width:100%; text-align:center}"+
"#hoverMenu { position:absolute; width:7px;}\n"+
"\n","hoverMenuStyles");


config.macros.renameButton={};
config.macros.renameButton.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{

               if (place.lastChild.tagName!="BR")
                     {
                      place.lastChild.firstChild.data = params[0];
                      if (params[1]) {place.lastChild.title = params[1];}
                     }
};

config.shadowTiddlers["HoverMenu"]="<<top>>\n<<toggleSideBar>><<renameButton '>' >>\n<<jump j '' top>>\n<<saveChanges>><<renameButton s 'Save TiddlyWiki'>>\n<<newTiddler>><<renameButton n>>\n";
//}}}
//end HoverMenu plugin code

//Start ToggleSideBarMacro 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");
//}}}
//end ToggleSideBarMacro code

//start JumpToTopMacro code
//{{{
config.macros.top={};
config.macros.top.handler=function(place,macroName)
{
               createTiddlyButton(place,"^","jump to top",this.onclick);
}
config.macros.top.onclick=function()
{
               window.scrollTo(0,0);
};

config.commands.top =
{
               text:" ^ ",
               tooltip:"jump to top"
};

config.commands.top.handler = function(event,src,title)
{
               window.scrollTo(0,0);
}
//}}}
//end JumpToStartMacro code

//start JumpMacro code
//{{{
config.macros.jump= {};
config.macros.jump.handler = function (place,macroName,params,wikifier,paramString,tiddler)
{
        var label = (params[0] && params[0]!=".")? params[0]: 'jump';
        var tooltip = (params[1] && params[1]!=".")? params[1]: 'jump to an open tiddler';
        var top = (params[2] && params[2]=='top') ? true: false;        

        var btn =createTiddlyButton(place,label,tooltip,this.onclick);
        if (top==true)
              btn.setAttribute("top","true")
}

config.macros.jump.onclick = function(e)
{
        if (!e) var e = window.event;
        var theTarget = resolveTarget(e);
        var top = theTarget.getAttribute("top");
	var popup = Popup.create(this);
	if(popup)
		{
                 if(top=="true")
                                {createTiddlyButton(createTiddlyElement(popup,"li"),'Top ↑','Top of TW',config.macros.jump.top);
                                 createTiddlyElement(popup,"hr");}
		
		story.forEachTiddler(function(title,element) {
			createTiddlyLink(createTiddlyElement(popup,"li"),title,true);
			});
                }
	Popup.show(popup,false);
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return false;
}

config.macros.jump.top = function()
{
       window.scrollTo(0,0);
}
//}}}
//end JumpMacro code

//utility functions
//{{{
Popup.show = function(unused,slowly)
{
	var curr = Popup.stack[Popup.stack.length-1];
	var rootLeft = findPosX(curr.root);
	var rootTop = findPosY(curr.root);
	var rootHeight = curr.root.offsetHeight;
	var popupLeft = rootLeft;
	var popupTop = rootTop + rootHeight;
	var popupWidth = curr.popup.offsetWidth;
	var winWidth = findWindowWidth();
        if (isChild(curr.root,'hoverMenu'))
              var x = config.hoverMenu.settings.x;
        else
              var x = 0;
	if(popupLeft + popupWidth+x > winWidth)
		popupLeft = winWidth - popupWidth -x;
        if (isChild(curr.root,'hoverMenu'))
  	        {curr.popup.style.right = x + "px";}
        else
                curr.popup.style.left = popupLeft + "px";
	curr.popup.style.top = popupTop + "px";
	curr.popup.style.display = "block";
	addClass(curr.root,"highlight");
	if(config.options.chkAnimate)
		anim.startAnimating(new Scroller(curr.popup,slowly));
	else
		window.scrollTo(0,ensureVisible(curr.popup));
}

window.isChild = function(e,parentId) {
        while (e != null) {
                var parent = document.getElementById(parentId);
                if (parent == e) return true;
                e = e.parentNode;
                }
        return false;
};
//}}}
/***
| Name:|QuickOpenTagPlugin|
| Purpose:|Makes tag links into a Taggly style open tag plus a normal style drop down menu|
| Creator:|SimonBaird|
| Source:|http://simonbaird.com/mptw/#QuickOpenTagPlugin|
| Requires:|TW 2.x|
| Version|1.1 (7-Feb-06)|

!History
* Version 1.1 (07/02/2006)
** Fix Firefox 1.5.0.1 crashes
** Updated by ~BidiX[at]~BidiX.info
* Version 1.0 (?/01/2006)
** First release

***/
//{{{

//⊻ ⊽ ⋁ ▼ 

window.createTagButton_orig_mptw = createTagButton;
window.createTagButton = function(place,tag,excludeTiddler) {
 var sp = createTiddlyElement(place,"span",null,"quickopentag");
 createTiddlyLink(sp,tag,true,"button");
 var theTag = createTiddlyButton(sp,config.macros.miniTag.dropdownchar,config.views.wikified.tag.tooltip.format([tag]),onClickTag);
 theTag.setAttribute("tag",tag);
 if(excludeTiddler)
 	theTag.setAttribute("tiddler",excludeTiddler);
 return(theTag);
};

config.macros.miniTag = {handler:function(place,macroName,params,wikifier,paramString,tiddler) {
 var tagged = store.getTaggedTiddlers(tiddler.title);
 if (tagged.length > 0) {
 	var theTag = createTiddlyButton(place,config.macros.miniTag.dropdownchar,config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);
 	theTag.setAttribute("tag",tiddler.title);
 	theTag.className = "miniTag";
 }
}};

config.macros.miniTag.dropdownchar = (document.all?"▼":"▾"); // the fat one is the only one that works in IE

config.macros.allTags.handler = function(place,macroName,params)
{
 var tags = store.getTags();
 var theDateList = createTiddlyElement(place,"ul",null,null,null);
 if(tags.length === 0)
 	createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);
 for (var t=0; t<tags.length; t++)
 {
 	var theListItem =createTiddlyElement(theDateList,"li",null,null,null);
 	var theLink = createTiddlyLink(theListItem,tags[t][0],true);
 	var theCount = " (" + tags[t][1] + ")";
 	theLink.appendChild(document.createTextNode(theCount));

 	var theDropDownBtn = createTiddlyButton(theListItem," "+config.macros.miniTag.dropdownchar,this.tooltip.format([tags[t][0]]),onClickTag);
 	theDropDownBtn.setAttribute("tag",tags[t][0]);
 }
};


setStylesheet(
 ".quickopentag { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }\n"+
 ".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }\n"+
 ".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}\n"+
 "a.miniTag {font-size:150%;}\n"+
 "",
"QuickOpenTagStyles");

//}}}

/***
<html>&#x22bb; &#x22bd; &#x22c1; &#x25bc; &#x25be;</html>
***/
/***
''SearchOptionsPlugin for TiddlyWiki version 2.0''
^^author: Eric Shulman - ELS Design Studios
source: http://www.TiddlyTools.com/#SearchOptionsPlugin
license: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^

The TiddlyWiki search function normally looks in both tiddler titles and tiddler body content ('text').  However, narrowing the search so that it examines only titles or only text, or expanding the search to include text contained in tiddler tags can be very helpful, especially when searching on common words or phrases.  In addition, it is often useful for the search results to show tiddlers with matching titles before tiddlers that contain matching text or tags.

!!!!!Usage
<<<
This plugin adds checkboxes (see below and in AdvancedOptions) to let you selectively configure the TiddlyWiki search function to just examine any combination of tiddler titles, text, or tags.  It also provides an option to switch the search results order between 'titles mixed in' (default) and 'titles shown first', as well as an option display the search results as a list of links (in an auto-generated "SearchResults" tiddler), rather than actually displaying all matching tiddlers.  You can also enable/disable the "incremental search" (key-by-key searching), so that a search is only initiated when you press the ENTER key or click on the "search:" prompt text.
<<<
!!!!!Configuration
<<<
In additional to the checkboxes in AdvancedOptions, a self-contained control panel is included here for your convenience:
<<option chkSearchTitles>> Search tiddler titles
<<option chkSearchText>> Search tiddler text
<<option chkSearchTags>> Search in tiddler tags
<<option chkSearchTitlesFirst>> Show title matches first
<<option chkSearchList>> Show list of matching tiddlers
<<option chkSearchIncremental>> Incremental searching
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''SearchOptionsPlugin'' (tagged with <<tag systemConfig>>)
^^documentation and javascript for SearchOptionsPlugin handling^^

When installed, this plugin automatically adds checkboxes in the AdvancedOptions shadow tiddler so you can enable/disable the extended search behavior.  However, if you have customized your AdvancedOptions, you will need to manually add {{{<<option chkSearchTitles>>}}},  {{{<<option chkSearchText>>}}} and {{{<<option chkSearchTitlesFirst>>}}}  (with suitable prompt text) to your customized tiddler.
<<<
!!!!!Revision History
<<<
''2006.02.03 [2.2.1]''
rewrite timeout clearing code and blank search text handling to match 2.0.4 core release changes.  note that core no longer permits "blank=all" searches, so neither does this plugin.  To search for all, use "." with text patterns enabled.
''2006.02.02 [2.2.0]''
in search.handler(), KeyHandler() function clears 'left over' timeout when search input is < 3 chars.  Prevents searching on shorter text when shortened by rapid backspaces (<500msec)
''2006.02.01 [2.1.9]''
in Story.prototype.search(), correct inverted logic for using/not using regular expressions when searching
also, blank search text now presents "No search text.  Continue anyway?" confirm() message box, so search on blank can still be processed if desired by user.
''2006.02.01 [2.1.8]''
in doSearch(), added alert/return if search text is blank
''2006.01.20 [2.1.7]''
fixed setting of config.macros.search.reportTitle so that Tweaks can override it.
''2006.01.19 [2.1.6]''
improved SearchResults formatting, added a "search again" form to the report (based on a suggestion from MorrisGray)
define results report title using config.macros.search.reportTitle instead of hard-coding the tiddler title
''2006.01.18 [2.1.5]''
Created separate functions for reportSearchResults(text,matches) and discardSearchResults(), so that other developers can create alternative report generators.
''2006.01.17 [2.1.4]''
Use regExp.search() instead of regExp.test() to scan for matches.  Correctd the problem where only half the matching tiddlers (the odd-numbered ones) were being reported.
''2006.01.15 [2.1.3]''
Added information (date/time, username, search options used) to SearchResults output
''2006.01.10 [2.1.2]''
use displayTiddlers() to render matched tiddlers.  This lets you display multiple matching tiddlers, even if SinglePageModePlugin is enabled.
''2006.01.08 [2.1.1]''
corrected invalid variable reference, "txt.value" to "text" in story.search()
''2006.01.08 [2.1.0]''
re-write to match new store.search(), store.search.handler() and story.search() functions.
''2005.12.30 [2.0.0]''
Upgraded to TW2.0
when rendering SearchResults tiddler, closeTiddler() first to ensure display is refreshed.
''2005.12.26 [1.4.0]''
added option to search for matching text in tiddler tags
''2005.12.21 [1.3.7]''
use \\ to 'escape' single quotes in tiddler titles when generating "Open all matching tiddlers" link.  Also, added access key: "O", to trigger "open all" link.
Based on a suggestion by UdoBorkowski.
''2005.12.18 [1.3.6]''
call displayMessage() AFTER showing matching tiddlers so message is not cleared too soon
''2005.12.17 [1.3.5]''
if no matches found, just display message and delete any existing SearchResults tiddler.
''2005.12.17 [1.3.4]''
use """{{{"""  and """}}}""" to 'escape' display text in SearchResults tiddler to ensure that formatting contained in search string is not rendered 
Based on a suggestion by UdoBorkowski.
''2005.12.14 [1.3.3]''
tag SearchResults tiddler with 'excludeSearch' so it won't list itself in subsequent searches
Based on a suggestion by UdoBorkowski.
''2005.12.14 [1.3.2]''
added "open all matching tiddlers..." link to search results output.
Based on a suggestion by UdoBorkowski.
''2005.12.10 [1.3.1]''
added "discard search results" link to end of search list tiddler output for quick self-removal of 'SearchResults' tiddler.
''2005.12.01 [1.3.0]''
added chkSearchIncremental to enable/disable 'incremental' searching (i.e., search after each keystroke) (default is ENABLED).
added handling for Enter key so it can be used to start a search.
Based on a suggestion by LyallPearce
''2005.11.25 [1.2.1]''
renamed from SearchTitleOrTextPlugin to SearchOptionsPlugin
''2005.11.25 [1.2.0]''
added chkSearchList option
Based on a suggestion by RodneyGomes
''2005.10.19 [1.1.0]''
added chkSearchTitlesFirst option.
Based on a suggestion by ChristianHauck
''2005.10.18 [1.0.0]''
Initial Release
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].
Based on a suggestion by LyallPearce.
<<<
!!!!!Code
***/
//{{{
version.extensions.SearchTitleOrText = {major: 2, minor: 2, revision: 1, date: new Date(2006,2,3)};
//}}}

//{{{
if (config.options.chkSearchTitles==undefined) config.options.chkSearchTitles=true;
if (config.options.chkSearchText==undefined) config.options.chkSearchText=true;
if (config.options.chkSearchTags==undefined) config.options.chkSearchTags=true;
if (config.options.chkSearchTitlesFirst==undefined) config.options.chkSearchTitlesFirst=false;
if (config.options.chkSearchList==undefined) config.options.chkSearchList=false;
if (config.options.chkSearchIncremental==undefined) config.options.chkSearchIncremental=true;

config.shadowTiddlers.AdvancedOptions += "\n<<option chkSearchTitles>> Search in tiddler titles";
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSearchText>> Search in tiddler text";
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSearchTags>> Search in tiddler tags";
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSearchTitlesFirst>> Search results show title matches first";
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSearchList>> Search results show list of matching tiddlers";
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSearchIncremental>> Incremental searching";
//}}}

//{{{
if (config.macros.search.reportTitle==undefined)
	config.macros.search.reportTitle="SearchResults";
//}}}

//{{{
config.macros.search.handler = function(place,macroName,params)
{
	var lastSearchText = "";
	var searchTimeout = null;
	var doSearch = function(txt)
		{
		if (txt.value.length>0)
			{
			story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);
			lastSearchText = txt.value;
			}
		};
	var clickHandler = function(e)
		{
		doSearch(this.nextSibling);
		return false;
		};
	var keyHandler = function(e)
		{
		if (!e) var e = window.event;
		switch(e.keyCode)
			{
			case 13: // ELS: handle enter key
				doSearch(this);
				break;
			case 27:
				this.value = "";
				clearMessage();
				break;
			}
		if (config.options.chkSearchIncremental)
			{
			if(this.value.length > 2)
				{
				if(this.value != lastSearchText)
					{
					if(searchTimeout) clearTimeout(searchTimeout);
					var txt = this;
					searchTimeout = setTimeout(function() {doSearch(txt);},500);
					}
				}
			else
				if(searchTimeout) clearTimeout(searchTimeout);
			}
		};
	var focusHandler = function(e)
		{
		this.select();
		};
	var btn = createTiddlyButton(place,this.label,this.prompt,clickHandler);
	var txt = createTiddlyElement(place,"input",null,null,null);
	if(params[0])
		txt.value = params[0];
	txt.onkeyup = keyHandler;
	txt.onfocus = focusHandler;
	txt.setAttribute("size",this.sizeTextbox);
	txt.setAttribute("accessKey",this.accessKey);
	txt.setAttribute("autocomplete","off");
	if(config.browser.isSafari)
		{
		txt.setAttribute("type","search");
		txt.setAttribute("results","5");
		}
	else
		txt.setAttribute("type","text");
}
//}}}

//{{{
Story.prototype.search = function(text,useCaseSensitive,useRegExp)
{
	highlightHack = new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");
	var matches = store.search(highlightHack,"title","excludeSearch");
	var q = useRegExp ? "/" : "'";
	clearMessage();
	if (!matches.length) {
		if (config.options.chkSearchList) discardSearchResults();
		displayMessage(config.macros.search.failureMsg.format([q+text+q]));
	} else {
		if (config.options.chkSearchList) 
			reportSearchResults(text,matches);
		else {
			var titles = []; for(var t=0; t<matches.length; t++) titles.push(matches[t].title);
			this.closeAllTiddlers(); story.displayTiddlers(null,titles);
			displayMessage(config.macros.search.successMsg.format([matches.length, q+text+q]));
		}
	}
	highlightHack = null;
}
//}}}

//{{{
TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag)
{
	var candidates = this.reverseLookup("tags",excludeTag,false,sortField);

	// scan for matching titles
	var title_results = [];
	if (config.options.chkSearchTitles)
		for(var t=0; t<candidates.length; t++)
			if(candidates[t].title.search(searchRegExp)!=-1)
				title_results.push(candidates[t]);

	// scan for matching text
	var text_results = [];
	if (config.options.chkSearchText)
		for(var t=0; t<candidates.length; t++)
			if(candidates[t].text.search(searchRegExp)!=-1)
				text_results.push(candidates[t]);

	// scan for matching tags
	var tag_results = [];
	if (config.options.chkSearchTags)
		for(var t=0; t<candidates.length; t++)
			if(candidates[t].tags.join(" ").search(searchRegExp)!=-1)
				tag_results.push(candidates[t]);

	// merge the results, eliminating redundant matches
	var results = [];
	for(var t=0; t<title_results.length; t++) results.pushUnique(title_results[t]);
	for(var t=0; t<text_results.length; t++) results.pushUnique(text_results[t]);
	for(var t=0; t<tag_results.length; t++) results.pushUnique(tag_results[t]);

	// if not 'titles first',  re-sort results to so titles, text and tag matches are mixed together
	if(!sortField) sortField = "title";
	var bySortField=function (a,b) {if(a[sortField] == b[sortField]) return(0); else return (a[sortField] < b[sortField]) ? -1 : +1; }
	if (!config.options.chkSearchTitlesFirst) results.sort(bySortField);
	return results;
}
//}}}

// // ''REPORT GENERATOR''
//{{{
if (!window.reportSearchResults) window.reportSearchResults=function(text,matches)
{
	var title=config.macros.search.reportTitle
	var q = config.options.chkRegExpSearch ? "/" : "'";
	var body="";

	// summary: nn tiddlers found matching '...', options used
	body+="''"+config.macros.search.successMsg.format([matches.length,q+"{{{"+text+"}}}"+q])+"''\n";
	body+="^^//searched in:// ";
	body+=(config.options.chkSearchTitles?"''titles'' ":"");
	body+=(config.options.chkSearchText?"''text'' ":"");
	body+=(config.options.chkSearchTags?"''tags'' ":"");
	if (config.options.chkCaseSensitiveSearch||config.options.chkRegExpSearch) {
		body+=" //with options:// ";
		body+=(config.options.chkCaseSensitiveSearch?"''case sensitive'' ":"");
		body+=(config.options.chkRegExpSearch?"''text patterns'' ":"");
	}
	body+="^^";

	// numbered list of links to matching tiddlers
	body+="\n<<<";
	for(var t=0;t<matches.length;t++) body+="\n# [["+matches[t].title+"]]";
	body+="\n<<<\n";

	// open all matches button
	body+="<html><input type=\"button\" href=\"javascript:;\" ";
	body+="onclick=\"story.displayTiddlers(null,["
	for(var t=0;t<matches.length;t++)
		body+="'"+matches[t].title.replace(/\'/mg,"\\'")+"'"+((t<matches.length-1)?", ":"");
	body+="],1);\" ";
	body+="accesskey=\"O\" ";
	body+="value=\"open all matching tiddlers\"></html> ";

	// discard search results button
	body+="<html><input type=\"button\" href=\"javascript:;\" ";
	body+="onclick=\"story.closeTiddler('"+title+"'); store.deleteTiddler('"+title+"');\" ";
	body+="value=\"discard "+title+"\"></html>";

	// search again
	body+="\n\n----\n";
	body+="<<search \""+text+"\">> ";
	body+="<<option chkSearchTitles>>titles ";
	body+="<<option chkSearchText>>text ";
	body+="<<option chkSearchTags>>tags";
	body+="<<option chkCaseSensitiveSearch>>case-sensitive ";
	body+="<<option chkRegExpSearch>>text patterns";

	// create/update the tiddler
	var tiddler=store.getTiddler(title); if (!tiddler) tiddler=new Tiddler();
	tiddler.set(title,body,config.options.txtUserName,(new Date()),"excludeLists excludeSearch");
	store.addTiddler(tiddler); story.closeTiddler(title);

	// use alternate "search again" label in <<search>> macro
	var oldprompt=config.macros.search.label;
	config.macros.search.label="search again";

	// render tiddler
	story.displayTiddler(null,title,1); // force refresh

	// restore standard search label
	config.macros.search.label=oldprompt;

}

if (!window.discardSearchResults) window.discardSearchResults=function()
{
	// remove the tiddler
	story.closeTiddler(config.macros.search.reportTitle);
	store.deleteTiddler(config.macros.search.reportTitle);
}
//}}}


config.macros.listTags = { text: "Hello" };
config.macros.listTags.handler = function(place,macroName,params)
{
 var tagged = store.getTaggedTiddlers(params[0]);
 var ul = createTiddlyElement(place,"ul",null,null,"");
 for(var r=0;r<tagged.length;r++)
 {
 var li = createTiddlyElement(ul,"li",null,null,"");
 createTiddlyLink(li,tagged[r].title,true);
 }
}
/***
Pre-check AutoSave
***/
//{{{
config.options.chkAutoSave = true;
//}}}
/***
Pre-check SinglePageMode
***/
//{{{
config.options.chkSinglePageMode=false;
//}}}

/***
Pre-check SearchList
***/
//{{{
config.options.chkSearchList=true;
//}}}
/***
Change "close" message to "X"
***/
//{{{
config.messages.messageClose.text = "X";
//}}}
/***
Remove default "The tiddler '%0' doesn't yet exist. Double-click to create it" Tiddler body message
***/
//{{{
config.views.wikified.defaultText = ""; 
//}}}
http://softwareas.com/tiddlywiki-quiz-plugin
/***
|Name:|PrettyDatesPlugin|
|Description:|Provides a new date format ('pppp') that displays times such as '2 days ago'|
|Version:|1.0a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#PrettyDatesPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Notes
* If you want to you can rename this plugin. :) Some suggestions: LastUpdatedPlugin, RelativeDatesPlugin, SmartDatesPlugin, SexyDatesPlugin.
* Inspired by http://ejohn.org/files/pretty.js
***/
//{{{
Date.prototype.prettyDate = function() {
  var diff = (((new Date()).getTime() - this.getTime()) / 1000);
  var day_diff = Math.floor(diff / 86400);

  if (isNaN(day_diff))      return "";
  else if (diff < 0)        return "in the future";
  else if (diff < 60)       return "just now";
  else if (diff < 120)      return "1 minute ago";
  else if (diff < 3600)     return Math.floor(diff/60) + " minutes ago";
  else if (diff < 7200)     return "1 hour ago";
  else if (diff < 86400)    return Math.floor(diff/3600) + " hours ago";
  else if (day_diff == 1)   return "Yesterday";
  else if (day_diff < 7)    return day_diff + " days ago";
  else if (day_diff < 14)   return  "a week ago";
  else if (day_diff < 31)   return Math.ceil(day_diff/7) + " weeks ago";
  else if (day_diff < 62)   return "a month ago";
  else if (day_diff < 365)  return "about " + Math.ceil(day_diff/31) + " months ago";
  else if (day_diff < 730)  return "a year ago";
  else                      return Math.ceil(day_diff/365) + " years ago";
}

Date.prototype.formatString_orig_mptw = Date.prototype.formatString;

Date.prototype.formatString = function(template) {
  return this.formatString_orig_mptw(template).replace(/pppp/,this.prettyDate());
}

// for MPTW. otherwise edit your ViewTemplate as required.
// config.mptwDateFormat = 'pppp (DD/MM/YY)';
config.mptwDateFormat = 'pppp';

//}}}
/***
|''Name''|PrintMacro|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#PrintMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|prints the current document|
!Usage
{{{
<<print [label] [tooltip] [class] [access key]>>
}}}
<<print>>
!Revision History
!!v0.1 (2007-12-10)
* initial release
!Code
***/
//{{{
config.macros.print = {
	label: "print",
	prompt: "print document",
	buttonClass: "",
	accessKey: ""
};

config.macros.print.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var label = params[0] || this.label;
	var prompt = params[1] || this.prompt;
	var buttonClass = params[2] || this.buttonClass;
	var accessKey = params[3] || this.accessKey;
	createTiddlyButton(place, label, prompt,
		function() { window.print(); },
		buttonClass, null, accessKey);
}
//}}}
<<LaunchApplicationButton "Putty prod" "Putty" "file:///C:/Program Files (x86)/PuTTY/putty.exe" -load "my_server">>
<<LaunchApplicationButton "WinSCP prod" "WinSCP" "file:///C:/Program Files (x86)/WinSCP/WinSCP.exe">>
разобраться с winscp
http://winscp.net/eng/docs/scripts

<<LaunchApplicationButton "Putty" "Putty" "file:///C:/Program Files (x86)/PuTTY/putty.exe">>
/***
|Name:|QuickOpenTagPlugin|
|Description:|Changes tag links to make it easier to open tags as tiddlers|
|Version:|3.0.1a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#QuickOpenTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
config.quickOpenTag = {

  dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE?

  createTagButton: function(place,tag,excludeTiddler) {
    // little hack so we can do this: <<tag PrettyTagName|RealTagName>>
    var splitTag = tag.split("|");
    var pretty = tag;
    if (splitTag.length == 2) {
      tag = splitTag[1];
      pretty = splitTag[0];
    }

    var sp = createTiddlyElement(place,"span",null,"quickopentag");
    createTiddlyText(createTiddlyLink(sp,tag,false),pretty);

    var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,
                        config.views.wikified.tag.tooltip.format([tag]),onClickTag);
    theTag.setAttribute("tag",tag);
    if (excludeTiddler)
      theTag.setAttribute("tiddler",excludeTiddler);
        return(theTag);
  },

  miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {
    var tagged = store.getTaggedTiddlers(tiddler.title);
    if (tagged.length > 0) {
      var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,
                          config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);
      theTag.setAttribute("tag",tiddler.title);
      theTag.className = "miniTag";
    }
  },

  allTagsHandler: function(place,macroName,params) {
    var tags = store.getTags(params[0]);
    var filter = params[1]; // new feature
    var ul = createTiddlyElement(place,"ul");
    if(tags.length == 0)
      createTiddlyElement(ul,"li",null,"listTitle",this.noTags);
    for(var t=0; t<tags.length; t++) {
      var title = tags[t][0];
      if (!filter || (title.match(new RegExp('^'+filter)))) {
        var info = getTiddlyLinkInfo(title);
        var theListItem =createTiddlyElement(ul,"li");
        var theLink = createTiddlyLink(theListItem,tags[t][0],true);
        var theCount = " (" + tags[t][1] + ")";
        theLink.appendChild(document.createTextNode(theCount));
        var theDropDownBtn = createTiddlyButton(theListItem," " +
          config.quickOpenTag.dropdownChar,this.tooltip.format([tags[t][0]]),onClickTag);
        theDropDownBtn.setAttribute("tag",tags[t][0]);
      }
    }
  },

  // todo fix these up a bit
  styles: [
"/*{{{*/",
"/* created by QuickOpenTagPlugin */",
".tagglyTagged .quickopentag, .tagged .quickopentag ",
" { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",
".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",
".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",
"/* extra specificity to make it work right */",
"#displayArea .viewer .quickopentag a.button, ",
"#displayArea .viewer .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink ",
" { border:0px solid black; }",
"#displayArea .viewer .quickopentag a.button, ",
"#mainMenu .quickopentag a.button ",
" { margin-left:0px; padding-left:2px; }",
"#displayArea .viewer .quickopentag a.tiddlyLink, ",
"#mainMenu .quickopentag a.tiddlyLink ",
" { margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",
"a.miniTag {font-size:150%;} ",
"#mainMenu .quickopentag a.button ",
" /* looks better in right justified main menus */",
" { margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }",
"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",
"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",
"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",
"/*}}}*/",
    ""].join("\n"),

  init: function() {
    // we fully replace these builtins. can't hijack them easily
    window.createTagButton = this.createTagButton;
    config.macros.allTags.handler = this.allTagsHandler;
    config.macros.miniTag = { handler: this.miniTagHandler };
    config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;
    store.addNotification("QuickOpenTagStyles",refreshStyles);
  }
}

config.quickOpenTag.init();

//}}}
http://www.bbc.co.uk/iplayer/console/bbc_radio_five_live
Click the button to get a random color palette defined in hex.
<<RandomColorPaletteButton>>

Don't like hex? Want rgb instead. Use the rgb parameter ({{{<<RandomColorPaletteButton rgb:yes>>}}})
<<RandomColorPaletteButton rgb:yes>>

Want to seed it with a certain hue (0-360 degrees)? Then use the hue parameter... {{{<<RandomColorPaletteButton hue:0>>}}} ... note hue=0 corresponds to red color schemes.
<<RandomColorPaletteButton hue:0>>

Want a bright scheme? Use the lightness parameter {{{<<RandomColorPaletteButton lightness:0.9>>}}}
<<RandomColorPaletteButton lightness:0.9>> Bit of a goth? Seed it low.. {{{<<RandomColorPaletteButton lightness:0.2>>}}} <<RandomColorPaletteButton lightness:0.2>>

Want a heavily saturated scheme? Use the saturation parameter. {{{<<RandomColorPaletteButton saturation:0.8>>}}}
<<RandomColorPaletteButton saturation:0.8>>

Jons favourite settings..
<<RandomColorPaletteButton saturation:0.6 darkest:0.1 lightness:0.9 huevariance:1>>
!The macros
{{{<<RandomColorPalette>>}}} is a run once macro which picks a random colour scheme for your TiddlyWiki, saving a new ColorPalette tiddler on completion.
This is useful if you want the color palette to change when a certain tiddler is opened. If your particular whacky you could make it change every time you display a new tiddler by adding the macro to the ViewTemplate.

{{{<<RandomColorPaletteButton>>}}} gives you a button that you can be used to pick a random colour scheme.
To change the color scheme within TiddlySpace

{{{
<<RandomColorPaletteButton>>
}}}

Displays as:

<<RandomColorPaletteButton>>
!Parameters
{{{
rgb: yes
}}}
By default the ColorPalette is defined in hexadecimal. You can output the colours as rgb by simply including this parameter.
{{{
hue:[0,360]
}}}
Seeds the randomiser with this hue.
{{{
saturation:[0,1]
}}}
Seeds the randomiser with a given saturation
{{{
pale:[0,1]
light:[0,1]
mid:[0,1]
dark:[0,1]
}}}
Seeds the randomiser with the required lightness values for calculating the different tones of the ColorPalette.
{{{
huevariance: [0,90]
}}}
Given a certain hue, specify the angle from the secondary colour to which the secondary and tertiary colours should be determined.

Note parameters can be discovered by viewing the ColorPaletteParameter slice within the generated ColorPalette.

{{{
<<RandomColorPaletteButton hue:200 saturation:0.7 huevariance:30 dark:0.3 mid:0.6 light:0.8 pale: 0.9>>
}}}
This example forces values so will create the same ColorPalette no matter what is clicked.
/***
|''Name''|RandomColorPalettePlugin|
|''Description''|Adds a random color palette to TiddlyWiki|
|''Author''|Jon Robson|
|''Version''|<1.1.0>|
|''Status''|stable|
|''Source''|http://svn.tiddlywiki.org/Trunk/contributors/JonRobson/plugins/RandomColorPalettePlugin/RandomColorPalettePlugin.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
!Usage
{{{
<<RandomColorPalette>>
Sets and saves a random color palette on execution

<<RandomColorPaletteButton>>
Creates a button, which when clicked will change the color palette
}}}
!Parameters
rgb: yes
By default the ColorPalette is defined in hex. You can output the colours as rgb by simply including this parameter.
hue:[0,360]
Seeds the randomiser with this hue.
saturation:[0,1]
Seeds the randomiser with a given saturation
lightness:[0,1]
Seeds the randomiser with a value for the lightest color tone (0 being darkest, 1 being lightest).

darkest:[0,1]
Seeds the randomiser with a value for the darkest color tone (0 being darkest, 1 being lightest).

huevariance: [0,90]
Given a certain hue, specify the angle from the secondary colour to which the secondary and tertiary colours should be determined.
!Code
***/
/*{{{*/
(function($){
	RGB.prototype.toRGBString = function() {
		return "rgb(%0,%1,%2)".format([parseInt(this.r * 255, 10), 
			parseInt(this.g * 255, 10), parseInt(this.b * 255, 10)])
	}
	function HSL_TO_RGB(h, s, l){ // h (hue) between 0 and 360, s (saturation) & l (lightness) between 0 and 1
		var c;
		if(l <= 0.5) {
			c = 2 * l * s;
		} else {
			c = ( 2 - (2 * l)) * s;
		}
		var h1 = h / 60;
		var x = c * (1 - Math.abs((h1 % 2) - 1)); 
		var r, g, b;
		if(typeof(h) == 'undefined') {
			r = 0;
			g = 0;
			b = 0;
		} else if(0 <= h1 && h1 < 1) {
			r = c;
			g = x;
			b = 0;
		} else if(1 <= h1 && h1 < 2) {
			r = x;
			g = c;
			b = 0;
		} else if(2 <= h1 && h1 < 3) {
			r = 0;
			g = c;
			b = x;
		}
		else if(3 <= h1 && h1 < 4) {
			r = 0;
			g = x;
			b = c;
		} else if(4 <= h1 && h1 < 5) {
			r = x;
			g = 0;
			b = c;
		} else if(5 <= h1 && h1 < 6) {
			r = c;
			g = 0;
			b = x;
		}
		m = l - (0.5 * c);
		r += m;
		g += m;
		b += m;
		return new RGB(r, g, b);
	}

	var macro = config.macros.RandomColorPalette = {
		messagesOn: false, 
		changedPaletteText: "We have assigned you a random theme by adjusting the [[ColorPalette]] tiddler.\nDon't like it? Click <<RandomColorPalette>> for another one.", 
		generate_palette: function(options) {
			var outputRGB = options.rgb && options.rgb[0];
			if(this.inprogress) { 
				return;
			}
			this.inprogress = true;
			var palette = {
				Background: "#fff",
				Foreground: "#000",
				PrimaryPale: "#8cf",
				PrimaryLight: "#FF7673",
				PrimaryMid: "#A60400",
				PrimaryDark: "#A60400",
				SecondaryPale: "#ffc",
				SecondaryLight: "#fe8",
				SecondaryMid: "#db4",
				SecondaryDark: "#841",
				TertiaryPale: "#eee",
				TertiaryLight: "#ccc",
				TertiaryMid: "#999",
				TertiaryDark: "#666"
			};
			var hue = options.hue ? parseInt(options.hue[0]) : Math.floor(Math.random() * 359);
			var saturation = options.saturation ? parseFloat(options.saturation[0]) : (Math.random() * 1);
			var pale = options.lightness ? parseFloat(options.lightness[0]) : (Math.random() * 1); 
			var dark = options.darkest ? parseFloat(options.darkest[0]) : 0;
			var lightness_values = {Dark:dark, Mid:pale - ( ( pale - dark ) / 2 ), Light:pale - ( ( pale - dark ) / 4 ), Pale:pale};

			var opposite_hue = (hue + 180) % 360;
			var seed = options.huevariance ? options.huevariance[0] : Math.floor((85 * Math.random()) + 5); // we want it to be at least 5 degrees
			var huetwo = (opposite_hue + seed) % 360;
			var huethree = (opposite_hue - seed) % 360;
			if(huetwo < 0) {
				huetwo = 360 + huetwo;
			}
			if(huethree < 0) {
				huethree = 360 + huethree;
			}
			for(var j in lightness_values) {
				if(true) {
					palette["Primary" + j] = HSL_TO_RGB(hue, saturation, lightness_values[j]);	
					palette["Secondary" + j] = HSL_TO_RGB(huetwo, saturation, lightness_values[j]);
					palette["Tertiary" + j] = HSL_TO_RGB(huethree, saturation, lightness_values[j]);
				}
			}
			palette.Background = HSL_TO_RGB(hue, saturation, 0.92);
			palette.Foreground = HSL_TO_RGB(hue, saturation, 0.08);
			
			// construct new ColorPalette
			var text = ["/*{{{*/\n"];
			var colorcode;
			for(var id in palette) {
				if(true) {
					var color = palette[id];
					if(outputRGB) {
						colorcode = color.toRGBString();
					} else {
						colorcode = color.toString();
					}	
					text.push("%0: %1\n".format([id, colorcode]));
				}
			}
			text.push("/*}}}*/");
			
			var tid = store.getTiddler('ColorPalette');
			if(!tid) {
				tid = new Tiddler('ColorPalette');
				tid.fields = merge({}, config.defaultCustomFields);
				tid.modifier ='RandomColorPalette Macro';
			}
			tid.text = text.join("");
			this.inprogress = false;
			return tid;
		},
		saveColorPalette: function(tid) {
			// save the color palette in tid
			store.saveTiddler(tid.title, tid.title, tid.text, tid.modifier, tid.modified, tid.tags, tid.fields, false, tid.created, '');
			// an interval is used to cope with users clicking on the palette button quickly.
			if(macro._nextSave) {
				window.clearTimeout(macro._nextSave);
			}
			macro._nextSave = window.setTimeout(function() {
					autoSaveChanges(null, [tid]);
				}, 2000);
			refreshAll();
			macro.reportChange();
		},
		reportChange: function() {
			var msgPlace = getMessageDiv();
			if(macro.messagesOn && !$(".changedPalette", msgPlace)[0]) { // only display message once..
				var tempPlace = document.createElement("div");
				wikify("{{changedPalette{" + macro.changedPaletteText + "}}}", tempPlace);
				msgPlace.appendChild(tempPlace);
			}
		},
		handler: function(place, macroName, params, wikifier, paramString, tiddler) {
			paramString = paramString || "";
			var options = paramString.parseParams("name", null, true, false, true)[0];
			var tiddler = macro.generate_palette(options);
			macro.saveColorPalette(tiddler);
		}
	};

	config.macros.RandomColorPaletteButton = {
			text: "New ColorPalette",
			tooltip: "Generate a random colour scheme for your TiddlyWiki",
			handler: function(place, macroName, params, wikifier, paramString, tiddler) {
				var btnHandler = function() {
					config.macros.RandomColorPalette.handler(place, macroName, params, wikifier, paramString, tiddler);
				};
				createTiddlyButton(place, this.text, this.tooltip, btnHandler);
			}
	};
})(jQuery);
/*}}}*/
/***
|''Name''|RandomSliceMacro|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#RandomSliceMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|Fetches a random slice from a given tiddler.|
!Usage
{{{
<<randomSlice [tiddler name] [show label] [separator string]>>
}}}
!!Examples
<<randomSlice [[ColorPalette]]>>
<<randomSlice [[ColorPalette]] true "::">>
!Revision History
!!v0.1 (2007-12-16)
* initial release
!To Do
* documentation
* custom label position (pre-/suffix)
!Code
***/
//{{{
config.macros.randomSlice = {};

config.macros.randomSlice.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var title = params[0] || tiddler.title;
	var showLabel = params[1] || false;
	var separator = params[2] || ": ";
	var slices = store.calcAllSlices(title);
	var labels = [];
	for(var name in slices) { // use Hash.keys() instead? cf. http://rick.measham.id.au/javascript/hash.htm
		labels.push(name);
	}
	if(labels.length > 0) {
		var r = Math.round((labels.length - 1) * Math.random());
		var value = slices[labels[r]];
		if(showLabel) {
			var output = labels[r] + separator + value;
		} else {
			var output = value;
		}
		wikify(output, place);
	}
};
//}}}
/***
|''Name''|RawTextAdaptor|
|''Description''|adaptor for importing plain-text files (e.g. from Subversion) as tiddlers|
|''Author''|FND|
|''Version''|0.2.3|
|''Status''|@@beta@@|
|''Source''|http://devpad.tiddlyspot.com/#RawTextAdaptor|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/association/adaptors/|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''CoreVersion''|2.5|
!Revision History
!!v0.1 (2008-10-28)
* initial release
!To Do
* properly normalize URIs (cf. {{{trimURI}}})
!Code
***/
//{{{
if(!version.extensions.RawTextAdaptor) { //# ensure that the plugin is only installed once
version.extensions.RawTextAdaptor = { installed: true };

config.adaptors.rawtext = function() {};

(function(adaptor) { //# set up alias

adaptor.prototype = new AdaptorBase();
adaptor.serverType = "rawtext";
adaptor.serverLabel = "Raw Text";
adaptor.defaultModifier = "..."; // XXX: use empty string?

adaptor.prototype.getWorkspaceList = function(context, userParams, callback) {
	context = this.setContext(context, userParams, callback);
	context.workspaces = [{ title: "N/A" }];
	if(context.callback) {
		context.status = true;
		window.setTimeout(function() { callback(context, context.userParams); }, 0);
	}
	return true;
};

adaptor.prototype.getTiddlerList = function(context, userParams, callback) {
	context = this.setContext(context, userParams, callback);
	if(context.callback) {
		context.status = true;
		var filename = adaptor.trimURI(context.host).split("/").pop();
		context.tiddlers = [adaptor.createTiddler(filename)];
		window.setTimeout(function() { callback(context, context.userParams); }, 0);
	}
	return true;
};

adaptor.prototype.getTiddler = function(title, context, userParams, callback) {
	context = this.setContext(context, userParams, callback);
	if(!context.tiddler) {
		context.tiddler = adaptor.createTiddler(title);
	}
	context.tiddler.fields["server.type"] = adaptor.serverType;
	context.tiddler.fields["server.host"] = AdaptorBase.minHostName(context.host);
	var req = httpReq("GET", context.host, adaptor.getTiddlerCallback, context);
	return typeof req == "string" ? req : true;
};

adaptor.getTiddlerCallback = function(status, context, responseText, uri, xhr) {
	context.status = status;
	context.statusText = xhr.statusText;
	context.httpStatus = xhr.status;
	if(status) {
		context.tiddler.text = responseText;
	}
	if(context.callback) {
		context.callback(context, context.userParams);
	}
};

// create tiddler from filename
adaptor.createTiddler = function(filename) {
	var tiddler = new Tiddler(filename);
	var pos = filename.lastIndexOf(".");
	if(pos != -1) { // strip file extension
		tiddler.title = filename.substr(0, pos); //# N.B.: altering title is acceptable since it's not used as URI component
		if(filename.substr(pos) == ".js") { // treat as plugin
			tiddler.tags = ["systemConfig"];
		}
	}
	tiddler.created = new Date();
	tiddler.modified = tiddler.created;
	tiddler.modifier = adaptor.defaultModifier;
	return tiddler;
};

// strip fragments and parameters from URI
adaptor.trimURI = function(uri) {
	return uri.split("#")[0].split("?")[0];
}

})(config.adaptors.rawtext); //# end of alias

} //# end of "install only once"
//}}}
{{annotation{(via [[MathCell TiddlyWiki|http://genisis329.googlepages.com/TWMath.html#%5B%5BRegexp%20Tester%5D%5D]])}}}
<html><form><table style="width: 80%; right: 0em;"><tbody><tr><td>REGEX</td><td><input type="text" name="regex" style="width: 100%;"></input></td></tr><tr><td>
FLAGS</td><td style="text-align: right;">Global<input type="checkbox" name="g"><br/>Multiline<input type="checkbox" name="m"><br/>Ignore Case<input type="checkbox" name="i"></td></tr><tr>
<td>STRING</td><td><textarea type="text" name="string" style="width: 100%; height: 5em;"></textarea></td></tr>
<tr><td></td><td style="text-align: right;"><input type="button" value="execute" onclick="
var flagging = []
if(this.form.g.checked)flagging.push('g');
if(this.form.i.checked)flagging.push('i');
if(this.form.m.checked)flagging.push('m');
var Reg = new RegExp(this.form.regex.value,flagging.join(''));
var result =this.form.string.value.match(Reg);
for(var i = 0; i < result.length;i++){alert(result[i].toSource())}
this.form.lastChild.innerHTML = result.join(&quot;&lt;hr/&gt;&quot;);
"></input></td></tr></tbody></table>
<br/>RESULT<hr/>
<pre name="results"></pre></form>
</html>
/***
|''Name''|RelativeLinkMacro|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#RelativeLinkMacro]]|
|''Version''|0.2|
|''Author''|FND|
|''License''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|creates PrettyLinks relative to the current tiddler|
!Usage Notes
{{{
<<relLink "sub-tiddler" ["link title"]>>
}}}
!!Examples
* {{{<<relLink "SubTiddler">>}}}: <<relLink "SubTiddler">>
* {{{<<relLink "SubTiddler" "custom link title">>}}}: <<relLink "SubTiddler" "custom link title">>
!Revision History
!!v0.1 (2007-08-10)
* initial proof-of-concept implementation
!!v0.2 (2007-08-10)
* added optional parameter for link title
!To Do
* rename plugin(?)
* adjust description
!Code
***/
//{{{
config.macros.relLink = {}
config.macros.relLink.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	if(!params[1])
		var link = "[[" + tiddler.title + params[0] + "]]";
	else
		var link = "[[" + params[1] + "|" + tiddler.title + params[0] + "]]";
	wikify(link, place);
}
//}}}
/***
RemoteBackgroundPlugin v1.0 (2007-02-19)
 by FND

Retrieves a random image from XKCD and uses it as background image.

''N.B.:'' Do not abuse this; retrieving the images from XKCD could be regarded as hotlinking!
!!Changelog
!!!v0.9 (2007-02-18)
* initial release
!!!v1.0 (2007-02-19)
* added ability to position background image
* minor code adjustments
!!ToDo
* wait until TiddlyWiki loaded has completed before loading remote data
* extensive bug-testing (esp. non-Mozilla browsers)
!!Code
***/
/*{{{*/
setBgImg();

// set background image
function setBgImg() {
	if (img() != null) {
		document.body.style.backgroundImage = "url(" + img()[0] + ")";
		document.body.style.backgroundRepeat = "no-repeat";
		document.body.style.backgroundPosition = "center";
		document.body.style.backgroundAttachment = "fixed";
		document.body.title = img()[1];
	} else {
		alert("error fetching remote image");
	}
}

// fetch image URL
function img() {
	// get remote location
	var maxCount = 225; // current amount of comcics - 2007-02-19
	var counter = Math.ceil(Math.random() * maxCount);
	var remoteSite = "http://xkcd.com/c" + counter + ".html";
	// fetch remote image
	var XmlHttp = true;
	var source = null;
	try { // query for permission to access remote file
		netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
	} catch (e) {
		XmlHttp = false;
	}
	// initiate XmlHttp
	if (typeof XMLHttpRequest != 'undefined') { // Mozilla, Opera, Safari and Internet Explorer 7
		XmlHttp = new XMLHttpRequest();
	}
	if (!XmlHttp) { // Internet Explorer 6 and older
		try {
			XmlHttp  = new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try {
				XmlHttp  = new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e) {
				XmlHttp  = null;
			}
		}
	}
	// get remote document
	if (XmlHttp != false) {
		XmlHttp = new XMLHttpRequest();
		if (XmlHttp) {
			// establish connection
			XmlHttp.open('GET', remoteSite, false);
			XmlHttp.send(null);
			// get image URL
			//source = XmlHttp.responseXML.getElementsByTagName('img')[1].src; // source data no valid XML => RexEx workaround
			var extract = XmlHttp.responseText.match(/<img src="(.+)" title="(.+)" alt/i);
			image = new Array(extract[1], extract[2]); // store URL and title value
		}
	}
	return image;
}
/*}}}*/
/***
|Name:|RenameTagsPlugin|
|Description:|Allows you to easily rename or delete tags across multiple tiddlers|
|Version:|3.0a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#RenameTagsPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
Rename a tag and you will be prompted to rename it in all its tagged tiddlers.
***/
//{{{
config.renameTags = {

  prompts: {
    rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",
    remove: "Remove the tag '%0' from %1 tidder%2?"
  },

  removeTag: function(tag,tiddlers) {
    store.suspendNotifications();
    for (var i=0;i<tiddlers.length;i++) {
      store.setTiddlerTag(tiddlers[i].title,false,tag);
    }
    store.resumeNotifications();
    store.notifyAll();
  },

  renameTag: function(oldTag,newTag,tiddlers) {
    store.suspendNotifications();
    for (var i=0;i<tiddlers.length;i++) {
      store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old
      store.setTiddlerTag(tiddlers[i].title,true,newTag);  // add new
    }
    store.resumeNotifications();
    store.notifyAll();
  },

  storeMethods: {

    saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,

    saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created,creator) {
      if (title != newTitle) {
        var tagged = this.getTaggedTiddlers(title);
        if (tagged.length > 0) {
          // then we are renaming a tag
          if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))
            config.renameTags.renameTag(title,newTitle,tagged);

          if (!this.tiddlerExists(title) && newBody == "")
            // dont create unwanted tiddler
            return null;
        }
      }
      return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created,creator);
    },

    removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,

    removeTiddler: function(title) {
      var tagged = this.getTaggedTiddlers(title);
      if (tagged.length > 0)
        if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))
          config.renameTags.removeTag(title,tagged);
      return this.removeTiddler_orig_renameTags(title);
    }

  },

  init: function() {
    merge(TiddlyWiki.prototype,this.storeMethods);
  }
}

config.renameTags.init();

//}}}
http://www.autohotkey.com/forum/topic52732.html
/***
|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:|SaveCloseTiddlerPlugin|
|Description:|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler|
|Version:|3.0a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#SaveCloseTiddlerPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
To use these add them to the commands in ToolbarCommands under EditToolbar,
or in the MptwTheme tiddler under EditTemplate.
***/
//{{{
merge(config.commands,{

  saveCloseTiddler: {
    text: 'done/close',
    tooltip: 'Save changes to this tiddler and close it',
    handler: function(ev,src,title) {
      var closeTitle = title;
      var newTitle = story.saveTiddler(title,ev.shiftKey);
      if (newTitle)
        closeTitle = newTitle;
      return config.commands.closeTiddler.handler(ev,src,closeTitle);
    }
  },

  cancelCloseTiddler: {
    text: 'cancel/close',
    tooltip: 'Undo changes to this tiddler and close it',
    handler: function(ev,src,title) {
      // the same as closeTiddler now actually
      return config.commands.closeTiddler.handler(ev,src,title);
    }
  }

});

//}}}
/***
|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
<<<
/***
|''Name''|SearchTagPlugin|
|''Description''|adds web-search links to internal wiki links|
|''Author''|FND|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Source''|http://devpad.tiddlyspot.com/#SearchTagPlugin|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
!Notes
Also see http://www.aboutus.org/TiddlyWikiGoogleTagCombinations.
!Revision History
!!v0.1 (2008-07-16)
* initial release
!Code
***/
//{{{
if(!version.extensions.SearchTagPlugin) {
version.extensions.SearchTagPlugin = {
	installed: true,
	URL: "http://google.com/search?q=",
	label: "[G]"
};
 
// hijack createTiddlyLink() to prepend search link
createTiddlyLink_SearchTag = window.createTiddlyLink;
window.createTiddlyLink = function(place, title, includeText, className, isStatic, linkedFromTiddler, noToggle) {
	var cfg = version.extensions.SearchTagPlugin;
	createTiddlyText(createExternalLink(place, cfg.URL + title), cfg.label);
	createTiddlyText(place, " ");
	return createTiddlyLink_SearchTag.apply(this, arguments);
};

} //# end of "install only once"
//}}}
/***
|''Name:''|SearchTextTweaks|
|''Description:''|adds descriptive text to the search box|
|''Author:''|Saq Imtiaz (lewcid@gmail.com)|
|''Contributor:''|FND|
|''Source:''|http://tw.lewcid.org/#SearchTextTweaks|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.0 beta|
|''Date:''|2007-09-09|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.1|
!Configuration
Using [[StyleSheet]], the {{{inactive}}} class can be used to change the search box's style (using CSS) when it is not active.
For example, the following code dims the text in the search box when it is not active:
{{{
.inactive { color: #aaa; }
}}}
***/
// /%
//!BEGIN-PLUGIN-CODE
//{{{
config.macros.search.defaultText = "Search";

config.macros.search.old_handler = config.macros.search.handler;
config.macros.search.handler = function(place,macroName,params) {
	this.old_handler.apply(this,arguments);
	var e = place.lastChild;
	e.setAttribute("defaultText",params[0]||this.defaultText);
	e.value = e.getAttribute("defaultText");
	e.onblur = function() {
		if(this.value == '' || !this.value)
			this.value = this.getAttribute("defaultText");
		addClass(this, "inactive");
	};
};

config.macros.search.onFocus = function(e) {
	if(this.value == this.getAttribute("defaultText"))
		this.value = '';
	removeClass(this, "inactive");
	this.select();
};
//}}}
//!END-PLUGIN-CODE
// %/
/***
|Name:|SelectThemePlugin|
|Description:|Lets you easily switch theme and palette|
|Version:|1.0.1a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#SelectThemePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
* Borrows largely from ThemeSwitcherPlugin by Martin Budden http://www.martinswiki.com/#ThemeSwitcherPlugin
* Theme is cookie based. But set a default by setting config.options.txtTheme in MptwConfigPlugin (for example)
* Palette is not cookie based. It actually overwrites your ColorPalette tiddler when you select a palette, so beware.
!Usage
* {{{<<selectTheme>>}}} makes a dropdown selector
* {{{<<selectPalette>>}}} makes a dropdown selector
* {{{<<applyTheme>>}}} applies the current tiddler as a theme
* {{{<<applyPalette>>}}} applies the current tiddler as a palette
* {{{<<applyTheme TiddlerName>>}}} applies TiddlerName as a theme
* {{{<<applyPalette TiddlerName>>}}} applies TiddlerName as a palette
***/
//{{{

config.macros.selectTheme = {
  label: {
    selectTheme:"select theme",
    selectPalette:"select palette"
  },
  prompt: {
    selectTheme:"Select the current theme",
    selectPalette:"Select the current palette"
  },
  tags: {
    selectTheme:'systemTheme',
    selectPalette:'systemPalette'
  }
};

config.macros.selectTheme.handler = function(place,macroName)
{
  var btn = createTiddlyButton(place,this.label[macroName],this.prompt[macroName],this.onClick);
  // want to handle palettes and themes with same code. use mode attribute to distinguish
  btn.setAttribute('mode',macroName);
};

config.macros.selectTheme.onClick = function(ev)
{
  var e = ev ? ev : window.event;
  var popup = Popup.create(this);
  var mode = this.getAttribute('mode');
  var tiddlers = store.getTaggedTiddlers(config.macros.selectTheme.tags[mode]);
  // for default
  if (mode == "selectPalette") {
    var btn = createTiddlyButton(createTiddlyElement(popup,'li'),"(default)","default color palette",config.macros.selectTheme.onClickTheme);
    btn.setAttribute('theme',"(default)");
    btn.setAttribute('mode',mode);
  }
  for(var i=0; i<tiddlers.length; i++) {
    var t = tiddlers[i].title;
    var name = store.getTiddlerSlice(t,'Name');
    var desc = store.getTiddlerSlice(t,'Description');
    var btn = createTiddlyButton(createTiddlyElement(popup,'li'), name?name:t, desc?desc:config.macros.selectTheme.label['mode'], config.macros.selectTheme.onClickTheme);
    btn.setAttribute('theme',t);
    btn.setAttribute('mode',mode);
  }
  Popup.show();
  return stopEvent(e);
};

config.macros.selectTheme.onClickTheme = function(ev)
{
  var mode = this.getAttribute('mode');
  var theme = this.getAttribute('theme');
  if (mode == 'selectTheme')
    story.switchTheme(theme);
  else // selectPalette
    config.macros.selectTheme.updatePalette(theme);
  return false;
};

config.macros.selectTheme.updatePalette = function(title)
{
  if (title != "") {
    store.deleteTiddler("ColorPalette");
    if (title != "(default)")
      store.saveTiddler("ColorPalette","ColorPalette",store.getTiddlerText(title),
          config.options.txtUserName,undefined,"");
    refreshAll();
    if(config.options.chkAutoSave)
      saveChanges(true);
  }
};

config.macros.applyTheme = {
  label: "apply",
  prompt: "apply this theme or palette" // i'm lazy
};

config.macros.applyTheme.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
  var useTiddler = params[0] ? params[0] : tiddler.title;
  var btn = createTiddlyButton(place,this.label,this.prompt,config.macros.selectTheme.onClickTheme);
  btn.setAttribute('theme',useTiddler);
  btn.setAttribute('mode',macroName=="applyTheme"?"selectTheme":"selectPalette"); // a bit untidy here
}

config.macros.selectPalette = config.macros.selectTheme;
config.macros.applyPalette = config.macros.applyTheme;

config.macros.refreshAll = { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
  createTiddlyButton(place,"refresh","refresh layout and styles",function() { refreshAll(); });
}};

//}}}
https://servicedesk.luxoft.com/browse/SD-89154
<<closeAll>><<permaview>><<newTiddler>>{{separator{ }}}<<saveChanges>><<doBackup>><<tiddler TspotSidebar>>{{separator{ }}}<<slider chkSliderOptionsPanel OptionsPanel 'options ۧ 'Change TiddlyWiki advanced options'>>
/***
|Name|SimpleCommentsPlugin|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#SimpleCommentsPlugin]]|
|Version|0.7|
|Author|FND|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|add comments to a tiddler|
!Usage
Add {{{<<addComment>>}}} to the desired tiddler(s).
Alternatively, add the following to the tiddler toolbar (usually in ViewTemplate, {{{<div class='toolbar' macro='...'>}}}): {{{addComment}}} (currently untested)

''N.B.:'' For now, TiddlyWiki needs to be saved manually after adding a comment, thus making this plugin rather unsuitable for read-only TiddlyWikis.
!Changelog
!!v0.5 (2007-05-08)
* initial release
!!v0.6 (2007-05-10)
* moved required styles into a shadow tiddler
!!v0.7 (2007-05-14)
* complete rewrite from DOM-based to string-based processing
!Issues / To Do
* proper creation of command buttons
* global option and/or macro parameter for reverseOrder
* revise CSS properties
* review code (esp. section marked with DEBUG)
* some functions/routines might be redundant (i.e. already present in the TiddlyWiki core, e.g. {{{trim()}}}, {{{IsoTimestamp()}}} & {{{zeroPad()}}}?)
!Code
***/
//{{{
/*
** Styles (can be customized in the StyleSheetSimpleComments shadow tiddler)
*/

config.shadowTiddlers.StyleSheetSimpleComments = "/*{{{*/\n"
	+ ".comments {\n\tmargin-top: 2em;\n\tpadding: 1em 4px 4px;\n\tborder-top: 2px ridge #AAA;\n\tbackground-color: #F8F8F8;\n}\n\n"
	+ ".comments .comment {\n\tmargin: 0.5em 1em;\n\tpadding: 4px;\n\tborder: 1px solid #AAA;\n\tbackground-color: #FFF;\n}\n\n"
	+ ".comments .comment h1,\n.comments .comment h2 {\n\tmargin: 0 0 0.2em;\n\tpadding: 0;\n\tborder-bottom: 1px solid #AAA;\n\tbackground-color: transparent;\n}\n\n"
	+ ".comments .comment h1 {\n\tfloat: right;\n}\n\n"
	+ ".comments .comment p {\n\tmargin: 0 0 0.2em;\n}\n"
	+ "/*}}}*/";
store.addNotification("StyleSheetSimpleComments", refreshStyles);

/*
** Command Buttons
*/

/* Macro Button */
// adapted from Jack's DoBackupMacro (http://groups.google.com/group/TiddlyWiki/browse_thread/thread/5f1123d08bdadeac/86245d5e4bbe846c)
config.macros.addComment = { label: "Add comment", prompt: "Add a new comment" }; // DEBUG: prompt not needed!?
config.macros.addComment.handler = function(place) {
	if(!readOnly) {
		createTiddlyButton(place, this.label, this.prompt, function() {
				addTiddlerComment(this);
				return false; // DEBUG: ?
			}, null, null, this.accessKey
		); // DEBUG - to do: look up createTiddlyButton()'s parameters
	}
}

/* Toolbar Button */
config.commands.addComment = { text: "Add comment", tooltip: "Add a comment" }
config.commands.addComment.handler = function() {
	addTiddlerComment(this); // DEBUG: does that work?
}

/*
** Script
*/

// adapted from Eric Shulman's CommentScript (http://www.tiddlytools.com/#CommentScript)
addTiddlerComment = function(place) {
	// select current tiddler
	var here = story.findContainingTiddler(place);
	if (!here) {
		alert("error: no tiddler specified");
		return;
	}
	var title = here.getAttribute("tiddler");
	var tiddler = store.getTiddler(title);
	// retrieve tiddler sections
	var tiddlerContentsPre = tiddler.text + "\n";
	var tiddlerComments = "";
	var tiddlerContentsPost = "";
	var RegEx = /^([\S\s]*)\{\{comments\{((?:\{\{comment\{[^}]*\}\}\}|\s+)*)\}\}\}([\S\s]*)$/i; // RegEx provided by Andreas "Qtax" Zetterlund (www.qtax.se)
	var tiddlerContents = RegEx.exec(tiddler.text);
	if (tiddlerContents != null) {
		tiddlerContentsPre = tiddlerContents[1];
		tiddlerComments += lTrim(tiddlerContents[2]); // assuming there is only a single comments section per tiddler
		tiddlerContentsPost = tiddlerContents[3];
	}
	// append comment
	var reverseOrder = false; // DEBUG: global option!?
	if (reverseOrder) {
		tiddlerComments = newComment() + "\n" + tiddlerComments;
	} else {
		tiddlerComments += newComment() + "\n";
	}
	tiddlerComments = "{{comments{\n" + tiddlerComments + "}}}";
	// re-create tiddler contents
	tiddlerContents = tiddlerContentsPre + tiddlerComments + tiddlerContentsPost;
	// store new tiddler contents
	store.saveTiddler(tiddler.title, tiddler.title, tiddlerContents, tiddler.modifier, tiddler.modified, tiddler.tags); // DEBUG: look up saveTiddler()'s parameters
	story.refreshTiddler(title, 1, true); // DEBUG: look up refreshTiddler()'s parameters
	// DEBUG: save file automatically? (could also be uploaded if the respective plugin is installed)
}

function newComment() {
	// get comment
	var comment = getComment();
	// create comment
	if (comment != null) {
		// get username
		getUserName();
		// get timestamp
		var now = new Date();
		var timestamp = IsoTimestamp(now, true); // use UTC -- DEBUG: use toLocaleString()?; make UTC a macro parameter
		// add timestamp and username
		comment = "{{comment{\n"
			+ "!" + timestamp + "\n"
			+ "!!" + config.options.txtUserName + "\n"
			+ comment + "\n"
			+ "}}}";
	}
	return comment;
}

function getComment() { // DEBUG: use temporary textarea instead of dialog box?
	var comment = prompt("Please enter your comment (wiki markup is allowed).", "");
	comment = trim(comment);
	if (comment == "") { // disallow empty comments
		getComment();
	}
	return comment;
}

function getUserName() {
	if (config.options.txtUserName == "" || config.options.txtUserName == null) { // does not accept "Cancel"!
		config.options.txtUserName = prompt("Please enter your username.", config.options.txtUserName);
		config.options.txtUserName = trim(config.options.txtUserName);
		getUserName(); // check for empty username
	}
}

function IsoTimestamp(date, UTC) {
	var date = new Date(date)
	if (UTC == true) {
		date = date.getUTCFullYear() + "-"
			+ zeroPad(date.getUTCMonth() + 1, 2) + "-"
			+ zeroPad(date.getUTCDate(), 2) + " "
			+ zeroPad(date.getUTCHours(), 2) + ":"
			+ zeroPad(date.getUTCMinutes(), 2)
			+ " UTC";
	} else {				
		date = date.getFullYear() + "-"
			+ zeroPad(date.getMonth() + 1, 2) + "-"
			+ zeroPad(date.getDate(), 2) + " "
			+ zeroPad(date.getHours(), 2) + ":"
			+ zeroPad(date.getMinutes(), 2);
	}
	return date;
}

function zeroPad(number, digits) {
	var s = String(number);
	while (s.length < digits)
		s = '0' + s;
	return s;
}

// remove leading whitespaces
function lTrim(str) {
	var RE = /^\s*((\S+\s*)*)$/;
	return str.replace(RE, "$1");
}

// remove trailing whitespaces
function rTrim(str) {
	var RE = /^((\s*\S+)*)\s*$/;
	return str.replace(RE, "$1");
}

// remove leading and trailing whitespaces
function trim(str) {
	return lTrim(rTrim(str));
}
//}}}
/***
|''Name''|SimpleSearchPlugin|
|''Description''|displays search results as a simple list of matching tiddlers|
|''Authors''|FND|
|''Version''|0.4.1|
|''Status''|stable|
|''Source''|http://devpad.tiddlyspot.com/#SimpleSearchPlugin|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/plugins/SimpleSearchPlugin.js|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Keywords''|search|
!Revision History
!!v0.2.0 (2008-08-18)
* initial release
!!v0.3.0 (2008-08-19)
* added Open All button (renders Classic Search option obsolete)
* sorting by relevance (title matches before content matches)
!!v0.4.0 (2008-08-26)
* added tag matching
!To Do
* tag matching optional
* animations for container creation and removal
* when clicking on search results, do not scroll to the respective tiddler (optional)
* use template for search results
!Code
***/
//{{{
if(!version.extensions.SimpleSearchPlugin) { //# ensure that the plugin is only installed once
version.extensions.SimpleSearchPlugin = { installed: true };

if(!config.extensions) { config.extensions = {}; }

config.extensions.SimpleSearchPlugin = {
	heading: "Search Results",
	containerId: "searchResults",
	btnCloseLabel: "close",
	btnCloseTooltip: "dismiss search results",
	btnCloseId: "search_close",
	btnOpenLabel: "Open all",
	btnOpenTooltip: "open all search results",
	btnOpenId: "search_open",

	displayResults: function(matches, query) {
		story.refreshAllTiddlers(true); // update highlighting within story tiddlers
		var el = document.getElementById(this.containerId);
		query = '"""' + query + '"""'; // prevent WikiLinks
		if(el) {
			removeChildren(el);
		} else { //# fallback: use displayArea as parent
			var container = document.getElementById("displayArea");
			el = document.createElement("div");
			el.id = this.containerId;
			el = container.insertBefore(el, container.firstChild);
		}
		var msg = "!" + this.heading + "\n";
		if(matches.length > 0) {
			msg += "''" + config.macros.search.successMsg.format([matches.length.toString(), query]) + ":''\n";
			this.results = [];
			for(var i = 0 ; i < matches.length; i++) {
				this.results.push(matches[i].title);
				msg += "* [[" + matches[i].title + "]]\n";
			}
		} else {
			msg += "''" + config.macros.search.failureMsg.format([query]) + "''"; // XXX: do not use bold here!?
		}
		createTiddlyButton(el, this.btnCloseLabel, this.btnCloseTooltip, config.extensions.SimpleSearchPlugin.closeResults, "button", this.btnCloseId);
		wikify(msg, el);
		if(matches.length > 0) { // XXX: redundant!?
			createTiddlyButton(el, this.btnOpenLabel, this.btnOpenTooltip, config.extensions.SimpleSearchPlugin.openAll, "button", this.btnOpenId);
		}
	},

	closeResults: function() {
		var el = document.getElementById(config.extensions.SimpleSearchPlugin.containerId);
		removeNode(el);
		config.extensions.SimpleSearchPlugin.results = null;
		highlightHack = null;
	},

	openAll: function(ev) {
		story.displayTiddlers(null, config.extensions.SimpleSearchPlugin.results);
		return false;
	}
};

config.shadowTiddlers.StyleSheetSimpleSearch = "/*{{{*/\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " {\n" +
	"\toverflow: auto;\n" +
	"\tpadding: 5px 1em 10px;\n" +
	"\tbackground-color: [[ColorPalette::TertiaryPale]];\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " h1 {\n" +
	"\tmargin-top: 0;\n" +
	"\tborder: none;\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " ul {\n" +
	"\tmargin: 0.5em;\n" +
	"\tpadding-left: 1.5em;\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " .button {\n" +
	"\tdisplay: block;\n" +
	"\tborder-color: [[ColorPalette::TertiaryDark]];\n" +
	"\tpadding: 5px;\n" +
	"\tbackground-color: [[ColorPalette::TertiaryLight]];\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.containerId + " .button:hover {\n" +
	"\tborder-color: [[ColorPalette::SecondaryMid]];\n" +
	"\tbackground-color: [[ColorPalette::SecondaryLight]];\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.btnCloseId + " {\n" +
	"\tfloat: right;\n" +
	"\tmargin: -5px -1em 5px 5px;\n" +
	"}\n\n" +
	"#" + config.extensions.SimpleSearchPlugin.btnOpenId + " {\n" +
	"\tfloat: left;\n" +
	"\tmargin-top: 5px;\n" +
	"}\n" +
	"/*}}}*/";
store.addNotification("StyleSheetSimpleSearch", refreshStyles);

// override Story.search()
Story.prototype.search = function(text, useCaseSensitive, useRegExp) {
	highlightHack = new RegExp(useRegExp ? text : text.escapeRegExp(), useCaseSensitive ? "mg" : "img");
	var matches = store.search(highlightHack, null, "excludeSearch");
	var q = useRegExp ? "/" : "'";
	config.extensions.SimpleSearchPlugin.displayResults(matches, q + text + q);
};

// override TiddlyWiki.search() to sort by relevance
TiddlyWiki.prototype.search = function(searchRegExp, sortField, excludeTag, match) {
	var candidates = this.reverseLookup("tags", excludeTag, !!match);
	var primary = [];
	var secondary = [];
	var tertiary = [];
	for(var t = 0; t < candidates.length; t++) {
		if(candidates[t].title.search(searchRegExp) != -1) {
			primary.push(candidates[t]);
		} else if(candidates[t].tags.join(" ").search(searchRegExp) != -1) {
			secondary.push(candidates[t]);
		} else if(candidates[t].text.search(searchRegExp) != -1) {
			tertiary.push(candidates[t]);
		}
	}
	var results = primary.concat(secondary).concat(tertiary);
	if(sortField) {
		results.sort(function(a, b) {
			return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);
		});
	}
	return results;
};

} //# end of "install only once"
//}}}

<<tag "peoples">> <<tag "projects">>  <<tag meta>> Work pad

/***
!Page Layout
!!General
***/
/*{{{*/
body {
	background-color: [[ColorPalette::Background]];
}
/*}}}*/
/***
!!Header
***/
/*{{{*/
.headerForeground,
.headerShadow {
	padding: 1em 1em 1em 2em;
}

.siteTitle {
	font-size: 2.5em;
}

.siteSubtitle {
	margin-left: 1em;
	font-size: 1em;
}
/*}}}*/
/***
!!Main Menu
***/
/*{{{*/
#mainMenu {
	white-space: nowrap;
	text-align: left;
}

#mainMenu ul {
	margin: 0.2em 0 0;
	padding: 0 0 0 1em;
}
/*}}}*/
/***
!!Sidebar
***/
/*{{{*/
#sidebar {
	right: 0px;
}

#sidebarOptions .button {
	border-color: [[ColorPalette::Background]];
}

#sidebarOptions .button:hover {
	border-color: [[ColorPalette::SecondaryMid]];
}

#sidebarTabs .tabContents {
	max-height: 35em; /* not IE6-compatible */
	overflow: auto;
	width: 92.5%;
}

#sidebarTabs .tabContents .tabContents {
	max-height: 30em !important; /* not IE6-compatible */
}
/*}}}*/
/***
!!Search Bar
***/
/*{{{*/
#searchBar {
	float: right;
	font-size: 0.9em;
}

#searchBar .button {
	margin-right: 0.5em;
	border: none;
}
/*}}}*/
/***
!!Message Area {{annotation{(notification box)}}}
***/
/*{{{*/
#messageArea {
	top: auto;
	bottom: 0;
}
/*}}}*/
/***
!Tiddlers
!!Layout
***/
/*{{{*/
.tiddler {
	position: relative; /* fix disappearing borders issue */
	max-height: 60em; /* not IE6-compatible */
	overflow: auto;
	margin-bottom: 1em;
	border-top: 1px solid [[ColorPalette::TertiaryPale]];
	border-right: 1px solid [[ColorPalette::TertiaryDark]];
	border-bottom: 1px solid [[ColorPalette::TertiaryDark]];
	border-left: 1px solid [[ColorPalette::TertiaryPale]];
	padding-bottom: 1em;
}

.tiddler.selected {
	border-color: [[ColorPalette::TertiaryMid]];
}

.subtitle {
	margin-top: -1.5em;
	margin-bottom: 0.5em;
	padding-bottom: 0.5em;
	border-bottom: 1px solid [[ColorPalette::TertiaryMid]];
	font-size: x-small;
	text-align: right;
}

.editor {
	margin-top: 0.5em;
}
/*}}}*/
/***
!!Contents
***/
/*{{{*/
.viewer {
	font-size: 1.1em;
}

.viewer li {
	margin-bottom: 0.2em;
}

.viewer pre {
	max-height: 50em; /* not IE6-compatible */
	overflow: auto;
}

.viewer table caption {
	padding-top: 0;
	font-style: italic;
}

/* Headings */

h1 {
	padding: 0.1em 0.1em 0.1em 0.4em;
	color: [[ColorPalette::TertiaryMid]];
	background-color: [[ColorPalette::TertiaryPale]];
}

h2, h3, h4, h5 {
	padding: 0 0.2em;
	color: [[ColorPalette::Foreground]];
	background-color: transparent;
}

h2 {
	border-bottom: 1px solid [[ColorPalette::TertiaryMid]];
}

h3 {
	border-bottom: 1px dashed [[ColorPalette::TertiaryMid]];
}
/*}}}*/
/***
!Custom Classes
***/
/*{{{*/
/* horizontal separator */

.separator {
	display: block;
	margin: 0.2em 2em 0.2em 0;
	border-top: 1px solid [[ColorPalette::TertiaryMid]];
}

#sidebarOptions .separator {
	margin-left: 0.5em;
}

/* popup styles (cf. [[templatePopup]]) */

.dropdownPopup {
	color: [[ColorPalette::Background]];
}

.infoPopup {
	border: 1px solid [[ColorPalette::Foreground]];
	color: [[ColorPalette::Foreground]];
	background-color: #FFFFE1;
}

.dropdownPopup ol,
.infoPopup ol {
	padding-left: 2em;
	list-style-type: decimal;
}

.dropdownPopup ul,
.infoPopup ul {
	padding-left: 1.2em;
	list-style-type: disc;
}

.infoPopup ol,
.infoPopup ul {
	margin: 1em 0;
}

.dropdownPopup ul ul,
.infoPopup ul ul {
	list-style-type: circle;
}

.dropdownPopup ul ul ul,
.infoPopup ul ul ul {
	list-style-type: square;
}

.dropdownPopup a,
.infoPopup a {
	display: inline !important;
}

/* annotation */

.annotation {
	font-size: 0.9em;
	color: gray;
}

div.annotation {
	margin-left: 2em;
}

/* borderless table */

.viewer .borderlessTable,
.viewer .borderlessTable * {
	border: 0;
}

.viewer .borderlessTable th {
	border: 1px solid #000;
	font-weight: normal;
	text-align: left;
	color: [[ColorPalette::Foreground]];
	background-color: transparent;
}
/*}}}*/
/***
!Print Layout
***/
/*{{{*/
@media print {
	#searchBar {
		display: none;
	}

	.tiddler,
	.viewer pre {
		max-height: none; /* not IE6-compatible */
		overflow: visible;
	}
}
/*}}}*/
@media print {
#mainMenu, #sidebar, #messageArea, #breadCrumbs, #topMenu, .siteTitle, .siteSubtitle  {display: none ! important;}
#displayArea {margin: 0.5em 0.5em 0em 0.5em;}
}
These Styles represent all of the CSS Style data that control the look and feel of this site.

Note that I recently "modularized" the StyleSheet Tiddler so that "Styles xxxx" Tiddlers are "called" by StyleSheet. This makes for better troubleshooting.

If you wish to use these Styles, please be sure to copy them all, because they are all called from within StyleSheet.
/***
Calendar
***/
/*{{{*/
.calendar a { margin:0px !important; padding:0px !important; } 
/*}}}*/
/***
Styles Editor
***/
/*{{{*/
.editor textarea {height:200px;background-color:#F2F2F2;}

.editorFooter .button { 
  padding-top: 0px; 
  padding-bottom:0px; 
  background: #fff;
  color: #000; 
  border-top:    1px solid #ccc; 
  border-left:   1px solid #ccc; 
  border-bottom: 2px solid #ccc; 
  border-right:  2px solid #ccc; 
  margin-left: 3px;
  padding-top: 1px;
  padding-bottom: 1px;
  padding-left: 5px;
  padding-right: 5px; }
  
.editorFooter .button:hover { 
  border-top:    2px solid #ccc; 
  border-left:   2px solid #ccc; 
  border-bottom: 1px solid #ccc; 
  border-right:  1px solid #ccc; 
  margin-left: 3px;
  padding-top: 1px;
  padding-bottom: 1px;
  padding-left: 5px;
  padding-right: 5px; }
/*}}}*/
/***
To use, add {{{[[Styles HorizontalMainMenu]]}}} to your StyleSheet tiddler, or you can just paste the CSS in directly. See also HorizontalMainMenu and PageTemplate.
***/
/*{{{*/

#topMenu br {display:none; }
#topMenu { background: #39a; }
#topMenu { padding:2px; }
#topMenu .button,  #topMenu .tiddlyLink { padding-left:1em; padding-right:1em; color:white; font-size:115%;}
#displayArea { margin: 1em 15.7em 0em 1em; }

/* just in case want some QuickOpenTags in your topMenu */
#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }
#topMenu .quickopentag .tiddlyLink { padding-right:1px; }
#topMenu .quickopentag .button { padding-left:1px; border:0px; }


/*}}}*/
/***
Style Message Area
***/
/*{{{*/
#messageArea { 
  background-color: #eee; 
  border-color: #8ab; 
  border-width: 4px; 
  border-style: dotted; 
  font-size: 90%; 
  padding: 0.5em; 
  -moz-border-radius: 1em; }
#messageArea .button { text-decoration:none; font-weight:bold; background:transparent; border:0px; }
#messageArea .button:hover {background: #acd; }
/*}}}*/
/***
Styles SideBarOptions
***/
/*{{{*/
#sidebarOptions .sliderPanel {
  border: 0px solid #ccc; 
  background-color: #eee;
  margin: 0px;
  margin-left: 0.5em;
  padding: 0px;
  -moz-border-radius: 1em; }

#sidebarOptions .sliderPanel .tabSelected{
  border: 1px solid #ccc; 
  background-color: #fff;
  margin: 0px;
  padding-top: 5px;
  padding-bottom: 0px;
  padding-left: 2px;
  padding-right: 2px;
  -moz-border-radius-topleft: 1em; 
  -moz-border-radius-topright: 1em;}

#sidebarOptions .sliderPanel .tabUnselected{
  border:    1px solid #ccc; 
  background-color: #eee;
  margin: 0px;
  padding-top: 5px;
  padding-bottom: 0px;
  padding-left: 2px;
  padding-right: 2px;
  -moz-border-radius-topleft: 1em; 
  -moz-border-radius-topright: 1em;}

#sidebarOptions { 
  border-top:    1px solid #ccc; 
  border-left:   1px solid #ccc; 
  border-bottom: 3px solid #ccc; 
  border-right:  3px solid #ccc; 
  padding: 0.5em; 
  margin: 0.5em; 
  -moz-border-radius: 1em; }

#sidebarOptions .button {
  margin: 1px;
  border-color:white;
  border-top:    1px solid #ccc; 
  border-left:   1px solid #ccc; 
  border-bottom: 2px solid #ccc; 
  border-right:  2px solid #ccc; 
}

#sidebarOptions .button:hover {
  color: #000;
  background: #fff;
  border-top:    2px solid #ccc; 
  border-left:   2px solid #ccc; 
  border-bottom: 1px solid #ccc; 
  border-right:  1px solid #ccc; 
}

#sidebarOptions .button:active {
  color: #000;
  background: #fff;
}
/*}}}*/
/***
To use, add {{{[[Styles TagglyTagging]]}}} to your StyleSheet tiddler, or you can just paste the CSS in directly. See also ViewTemplate, EditTemplate and TagglyTagging.
***/
/*{{{*/
.tagglyTagged li.listTitle { display:none;}
.tagglyTagged li { display: inline; font-size:90%; }
.tagglyTagged ul  { margin:0px; padding:0px; }
.tagglyTagging { padding-top:0.5em; }
.tagglyTagging li.listTitle { display:none;}
.tagglyTagging ul  { margin-top:0px; padding-top:0.5em; padding-left:2em; margin-bottom:0px; padding-bottom:0px; }

/* .tagglyTagging .tghide { display:inline; } */

.tagglyTagging .button { display:none;  margin-left:3px; margin-right:3px; }
.tagglyTagging .button, .hidebutton  { color:#aaa; font-size:90%; border:0px; padding-left:0.3em;padding-right:0.3em;}
.tagglyTagging .button:hover, .hidebutton:hover { background:#eee; color:#888; }
.selected .tagglyTagging .button { display:inline; }

.tagglyLabel { color:#aaa; font-size:90%; }


.editLabel { font-size:90%; padding-top:0.5em; }
/*}}}*/
* TiddlyWiki equivalent of MediaWiki's subpages
* sub-tiddlers' names are preceded by the parent tiddler's name and a separator (e.g. "parent/sub")
* the parent tiddler contains an automatically-created index of all sub-tiddlers (like a table of contents, or like a horizontal menu bar)
* sub-tiddlers contain a "breadcrumb" link back to the parent tiddler(s)
* multiple sub-levels?
* all tiddlers optionally contain a button to create a sub-tiddler
----
related examples / alternatives:
* [[PartTiddlerPlugin|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin]]
* tiddler fields: [[ListboxPlugin|http://www.tiddlytools.com/#ListboxPlugin]], [[TaskViewTemplate|http://www.tiddlytools.com/#TaskViewTemplate]] / [[TaskTemplateTweak|http://www.tiddlytools.com/#TaskTemplateTweak]]
* [[easySlicer|http://yann.perrin.googlepages.com/twkd.html#easySlicer]] (might even render this project obsolete)
/***
|Name|SuppressEmptyTagsPlugin|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#SuppressEmptyTagsPlugin]]|
|Version|1.1|
|Author|FND|
|Contributors|[[Saq Imtiaz|http://tw.lewcid.org]], [[Eric Shulman|http://www.tiddlytools.com]]|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|config.macros.tags.handler|
|Description|suppress tagged box when tiddler is untagged|
!Changelog
!!v0.5 (2007-06-11)
* initial release
!!v1.0 (2007-06-11)
* proper overriding of core function (thanks Saq)
* changed ~CoreVersion to 2.1 (from 2.2)
!!v1.1 (2007-06-11)
* further improved hijacking method (thanks Eric)
!Code
***/
//{{{
config.macros.tags.oldHandler = config.macros.tags.handler;
config.macros.tags.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	if(tiddler.tags && tiddler.tags.length > 0)
		this.oldHandler.apply(this, arguments);
	else
		place.style.display = 'none';
};
//}}}
1. Разобраться как в padre подключить SVN
http://forum.vingrad.ru/forum/act-ST/f-5/t-328250/unread-1.html
2. Приделать сравнение файлов к padre
<<tabs txtMainTab Timeline Timeline TabTimeline All 'All tiddlers' TabAll Tags 'All tags' TabTags More 'More lists' TabMore>>
<<tCalendar lastModified>>
/***
|''Name''|TableHighlightMacro|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#TableHighlightMacro]]|
|''Version''|0.3|
|''Author''|FND|
|''License''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|macro for highlighting elements on mouse-over (hover)|
!Usage Notes
* two options:
** add {{{<<tableHighlight [class tag]>>}}} to the desired tiddler(s)
** add as a macro to ViewTemplate: {{{<span macro='tableHighlight [class tag]'></span>}}}
!!Example
highlight table rows (using footer class for compatibility reasons): {{{<<tableHighlight "footer" "tr">>}}} <<tableHighlight "footer" "tr">>
!Revision History
!!v0.1 (2007-08-16)
* initial proof-of-concept implementation
!!v0.2 (2007-08-16)
* added shadow tiddler for styles
!!v0.3 (2007-08-16)
* added optional parameters for class name and target element
* replaced minimal shadow tiddler with {{{setStylesheet()}}} call
* greatly improved code efficiency (thanks Lewcid)
!To Do
* rename plugin (e.g. ElementHoverHighlightMacro?) => also rename dependencies (macro name, default class and style sheet)
* adjust Description and Usage Notes
!Code
***/
//{{{
config.macros.tableHighlight = {}
config.macros.tableHighlight.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	// process parameters
	var highlightClass = (params[0] && params[0] != "") ? params[0] : "tableHighlightActive";
	var targetElement = (params[1] && params[1] != "") ? params[1] : "td";
	// highlight elements
	var cells = story.findContainingTiddler(place).getElementsByTagName(targetElement);
	for(var i = 0; i < cells.length; i++) {
		cells[i].onmouseover = function() { addClass(this, highlightClass); };
		cells[i].onmouseout = function() { removeClass(this, highlightClass); };
	}
}

// set default styles
setStylesheet(".tableHighlightActive { "
	+ "background-color: " + store.getTiddlerSlice("ColorPalette", "SecondaryPale") + ";"
	+ " }",
	+ "StyleSheetTableHighlight");
//}}}
easy interface for records on DataVault

cf. [[SliceGridPlugin|http://www.tiddlytools.com/#SliceGridPlugin]]
/***
|''Name''|TableToTiddlersMacro|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#TableToTiddlersMacro]]|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Author''|FND|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|generates individual tiddlers from a table|
!Notes
* one tiddler per row (tiddler name is value of first column)
* transposing; one row in each tiddler per column (excluding first column) in the source data
!Usage
{{{
<<table2tiddlers [tiddler] [tags] [header] [footer] [author] [prefixes] [suffixes]>>
}}}
!!Parameters
|!Index|!Optional|!Description|!Default Value|h
|1|yes|name of target tiddler (containing the table to be processed)|current tiddler|
|2|yes|tags to assign to newly-created tiddlers|slices2tiddlers|
|3|yes|author to assign to newly-created tiddlers|slices2tiddlers|
|4|yes|table includes header row (true/false)|false|
|5|yes|table includes footer row (true/false)|false|
|6|yes|bracketed list of prefixes to assign to newly-created tiddlers' rows (one item per row)|N/A|
|7|yes|bracketed list of suffixes to assign to newly-created tiddler's rows (one item per row)|N/A|
!!Example
{{{
<<table2tiddlers [[Log Data]] "logs" "admin" "true" "true" "|!Time| |!User| [[|!Avg. Value|]] |!Signature|" "|h | | |f">>
}}}
This will generate a table of three rows ("Time", "User", "Avg. Value") in each newly-created tiddler, provided that there are a total of four columns in the source data.
!Revision History
!!v0.1 (2008-01-10)
* initial release
!To Do
* use launch button instead of executing the macro when rendered
* instead of suffix and prefix arrays as parameters, use one parameter (prefix-suffix pair) for each row
* documentation
!Code
***/
//{{{
config.macros.table2tiddlers = {
	tags: ["slices2tiddlers"],
	modifier: "slices2tiddlers"
};

config.macros.table2tiddlers.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var tiddlerTitle = params[0] || tiddler.title;
	var tags = params[1] ? params[1].readBracketedList() : this.tags;
	var modifier = params[2] || this.modifier;
	var header = (params[3] == "true") ? true : false; // table includes header row
	var footer = (params[4] == "true") ? true : false; // table includes footer row
	var prefixes = params[5] ? params[5].readBracketedList(false) : [];
	var suffixes = params[6] ? params[6].readBracketedList(false) : [];
	var tiddlers = [];
	var errors = [];
	// retrieve individual rows
	var rows = store.getTiddlerText(tiddlerTitle);
	if(rows)
		rows = rows.split("\n");
	else
		wikify("error: tiddler not found", place);
	// create tiddlers from rows
	if(rows && rows.length > 0) {
		// remove table header and footer
		if(header)
			rows.splice(0, 1);
		if(footer)
			rows.splice(rows.length - 1, 1);
		// create tiddlers
		var cols, title, text;
		for(var i = 0; i < rows.length; i++) {
			// retrieve columns
			cols = rows[i].split("|");
			cols.splice(0, 1); // remove first element (always empty)
			cols.splice(cols.length - 1, 1); // remove last element (always empty)
			// create new tiddler
			title = cols[0];
			text = "";
			for(var j = 1; j < cols.length; j++) {
				text += (prefixes[j - 1] || "")
					+ cols[j]
					+ (suffixes[j - 1] || "")
					+ "\n";
			}
			if(!store.tiddlerExists(title)) { // do not overwrite local tiddlers
				store.saveTiddler(title, title, text, modifier, (new Date), tags, null, null, (new Date));
				tiddlers.push(title);
			} else {
				errors.push(title);
			}
		}
		// report results
		var output = "";
		if(errors.length > 0) {
			output += "!Tiddlers Not Created (" + errors.length + ")\n";
			for(i = 0; i < errors.length; i++)
				output += "* [[" + errors[i] + "]]\n";
		}
		if(tiddlers.length > 0) {
			output += "!Tiddlers Created (" + tiddlers.length + ")\n";
			for(i = 0; i < tiddlers.length; i++)
				output += "* [[" + tiddlers[i] + "]]\n";
		}
		wikify(output, place);
	}
};
//}}}
/***
|''Name''|TagBoxToggleMacro|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#TagBoxToggleMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Description''|toggles the visibility of the respective tiddler's tag box|
!Usage
{{{
<<taggedToggle
	[class name]
	[button label]
	[button tooltip]
	[button class]
	[button access key]
	[startup mode]
>>
}}}
!!Example
<<taggedToggle "" "" "" "" "" "hide">>
!Revision History
!!v0.1 (2007-12-20)
* initial release
!To Do
* documentation
!Code
***/
//{{{
config.macros.taggedToggle = {
	className: "tagged",
	label: "Toggle Tagged",
	prompt: "Switch tag box on and off",
	buttonClass: "",
	accessKey: ""
};

config.macros.taggedToggle.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	// process command line parameters
	var className = params[0] || this.className;
	var label = params[1] || this.label;
	var prompt = params[2] || this.prompt;
	var buttonClass = params[3] || this.buttonClass;
	var accessKey = params[4] || this.accessKey;
	// startup mode
	var t = story.findContainingTiddler(place);
	if(params[5] == "hide") {
		this.toggle(t, className);
	}
	// create toggle button
	createTiddlyButton(place, label, prompt,
		function() { config.macros.taggedToggle.toggle(t, className); },
		buttonClass, null, accessKey);
};

config.macros.taggedToggle.toggle = function(el, className) {
	if(el) {
		els = getElementsByClass(className, el);
		if(els[0].style.display != "none") {
			els[0].style.display = "none";
		} else {
			els[0].style.display = "";
		}
	}
};

/* by Dustin Diaz (http://www.dustindiaz.com/getelementsbyclass/) */
function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\\\s)"+searchClass+"(\\\\s|$)");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}
//}}}
/***
|''Name''|TagComboMacro|
|''Version''|0.1|
|''Status''|@@experimental@@|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#TagComboMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|returns a list of tiddlers matching a combination of tags|
!Usage
{{{
<<tagcombo [tag1] [tag2] [tag3] ... >>
}}}
!!Example
<<tagcombo [[systemConfig]] [[plugins]]>>
!Revision History
!!v0.1 (2007-11-30)
* initial release
!To Do
* rename
* remove excessive spacing (i.e. replace {{{.join()}}} with {{{for()}}} loop!?)
* custom output format (e.g. comma-separated list)
!Code
***/
//{{{
config.macros.tagcombo = {};
config.macros.tagcombo.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var r = [];
	var t = store.getTaggedTiddlers(params[0]);
	for(var i = 0; i < t.length; i++) {
		if(t[i].tags.containsAll(params)) {
			r.push(t[i].title);
		}
	}
	wikify("* [[" + r.join("]]\n* [[") + "]]", place);
}
//}}}
(preliminary implementation at [[ForEachTiddlerTest]])
!Name
* TagNavigatorPlugin
* DynamicTagTreePlugin (or TagTreePlugin)
* TagComboPlugin
!User Interface
{{{
 __________________________________
|                _______    _____  |
| Tag 1  Tag 2  | Tag 3 |  | add | |
|                ϯϯϯϠ   +------------+
|ϯϯϯϯϯϯϯϯϯϯϯϯϯϼ* [[Tag 4]] |
| * [[Tiddler 1]]           |* [[Tag 5]] |
| * [[Tiddler 2]]           |* [[Tag 6]] |
| * [[Tiddler 3]]           +------------+
| * [[Tiddler 4]]                  |
| * [[Tiddler 5]]                  |
| * [[Tiddler 6]]                  |
|__________________________________|
}}}
* upper part: tag (de)selection
** "Tag 3" removes this tag from the combination
** "add" expands a list of available tags (tags 4-6) to add to the combination (listed are only tags used in combination with the previously-selected tags)
* lower part: tiddler selection (list of tiddlers using the selected tags)
!Flowchart 
{{{
	+---------------------+
	| select all tiddlers |                store
	+---------------------+
	        |
	        V
	/ϯϯϯϯϯϯϯϯϯϯϯϯϯϜs
	| list of matching tiddlers |<----+    story object
	\___________________________/     |
	        |                         |
	        V                         |
	+-----------------------------+   |
	| retrieve tags from tiddlers |   |    using getTags(), or forEachTiddler() and .tags property
	+-----------------------------+   |
	        |                         |
	        V                         |
	+----------------------+          |
	| filter and sort tags |          |    using pushUnique() or readBracketedList() -- possibly obsolete (see above)
	+----------------------+          |
	        |                         |
	        V                         |
	/ϯϯϯϯϯϯϯϯϯϯϜs           |
	| list of unique tags |           |
	\_____________________/           |
	        |                         |
	        V                         |
	  /ϯϯϯϯϯϯ/                  |
	 / select tag /                   |    == BREAK POINT ==
	/____________/                    |
	        |                         |
	        V                         |
	+--------------------------+      |
	| select matching tiddlers |      |    using getTaggedTiddlers() -- problem (now obsolete?): how to return a story object?
	+--------------------------+      |
	        |                         |
	        V                         |
	+-------------------------+       |
	| retrieve tiddler titles |-------+    using forEachTiddler() and .title property
	+-------------------------+
	


	Key:
	ϯϯ
	+---------+    /ϯϯϯϯ\      /ϯϯϯϯϯϯϯ
	| Process |    | Result |     / Interaction /
	+---------+    \________/    /_____________/
}}}
/***
|Name|TagNavigatorPlugin (working title)|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#TagNavigatorPlugin]]|
|Version|0.1|
|Author|FND|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|select tiddlers based on tag combinations|
!Usage
{{{<<TagNav tag1 tag2 tag3 ... >>}}}
''N.B.:'' Tags containing spaces must be enclosed either in {{{[[brackets]]}}} or in {{{"quotation marks"}}}.
!Revision History
!!v0.1 (2007-06-08)
* initial alpha version
!Issues / To Do
* many, many issues; cf. DEBUG markers in code
* popup menu can't be closed yet (can even be opened multiple times!)
* displayed  the count of the number of matching tiddlers
!Code
***/
//{{{
// create TagNavigator namespace
TagNav = {};

// create shadow tiddler for CSS rules
TagNav.addStyles = function(shadowTiddler) {
	config.shadowTiddlers[shadowTiddler] = "/*{{{*/\n"
		+ "#TagNavigator {\n"
		+ "\tposition: absolute;\n" // DEBUG: messy display (overlay issues)
		+ "\tz-index: 99;\n"
		+ "\tmargin: 0;\n"
		+ "\tborder: 1px solid [[ColorPalette::PrimaryDark]];\n"
		+ "\tpadding: 0;\n"
		+ "\tbackground-color: [[ColorPalette::TertiaryPale]];\n"
		+ "}\n\n"
		+ "#TagNavigatorTagBar,\n"
		+ "#TagNavigatorTiddlers {\n"
		+ "\tmargin: 0;\n"
		+ "\tpadding: 5px;\n"
		+ "\tlist-style-type: none;\n"
		+ "}\n\n"
		+ "#TagNavigatorTagBar {\n"
		+ "\tmargin-bottom: 1.2em;\n" // required due to floating
		+ "}\n\n"
		+ "#TagNavigatorTiddlers {\n"
		+ "\tclear: both;\n"
		+ "\tborder-top: 1px solid [[ColorPalette::PrimaryDark]];\n"
		+ "}\n\n"
		+ "#TagNavigatorTagBar li {\n"
		+ "\tfloat: left;\n"
		+ "\tmargin: 0 0.2em 0.5em;\n"
		+ "}\n\n"
		+ "#TagNavigator .buttonClose {\n"
		+ "\tfloat: left;\n" // DEBUG: temporary solution (right-floating expands container width)
		+ "\tmargin: 0 5px 5px 0;\n"
		+ "\tborder: 1px solid [[ColorPalette::PrimaryDark]];\n"
		+ "\tpadding: 0 1px;\n"
		+ "}\n"
		+ "/*}}}*/";
	store.addNotification(shadowTiddler, refreshStyles);
}
TagNav.addStyles("StyleSheetTagNavigator");

/*
** Macro
*/

config.macros.TagNav = {
	label: "Tag Navigator",
	prompt: "select tiddlers based on tag combinations",
	accessKey: null
};

config.macros.TagNav.handler =
	function(place, macroName, params, wikifier, paramString, tiddler) {
		// create macro button
		createTiddlyButton(place, this.label, this.prompt,
			function() {
				// select active button
				TagNav.Btn = this;
				// close (remove) existing popups
				TagNav.popupClose(TagNav.Container, TagNav.active);
				// set activity status				
				TagNav.active = true;
				// process macro parameters (initial tags)
				TagNav.activeTags = [];
				if(params[0]) {
					for(var i = 0; i < params.length; i++) {
						TagNav.activeTags.pushUnique(params[i], true);
					}
				}
				// initialize
				TagNav.initializeTiddlerSelection();
				TagNav.initializeInterface();
				return false; // DEBUG: purpose? obsolete?
			},
			null, null, this.accessKey);
		return false; // DEBUG: purpose? obsolete?
}

/*
** Initialization
*/

// initialize tiddler selection
TagNav.initializeTiddlerSelection = function() {
	// get all tiddlers
	TagNav.tiddlers = store.reverseLookup("tags", "", false, "title"); // DEBUG: dirty hack!?
	// get tiddler titles
	TagNav.titles = TagNav.getTiddlerTitles(TagNav.tiddlers);
	// get tiddler tags
	TagNav.tags = TagNav.getTiddlerTags(TagNav.tiddlers);
	// process initial tags
	if(TagNav.activeTags.length > 0) {
		for(var i = 0; i < TagNav.activeTags.length; i++) {
			// update matching tiddler set
			TagNav.filter(TagNav.activeTags[i])
		}
	} 
}

// initialize Tag Navigator interface
TagNav.initializeInterface = function() {
	// create container elements
	TagNav.Container = createTiddlyElement(document.body, "div", "TagNavigator", null, null); // DEBUG: using document.body as parent only sub-optimal?	 
	btn = createTiddlyButton(TagNav.Container, "x", "close Tag Navigator popup", TagNav.popupClose, "buttonClose", null, null); // close button
	TagNav.TagBar = createTiddlyElement(TagNav.Container, "ul", "TagNavigatorTagBar", null, null);
	TagNav.TiddlerBox = createTiddlyElement(TagNav.Container, "ul", "TagNavigatorTiddlers", null, null);
	// adjust Tag Navigator popup position
	TagNav.popupPosition(TagNav.Btn, TagNav.Container);
	 // add previously-selected filter tags to tag bar
	var item, btn;
	for(var i = 0; i < TagNav.activeTags.length; i++) {
		item = createTiddlyElement(TagNav.TagBar, "li", null, null, null);
		btn = createTiddlyButton(item, TagNav.activeTags[i], null, null, "buttonBland", null, null); // DEBUG: buttonBland class not styled yet
	}
	 // add button for new filter tag to tag bar
	item = createTiddlyElement(TagNav.TagBar, "li", null, null, null);
	btn = createTiddlyButton(item, "+", "add a tag to filter by", TagNav.tagSelection, null, null, null);
	// fill in contents of tiddler
	TagNav.listTiddlerTitles(TagNav.TiddlerBox, TagNav.titles);	
}

/*
** Interface
*/

// event click on tiddler button: open tiddler and close popups
TagNav.tiddlerSelection = function(e) {
	var theTarget = resolveTarget(e);
	// close popup
	TagNav.popupClose();
	// open tiddler
	var title = theTarget.getAttribute("tiddler");
	story.displayTiddler(null, title); // DEBUG: temporary workaround (see below)
	//onClickTiddlerLink(e); // DEBUG: causes error "theLink.getAttribute is not a function"
}

// event click on tag button: add new filtering level
TagNav.tagSelection = function(e) {
	//TagNav.listTiddlerTags(TagNav.TagBar, TagNav.tags); // DEBUG'd: continue here
	/* DEBUG'd
	var theTarget = resolveTarget(e);
	var tag = theTarget.getAttribute("tag");
	if(tag) {
		// update matching tiddler set
		TagNav.filter(tag);
		// create sub-menu -- DEBUG: buggy/incomplete (e.g. how to close popups)
		TagNav.subMenus.push(Popup.create(theTarget));
		var TagNavigator = createTiddlyElement(theTarget, "ul", "TagNavigator", null, null);
		TagNav.listTiddlers(TagNavigator, TagNav.titles);
		TagNav.listTags(TagNavigator, TagNav.tags);
		Popup.show(TagNavigator, false);
	}
	*/
}

// adjust Tag Navigator popup position -- based upon Popup.show()
TagNav.popupPosition = function(parent, popup) {
	var rootLeft = findPosX(parent);
	var rootTop = findPosY(parent);
	var rootHeight = parent.offsetHeight;
	var popupLeft = rootLeft;
	var popupTop = rootTop + rootHeight;
	var popupWidth = popup.offsetWidth;
	var winWidth = findWindowWidth();
	if(popupLeft + popupWidth > winWidth)
		popupLeft = winWidth - popupWidth;
	popup.style.left = popupLeft + "px";
	popup.style.top = popupTop + "px";
	popup.style.display = "block";
	if(anim && config.options.chkAnimate)
		anim.startAnimating(new Scroller(popup, false));
	else
		window.scrollTo(0,ensureVisible(popup));
}

// close (remove) existing popup
TagNav.popupClose = function(popup, check) {
	if(check) {
		popup.parentNode.removeChild(popup);
	}
	check = false;
}

/*
** Tiddler Processing
*/

// retrieve tiddlers with a specific tag from tiddlers array
TagNav.getTaggedTiddlers = function(container, tag) {
	var tiddlers = [];
	for(var i = 0; i < container.length; i++) {
		if(container[i].tags.contains(tag)) {
			tiddlers.push(container[i]);
		}
	}
	return tiddlers;
}

// retrieve titles from tiddlers array
TagNav.getTiddlerTitles = function(container) {
	var titles = [];
	for(var i = 0; i < container.length; i++) {
		titles.push(container[i].title);
	}
	titles.sort();
	return titles;
}

// retrieve tags from tiddlers array
TagNav.getTiddlerTags = function(tiddlers) {
	var tags = [];
	for(var i = 0; i < tiddlers.length; i++) {
		for(var j = 0; j < tiddlers[i].tags.length; j++) {
			tags.pushUnique(tiddlers[i].tags[j]);
		}
	}
	tags.sort();
	return tags;
}

// update matching tiddler set
TagNav.filter = function(tag) {
	TagNav.tiddlers = TagNav.getTaggedTiddlers(TagNav.tiddlers, tag);
	TagNav.titles = TagNav.getTiddlerTitles(TagNav.tiddlers);
	TagNav.tags = TagNav.getTiddlerTags(TagNav.tiddlers);
}

// create list of tiddlers as links
TagNav.listTiddlerTitles = function(parent, titles) {
	var item, btn;
	if(titles.length == 0) {
		createTiddlyElement(parent, "span", null, null, "no matching tiddlers");
	}
	for(var i = 0; i < titles.length; i++) {
		item = createTiddlyElement(parent, "li", null, null, null);
		btn = createTiddlyButton(item, titles[i], "open tiddler", TagNav.tiddlerSelection, "tiddlyLink tiddlyLinkExisting");
		btn.setAttribute("tiddler", titles[i]);
	}
}

// create list of tags as links -- DEBUG: revise titles and prompts
TagNav.listTiddlerTags = function(parent, tags) {
	var item, btn;
	if(tags.length == 0) {
		createTiddlyElement(parent, "li", null, null, "no matching tags");
	}
	for(var i = 0; i < tags.length; i++) {
		item = createTiddlyElement(parent, "li", null, null, null);
		btn = createTiddlyButton(item, tags[i], "filter using this tag", TagNav.tagSelection);
		btn.setAttribute("tag", tags[i]);
	}
}
//}}}
This is the sandbox for testing the TagNavigatorPlugin.
Activate the Tag Navigator by using the button below.
The styling can be changed in the StyleSheetTagNavigator shadow tiddler.

|<<TagNav projects>><br>(no initial tags)|<<TagNav systemConfig>><br>(inital tag "systemConfig")|<<TagNav systemConfig plugin>><br>(inital tags "systemConfig" and "plugin")|
/***
|''Name''|TaggedBackupsPlugin|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#TableHighlightMacro]]|
|''Version''|0.1|
|''Author''|FND|
|''License''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|allows the creation of backup files with an edit summary|
!Usage Notes
<<taggedBackup>>
!Revision History
!!v0.1 (2007-08-11)
* initial proof-of-concept implementation
!To Do
* rename plugin(?)
* ensure that full backup path does not exceed OS limits (256 chars?)
!Code
***/
//{{{
config.macros.taggedBackup = {}
config.macros.taggedBackup.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var originalPath = document.location.toString();
	var localPath = getLocalPath(originalPath);
	var original = loadFile(localPath);
	var backupPath = getBackupPath(localPath);
	alert(originalPath + "\n" + localPath + "\n" + backupPath) // DEBUG
	// insert edit summary ("tag")
	var backupFileName = backupPath.substring(0, backupPath.lastIndexOf("."));
	var backupFileExt = backupPath.substring(backupPath.lastIndexOf("."));
	//prompt("Please enter a concise edit summary"); // DEBUG'd
	alert(backupPath) // DEBUG
	//var backup = saveFile(backupPath, original); // DEBUG'd
	if(backup)
		displayMessage(config.messages.backupSaved, "file://" + backupPath);
	else
		alert(config.messages.backupFailed);
}

// getBackupPath() -- DEBUG: needs to be hijacked/overwritten
function getBackupPath(localPath)
{
	var backSlash = true;
	var dirPathPos = localPath.lastIndexOf("\\");
	if(dirPathPos == -1)
		{
		dirPathPos = localPath.lastIndexOf("/");
		backSlash = false;
		}
	var backupFolder = config.options.txtBackupFolder;
	if(!backupFolder || backupFolder == "")
		backupFolder = ".";
	var backupPath = localPath.substr(0,dirPathPos) + (backSlash ? "\\" : "/") + backupFolder + localPath.substr(dirPathPos);
	backupPath = backupPath.substr(0,backupPath.lastIndexOf(".")) + "." + (new Date()).convertToYYYYMMDDHHMMSSMMM() + ".html"; // DEBUG: replace YYYYMMDDHHMMSSMMM with ISO 8601 and add edit summary
	return backupPath;
}
//}}}
/***
|Name:|TagglyTaggingPlugin|
|Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
|Version:|3.3.2a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
See http://mptw.tiddlyspot.com/#TagglyTagging
***/
//{{{

merge(String.prototype,{

  parseTagExpr: function(debug) {

    if (this.trim() == "")
      return "(true)";

    var anyLogicOp = /(!|&&|\|\||\(|\))/g;
    var singleLogicOp = /^(!|&&|\|\||\(|\))$/;

    var spaced = this.
      // because square brackets in templates are no good
      // this means you can use [(With Spaces)] instead of [[With Spaces]]
      replace(/\[\(/g," [[").
      replace(/\)\]/g,"]] ").
      // space things out so we can use readBracketedList. tricky eh?
      replace(anyLogicOp," $1 ");

    var expr = "";

    var tokens = spaced.readBracketedList(false); // false means don't uniq the list. nice one JR!

    for (var i=0;i<tokens.length;i++)
      if (tokens[i].match(singleLogicOp))
        expr += tokens[i];
      else
        expr += "tiddler.tags.contains('%0')".format([tokens[i].replace(/'/,"\\'")]); // fix single quote bug. still have round bracket bug i think

    if (debug)
      alert(expr);

    return '('+expr+')';
  }

});

merge(TiddlyWiki.prototype,{
  getTiddlersByTagExpr: function(tagExpr,sortField) {

    var result = [];

    var expr = tagExpr.parseTagExpr();

    store.forEachTiddler(function(title,tiddler) {
      if (eval(expr))
        result.push(tiddler);
    });

    if(!sortField)
      sortField = "title";

    result.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});

    return result;
  }
});

config.taggly = {

  // for translations
  lingo: {
    labels: {
      asc:        "\u2191", // down arrow
      desc:       "\u2193", // up arrow
      title:      "title",
      modified:   "modified",
      created:    "created",
      show:       "+",
      hide:       "-",
      normal:     "normal",
      group:      "group",
      commas:     "commas",
      sitemap:    "sitemap",
      numCols:    "cols\u00b1", // plus minus sign
      label:      "Tagged as '%0':",
      exprLabel:  "Matching tag expression '%0':",
      excerpts:   "excerpts",
      descr:      "descr",
      slices:     "slices",
      contents:   "contents",
      sliders:    "sliders",
      noexcerpts: "title only",
      noneFound:  "(none)"
    },

    tooltips: {
      title:      "Click to sort by title",
      modified:   "Click to sort by modified date",
      created:    "Click to sort by created date",
      show:       "Click to show tagging list",
      hide:       "Click to hide tagging list",
      normal:     "Click to show a normal ungrouped list",
      group:      "Click to show list grouped by tag",
      sitemap:    "Click to show a sitemap style list",
      commas:     "Click to show a comma separated list",
      numCols:    "Click to change number of columns",
      excerpts:   "Click to show excerpts",
      descr:      "Click to show the description slice",
      slices:     "Click to show all slices",
      contents:   "Click to show entire tiddler contents",
      sliders:    "Click to show tiddler contents in sliders",
      noexcerpts: "Click to show entire title only"
    },

    tooDeepMessage: "* //sitemap too deep...//"
  },

  config: {
    showTaggingCounts: true,
    listOpts: {
      // the first one will be the default
      sortBy:     ["title","modified","created"],
      sortOrder:  ["asc","desc"],
      hideState:  ["show","hide"],
      listMode:   ["normal","group","sitemap","commas"],
      numCols:    ["1","2","3","4","5","6"],
      excerpts:   ["noexcerpts","excerpts","descr","slices","contents","sliders"]
    },
    valuePrefix: "taggly.",
    excludeTags: ["excludeLists","excludeTagging"],
    excerptSize: 50,
    excerptMarker: "/%"+"%/",
    siteMapDepthLimit: 25
  },

  getTagglyOpt: function(title,opt) {
    var val = store.getValue(title,this.config.valuePrefix+opt);
    return val ? val : this.config.listOpts[opt][0];
  },

  setTagglyOpt: function(title,opt,value) {
    // create it silently if it doesn't exist
    if (!store.tiddlerExists(title)) {
      store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),"");

      // <<tagglyTagging expr:"...">> creates a tiddler to store its display settings
      // Make those tiddlers less noticeable by tagging as excludeSearch and excludeLists
      // Because we don't want to hide real tags, check that they aren't actually tags before doing so
      // Also tag them as tagglyExpression for manageability
      // (contributed by RA)
      if (!store.getTaggedTiddlers(title).length) {
        store.setTiddlerTag(title,true,"excludeSearch");
        store.setTiddlerTag(title,true,"excludeLists");
        store.setTiddlerTag(title,true,"tagglyExpression");
      }
    }

    // if value is default then remove it to save space
    return store.setValue(title, this.config.valuePrefix+opt, value == this.config.listOpts[opt][0] ? null : value);
  },

  getNextValue: function(title,opt) {
    var current = this.getTagglyOpt(title,opt);
    var pos = this.config.listOpts[opt].indexOf(current);
    // supposed to automagically don't let cols cycle up past the number of items
    // currently broken in some situations, eg when using an expression
    // lets fix it later when we rewrite for jquery
    // the columns thing should be jquery table manipulation probably
    var limit = (opt == "numCols" ? store.getTaggedTiddlers(title).length : this.config.listOpts[opt].length);
    var newPos = (pos + 1) % limit;
    return this.config.listOpts[opt][newPos];
  },

  toggleTagglyOpt: function(title,opt) {
    var newVal = this.getNextValue(title,opt);
    this.setTagglyOpt(title,opt,newVal);
  },

  createListControl: function(place,title,type) {
    var lingo = config.taggly.lingo;
    var label;
    var tooltip;
    var onclick;

    if ((type == "title" || type == "modified" || type == "created")) {
      // "special" controls. a little tricky. derived from sortOrder and sortBy
      label = lingo.labels[type];
      tooltip = lingo.tooltips[type];

      if (this.getTagglyOpt(title,"sortBy") == type) {
        label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
        onclick = function() {
          config.taggly.toggleTagglyOpt(title,"sortOrder");
          return false;
        }
      }
      else {
        onclick = function() {
          config.taggly.setTagglyOpt(title,"sortBy",type);
          config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);
          return false;
        }
      }
    }
    else {
      // "regular" controls, nice and simple
      label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
      tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
      onclick = function() {
        config.taggly.toggleTagglyOpt(title,type);
        return false;
      }
    }

    // hide button because commas don't have columns
    if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
      createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");
  },

  makeColumns: function(orig,numCols) {
    var listSize = orig.length;
    var colSize = listSize/numCols;
    var remainder = listSize % numCols;

    var upperColsize = colSize;
    var lowerColsize = colSize;

    if (colSize != Math.floor(colSize)) {
      // it's not an exact fit so..
      upperColsize = Math.floor(colSize) + 1;
      lowerColsize = Math.floor(colSize);
    }

    var output = [];
    var c = 0;
    for (var j=0;j<numCols;j++) {
      var singleCol = [];
      var thisSize = j < remainder ? upperColsize : lowerColsize;
      for (var i=0;i<thisSize;i++)
        singleCol.push(orig[c++]);
      output.push(singleCol);
    }

    return output;
  },

  drawTable: function(place,columns,theClass) {
    var newTable = createTiddlyElement(place,"table",null,theClass);
    var newTbody = createTiddlyElement(newTable,"tbody");
    var newTr = createTiddlyElement(newTbody,"tr");
    for (var j=0;j<columns.length;j++) {
      var colOutput = "";
      for (var i=0;i<columns[j].length;i++)
        colOutput += columns[j][i];
      var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
      wikify(colOutput,newTd);
    }
    return newTable;
  },

  createTagglyList: function(place,title,isTagExpr) {
    switch(this.getTagglyOpt(title,"listMode")) {
      case "group":  return this.createTagglyListGrouped(place,title,isTagExpr); break;
      case "normal": return this.createTagglyListNormal(place,title,false,isTagExpr); break;
      case "commas": return this.createTagglyListNormal(place,title,true,isTagExpr); break;
      case "sitemap":return this.createTagglyListSiteMap(place,title,isTagExpr); break;
    }
  },

  getTaggingCount: function(title,isTagExpr) {
    // thanks to Doug Edmunds
    if (this.config.showTaggingCounts) {
      var tagCount = config.taggly.getTiddlers(title,'title',isTagExpr).length;
      if (tagCount > 0)
        return " ("+tagCount+")";
    }
    return "";
  },

  getTiddlers: function(titleOrExpr,sortBy,isTagExpr) {
    return isTagExpr ? store.getTiddlersByTagExpr(titleOrExpr,sortBy) : store.getTaggedTiddlers(titleOrExpr,sortBy);
  },

  getExcerpt: function(inTiddlerTitle,title,indent) {
    if (!indent)
      indent = 1;

    var displayMode = this.getTagglyOpt(inTiddlerTitle,"excerpts");
    var t = store.getTiddler(title);

    if (t && displayMode == "excerpts") {
      var text = t.text.replace(/\n/," ");
      var marker = text.indexOf(this.config.excerptMarker);
      if (marker != -1) {
        return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
      }
      else if (text.length < this.config.excerptSize) {
        return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
      }
      else {
        return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
      }
    }
    else if (t && displayMode == "contents") {
      return "\n{{contents indent"+indent+"{\n" + t.text + "\n}}}";
    }
    else if (t && displayMode == "sliders") {
      return "<slider slide>\n{{contents{\n" + t.text + "\n}}}\n</slider>";
    }
    else if (t && displayMode == "descr") {
      var descr = store.getTiddlerSlice(title,'Description');
      return descr ? " {{excerpt{" + descr  + "}}}" : "";
    }
    else if (t && displayMode == "slices") {
      var result = "";
      var slices = store.calcAllSlices(title);
      for (var s in slices)
        result += "|%0|<nowiki>%1</nowiki>|\n".format([s,slices[s]]);
      return result ? "\n{{excerpt excerptIndent{\n" + result  + "}}}" : "";
    }
    return "";
  },

  notHidden: function(t,inTiddler) {
    if (typeof t == "string")
      t = store.getTiddler(t);
    return (!t || !t.tags.containsAny(this.config.excludeTags) ||
        (inTiddler && this.config.excludeTags.contains(inTiddler)));
  },

  // this is for normal and commas mode
  createTagglyListNormal: function(place,title,useCommas,isTagExpr) {

    var list = config.taggly.getTiddlers(title,this.getTagglyOpt(title,"sortBy"),isTagExpr);

    if (this.getTagglyOpt(title,"sortOrder") == "desc")
      list = list.reverse();

    var output = [];
    var first = true;
    for (var i=0;i<list.length;i++) {
      if (this.notHidden(list[i],title)) {
        var countString = this.getTaggingCount(list[i].title);
        var excerpt = this.getExcerpt(title,list[i].title);
        if (useCommas)
          output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
        else
          output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");

        first = false;
      }
    }

    return this.drawTable(place,
      this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
      useCommas ? "commas" : "normal");
  },

  // this is for the "grouped" mode
  createTagglyListGrouped: function(place,title,isTagExpr) {
    var sortBy = this.getTagglyOpt(title,"sortBy");
    var sortOrder = this.getTagglyOpt(title,"sortOrder");

    var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

    if (sortOrder == "desc")
      list = list.reverse();

    var leftOvers = []
    for (var i=0;i<list.length;i++)
      leftOvers.push(list[i].title);

    var allTagsHolder = {};
    for (var i=0;i<list.length;i++) {
      for (var j=0;j<list[i].tags.length;j++) {

        if (list[i].tags[j] != title) { // not this tiddler

          if (this.notHidden(list[i].tags[j],title)) {

            if (!allTagsHolder[list[i].tags[j]])
              allTagsHolder[list[i].tags[j]] = "";

            if (this.notHidden(list[i],title)) {
              allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
                    + this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";

              leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers

            }
          }
        }
      }
    }

    var allTags = [];
    for (var t in allTagsHolder)
      allTags.push(t);

    var sortHelper = function(a,b) {
      if (a == b) return 0;
      if (a < b) return -1;
      return 1;
    };

    allTags.sort(function(a,b) {
      var tidA = store.getTiddler(a);
      var tidB = store.getTiddler(b);
      if (sortBy == "title") return sortHelper(a,b);
      else if (!tidA && !tidB) return 0;
      else if (!tidA) return -1;
      else if (!tidB) return +1;
      else return sortHelper(tidA[sortBy],tidB[sortBy]);
    });

    var leftOverOutput = "";
    for (var i=0;i<leftOvers.length;i++)
      if (this.notHidden(leftOvers[i],title))
        leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";

    var output = [];

    if (sortOrder == "desc")
      allTags.reverse();
    else if (leftOverOutput != "")
      // leftovers first...
      output.push(leftOverOutput);

    for (var i=0;i<allTags.length;i++)
      if (allTagsHolder[allTags[i]] != "")
        output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);

    if (sortOrder == "desc" && leftOverOutput != "")
      // leftovers last...
      output.push(leftOverOutput);

    return this.drawTable(place,
        this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),
        "grouped");

  },

  // used to build site map
  treeTraverse: function(title,depth,sortBy,sortOrder,isTagExpr) {

    var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

    if (sortOrder == "desc")
      list.reverse();

    var indent = "";
    for (var j=0;j<depth;j++)
      indent += "*"

    var childOutput = "";

    if (depth > this.config.siteMapDepthLimit)
      childOutput += indent + this.lingo.tooDeepMessage + "\n";
    else
      for (var i=0;i<list.length;i++)
        if (list[i].title != title)
          if (this.notHidden(list[i].title,this.config.inTiddler))
            childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder,false);

    if (depth == 0)
      return childOutput;
    else
      return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title,depth) + "\n" + childOutput;
  },

  // this if for the site map mode
  createTagglyListSiteMap: function(place,title,isTagExpr) {
    this.config.inTiddler = title; // nasty. should pass it in to traverse probably
    var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"),isTagExpr);
    return this.drawTable(place,
        this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic
        "sitemap"
        );
  },

  macros: {
    tagglyTagging: {
      handler: function (place,macroName,params,wikifier,paramString,tiddler) {
        var parsedParams = paramString.parseParams("tag",null,true);
        var refreshContainer = createTiddlyElement(place,"div");

        // do some refresh magic to make it keep the list fresh - thanks Saq
        refreshContainer.setAttribute("refresh","macro");
        refreshContainer.setAttribute("macroName",macroName);

        var tag = getParam(parsedParams,"tag");
        var expr = getParam(parsedParams,"expr");

        if (expr) {
          refreshContainer.setAttribute("isTagExpr","true");
          refreshContainer.setAttribute("title",expr);
          refreshContainer.setAttribute("showEmpty","true");
        }
        else {
          refreshContainer.setAttribute("isTagExpr","false");
          if (tag) {
                refreshContainer.setAttribute("title",tag);
            refreshContainer.setAttribute("showEmpty","true");
          }
          else {
                refreshContainer.setAttribute("title",tiddler.title);
            refreshContainer.setAttribute("showEmpty","false");
          }
        }
        this.refresh(refreshContainer);
      },

      refresh: function(place) {
        var title = place.getAttribute("title");
        var isTagExpr = place.getAttribute("isTagExpr") == "true";
        var showEmpty = place.getAttribute("showEmpty") == "true";
        jQuery(place).empty()
        addClass(place,"tagglyTagging");
        var countFound = config.taggly.getTiddlers(title,'title',isTagExpr).length
        if (countFound > 0 || showEmpty) {
          var lingo = config.taggly.lingo;
          config.taggly.createListControl(place,title,"hideState");
          if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
            createTiddlyElement(place,"span",null,"tagglyLabel",
                isTagExpr ? lingo.labels.exprLabel.format([title]) : lingo.labels.label.format([title]));
            config.taggly.createListControl(place,title,"title");
            config.taggly.createListControl(place,title,"modified");
            config.taggly.createListControl(place,title,"created");
            config.taggly.createListControl(place,title,"listMode");
            config.taggly.createListControl(place,title,"excerpts");
            config.taggly.createListControl(place,title,"numCols");
            config.taggly.createTagglyList(place,title,isTagExpr);
            if (countFound == 0 && showEmpty)
              createTiddlyElement(place,"div",null,"tagglyNoneFound",lingo.labels.noneFound);
          }
        }
      }
    }
  },

  // todo fix these up a bit
  styles: [
"/*{{{*/",
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
" margin-top:0px; padding-top:0.5em; padding-left:2em;",
" margin-bottom:0px; padding-bottom:0px;",
"}",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
" color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
" border:0px; padding-left:0.3em;padding-right:0.3em;",
"}",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active  {",
" border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
"}",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryDark]]; }",
".excerptIndent { margin-left:4em; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
"td.tagglyTagging",
" {border-style:none!important; }",
".tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;",
"  margin-bottom:0.5em; }",
".tagglyTagging .indent1  { margin-left:3em;  }",
".tagglyTagging .indent2  { margin-left:4em;  }",
".tagglyTagging .indent3  { margin-left:5em;  }",
".tagglyTagging .indent4  { margin-left:6em;  }",
".tagglyTagging .indent5  { margin-left:7em;  }",
".tagglyTagging .indent6  { margin-left:8em;  }",
".tagglyTagging .indent7  { margin-left:9em;  }",
".tagglyTagging .indent8  { margin-left:10em; }",
".tagglyTagging .indent9  { margin-left:11em; }",
".tagglyTagging .indent10 { margin-left:12em; }",
".tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }",
"/*}}}*/",
    ""].join("\n"),

  init: function() {
    merge(config.macros,this.macros);
    config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;
    store.addNotification("TagglyTaggingStyles",refreshStyles);
  }
};

config.taggly.init();

//}}}

/***
InlineSlidersPlugin
By Saq Imtiaz
http://tw.lewcid.org/sandbox/#InlineSlidersPlugin

// syntax adjusted to not clash with NestedSlidersPlugin
// added + syntax to start open instead of closed

***/
//{{{
config.formatters.unshift( {
  name: "inlinesliders",
  // match: "\\+\\+\\+\\+|\\<slider",
  match: "\\<slider",
  // lookaheadRegExp: /(?:\+\+\+\+|<slider) (.*?)(?:>?)\n((?:.|\n)*?)\n(?:====|<\/slider>)/mg,
  lookaheadRegExp: /(?:<slider)(\+?) (.*?)(?:>)\n((?:.|\n)*?)\n(?:<\/slider>)/mg,
  handler: function(w) {
    this.lookaheadRegExp.lastIndex = w.matchStart;
    var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
    if(lookaheadMatch && lookaheadMatch.index == w.matchStart ) {
      var btn = createTiddlyButton(w.output,lookaheadMatch[2] + " "+"\u00BB",lookaheadMatch[2],this.onClickSlider,"button sliderButton");
      var panel = createTiddlyElement(w.output,"div",null,"sliderPanel");
      panel.style.display = (lookaheadMatch[1] == '+' ? "block" : "none");
      wikify(lookaheadMatch[3],panel);
      w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
    }
   },
   onClickSlider : function(e) {
    if(!e) var e = window.event;
    var n = this.nextSibling;
    n.style.display = (n.style.display=="none") ? "block" : "none";
    return false;
  }
});

//}}}
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','Background')}} Background $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','Foreground')}} Foreground $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','PrimaryPale')}} PrimaryPale $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','PrimaryLight')}} PrimaryLight $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','PrimaryMid')}} PrimaryMid $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','PrimaryDark')}} PrimaryDark $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','SecondaryPale')}} SecondaryPale $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','SecondaryLight')}} SecondaryLight $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','SecondaryMid')}} SecondaryMid $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','SecondaryDark')}} SecondaryDark $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','TertiaryPale')}} TertiaryPale $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','TertiaryLight')}} TertiaryLight $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','TertiaryMid')}} TertiaryMid $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','TertiaryDark')}} TertiaryDark $1>>
<<tiddler [[TemplateShowColor]] with:{{store.getTiddlerSlice('$1','Error')}} Error $1>>
@@margin:0 1em;padding:0 4em;background-color:$1;&nbsp;@@ @@padding-right:1em;{{{$1}}}@@ [[$2|$3]]
@@margin: 0 1em;padding: 0 4em;width: 20em;background-color: $1;&nbsp;@@ [[$2|ColorPalette]]
/***
|Name|TemporaryTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#TemporaryTiddlersPlugin|
|Version|1.1.2|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|SaverBase.prototype.externalize()|
|Options|##Configuration|
|Description|blocks tiddlers tagged with "temporary" from being saved into the TW file|
!!!!!Usage
<<<
When the TW document is saved (either to local disk or remote URL), any tiddlers tagged with "temporary" will be skipped over, so that they are not written to the file.  To keep a temporary tiddler, simply edit it and remove the tag before saving the file.  This feature can be combined with various plugins that can automatically create new tiddlers, such as [[SearchOptionsPlugin]] ([[SearchResults]]) and [[ImportTiddlersPlugin]] ([[ImportedTiddlers]]) so that these transient results are not retained when you save you document.

You can also use this tag with the {{{<<loadTiddlers>>}}} macro and the //auto-tagging// features provided by [[ImportTiddlersPlugin]], so that each time you open your document, you can automatically retrieve an up-to-date set of common tiddlers that are stored in another document (either local or via remote URL), without those tiddlers being retained when you save your document.
<<<
!!!!!Configuration
<<<
When saving the document:
<<option chkTemporaryQuiet>> Suppress reporting of individual temporary tiddlers that have not been saved
<<option chkTemporaryKeep>> Keep temporary tiddlers (i.e., ignore the 'temporary' tag)
Enter a tag value to use when marking tiddlers as temporary: <<option txtTemporaryTag>>
<<<
!!!!!Revisions
<<<
2008.11.14 [1.1.2] added "nnn temporary tiddlers not saved" summary message
2008.04.08 [1.1.1] don't automatically add configuration options to AdvancedOptions tiddler
2008.03.01 [1.1.0] added support for recognizing 'temporary' flag stored as a tiddler *field* (as an optional alternative to using a tag)
2007.02.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TemporaryTiddlersPlugin= {major: 1, minor: 1, revision: 2, date: new Date(2008,11,14)};

// configuration defaults
if (config.options.chkTemporaryKeep ==undefined) config.options.chkTemporaryKeep =false;
if (config.options.chkTemporaryQuiet==undefined) config.options.chkTemporaryQuiet=true;
if (config.options.txtTemporaryTag==undefined) config.options.txtTemporaryTag="temporary";
// lingo
config.messages.TemporaryWarning = "'%0' ...temporary tiddler";
config.messages.TemporarySummary = "%0 temporary tiddlers will not be saved";
// core override
SaverBase.prototype.externalize = function(store) 
{
	var results=[]; var totaltemps=0;
	var tiddlers=store.getTiddlers("title");
	for (var t=0; t<tiddlers.length; t++) {
		if (config.options.chkTemporaryKeep||!(tiddlers[t].fields['temporary']||tiddlers[t].isTagged(config.options.txtTemporaryTag)))
			results.push(this.externalizeTiddler(store, tiddlers[t]));
		else {
			if (!config.options.chkTemporaryQuiet) // notify user that tiddler won't be saved
				displayMessage(config.messages.TemporaryWarning.format([tiddlers[t].title]));
			totaltemps++;
		}
	}
	if (totaltemps) displayMessage(config.messages.TemporarySummary.format([totaltemps]));
	return results.join("\n");
}
//}}}
http://www.englishpage.com/verbpage/presentperfect.html
http://www.englishclub.com/grammar/verb-tenses_past.htm
http://www.englishelp.ru/learn-english/grammar/304-active-voice-tense-table.html

<div style="" class="terminal"><h3 class="">TiddlyBackpack Code</h3><pre class="terminal">cd /useful/for/terminals

or code

static final public String EFFECTIVE_CALL_WORST = "Worst";
static final public String EFFECTIVE_CALL_CUSTOM = "Custom";
static final public String EFFECTIVE_CALL_MATURITY ="Maturity";
        </pre></div>
						</div>

					</div>
See http://simonbaird.com/mptw/#CreateThemePack
/***
|Name|TidIDEPlugin|
|Source|http://www.TiddlyTools.com/#TidIDEPlugin|
|Version|1.6.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||
|Description|TiddlyWiki Integrated Development Environment - tools for authors and plugin writers|

~TidIDE (//prounounced "Tie Dyed"//) - ''Tid''dlyWiki ''I''ntegrated ''D''evelopment ''E''nvironment - tools for ~TiddlyWiki authors and editors.  

Provides a full-featured tiddler editor with key-by-key ''LIVE PREVIEW'' of //formatted// tiddler content!!  Also includes diagnostic tools to help you debug your TiddlyWiki problems by letting you view current TiddlyWiki internal option values, messages, shadows, stylesheets, notify and macro functions or display the internal DOM (Document Object Model) tree structure for any specific part of the TiddlyWiki document.
!!!!!Configuration
<<<
Automatically freeze preview updates when a tiddler takes more than <<option txtTidIDEAutoFreeze>> milliseconds to render.
<<<
!!!!!Usage/Example
<<<
{{{<<tidIDE id:example "font:Courier New" size:8pt system +edit:GettingStarted>>}}}
<<tidIDE id:example "font:Courier New" size:8pt system +edit:GettingStarted>>
!!!!!parameters:
* ''id'' - assign a unique ID to this instance of TidIDE.  (default id=current tiddler title or "" if not in a tiddler)
* ''font'' - sets the CSS font-family used by textarea controls in editor and system information panels.  Note: if the font name includes a space (e.g., Courier New), then you must enclose the entire parameter in double-quotes: {{{"font:Courier New"}}}.
* ''size'' - sets the CSS font-size used by text input and droplist controls in editor and system information panels.
* ''system'' includes system information panel.
* ''edit'' includes tiddler editor/previewer.
**''edit:here'' automatically sets the editor to show the current tiddler contents (if in a tiddler)
**''edit:tiddlertitle'' automatically sets the editor to show the specified tiddler contents
* use ''{{{[[label|tiddlertitle]]}}}'' to include 'custom panels' (and corresponding labelled checkboxes to toggle their display)
* all parameters are optional.  The default panel is "edit:here".
* panel parameters preceded by a "+" are displayed by default.  If only one panel specified in the parameters, it is automatically displayed, even if the "+" is omitted.
!!!!!using the editor
The editor includes a droplist of all tiddlers in the document, sorted alpha-numerically by tiddler title.  Shadow tiddlers that have not been customized are added to the end of this list and marked with "(shadow)".  Next to the droplist are several buttons:
* ''view'' opens the tiddler in the normal ~TiddlyWiki display area
* ''add'' prompts for a new tiddler title and begins a new editing session
* ''remove'' deletes an existing tiddler (note: shadow tiddlers cannot be removed)
* ''save'' saves changes to the tiddler currently being edited
* ''save as'' saves changes using a new tiddler title
If a tiddlername was not specified in the macro, select a tiddler from the droplist (or press ''add'') to begin editing.  Once a tiddler has been loaded into the editor, you can change it's content, enter or select tags.

Normally, when you save changes to a tiddler, the created/modified dates and tiddler author are automatically updated.  However, it is sometimes useful to make small changes to a tiddler without automatically updating the date/author information.  Select the ''minor edits'' checkbox to prevent those values from being //automatically// changed.  In addition, this enables the date/author edit fields which allows you to //manually// 'back date' a tiddler or change the author to another name.  When the tiddler is saved, the date/author values shown in the edit fields will be used.
!!!!!using the previewer
The ''preview'' checkbox adds a display area that shows you what your tiddler changes will look like, //before// committing to those changes.

By default, this preview display is automatically rendered each time a key is typed into the tiddler content edit field.  As soon as changes are entered, they will be instantly visible within the preview display.  Unfortunately, the partial tiddler source definitions that occur //during// editing may somtimes cause rendering problems, and some exceptionally complex tiddlers make take an unusually long amount of time to completely render their content.   In such cases, key-by-key display updates are undesirable or impractical.

When ''preview'' is selected, you can also select ''freeze'' to suspend automatic key-by-key preview display updates.  The preview display will not be re-rendered again until you press the ''refresh'' button, or clear the 'freeze' checkbox, or switch to editing a different tiddler.  The editor automatically freezes the preview display whenever the //rendering time// exceeds a pre-determined time limit (see configuration section), specified in milliseconds.  Note: the ''actual elapsed time'' used to process and render any given tiddler is reported in the browser's status bar area whenever that tiddler is previewed.

The previewer also can display a ''DOM viewer'' and an ''HTML viewer'' that are also updated with each keystroke.  These text-based displays can be helpful while attempting to correct or enhance the formatting of tiddler content, especially when complex combinations of wiki-syntax produce unexpected or undesired results.
!!!!!system information and TW option settings
You can use the ''system information'' panel to view a variety of system internal data and functions, and view/modify ''all'' of ~TiddlyWiki's internal config.option.* settings.  NOTE: Non-default config.options are stored in cookies and are retrieved whenever the TW document is loaded into a browser; however, ''core TW functions and custom-defined plugins can explicitly ignore or reset any locally-stored cookie values and use their own, internally-defined values'' instead.  As a result, changes to these may be completely ignored, or may only have an effect during the current TW document "session" (i.e., until the TW document is reloaded), even though a persistent cookie value has been saved.
!!!!! ~DOMViewer macro
syntax: {{{<<DOMViewer rows:nn indent:xxxx inline path elementID|tiddlertitle>>}}}

Whenever TiddlyWiki renders a given tiddler, it creates a 'tree' of DOM (Document Object Model) elements that represent the information that is displayed by the browser.  You can use the ''DOMViewer'' macro to examine the internal DOM elements that are produced by TiddlyWiki's formatter (the 'wikifier'), or elements directly produced by embedded macros that create custom formatted output.  This can be particularly helpful when trying to fine tune the layout and appearance of your tiddler content.

DOMViewer creates a textarea control and reports the DOM tree for the current 'insertion point' where the DOMViewer macro is being placed.  ''inline'' flag uses TiddlyWiki rendering instead of textarea control. ''path'' shows the relative location of each child element in the DOM tree, using subscript notation, ''[elementID or tiddlertitle]'' displays DOM elements starting from the node with the specified ID.  If that ID is not found in the DOM tree, the macro attempts to open a tiddler with that title and then displays the "tiddler"+title DOM elements that were rendered.
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''TidIDEPlugin'' (tagged with <<tag systemConfig>>)
^^documentation and javascript for macro handling^^
<<<
!!!!!Revision History
<<<
''2006.12.09 [1.6.1]'' in handler(), allow non-existing tiddler title when processing "edit:title" param
so that new tiddler (or journal) can be created directly from newTiddler, newJournal, or tidIDE macro (without pressing "new" button).  Also, set 'edit=text' attribute on text area field so that default content can be initialized from "text:xxx" parameter specified in newTiddler/newJournal macro.
''2006.11.28 [1.6.0]'' added font and size params to set CSS for form controls in editor and system info panels
|please see [[TidIDEPluginHistory]] for additional revision details|
''2006.04.15 [0.5.0]'' Initial ALPHA release. Converted from TiddlerTweaker inline script.
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].
<<<
!!!!!Code
***/
// // version info
//{{{
version.extensions.tidIDE = {major: 1, minor: 6, revision: 1, date: new Date(2006,12,9)};
//}}}

// //  macro definition
//{{{
config.macros.tidIDE = {
	versionMsg: "TidIDE v%0.%1.%2: ",
	datetimefmt: "0MM/0DD/YYYY 0hh:0mm",
	titleMsg: "Please enter a new tiddler title",
	isShadowMsg: "'%0' is a shadow tiddler and cannot be removed.",
	renderMsg: "rendering preview...",
	timeoutMsg: " (> %0ms)",
	freezeMsg: " - preview is frozen.  Press [refresh] to re-display.",
	evalMsg: "Warning!!\n\nThis action will process '%0' as a systemConfig (plugin) tiddler, and may produce unexpected results!\n\nAre you sure you want to proceed?",
	toolsDef: "<html><a href='javascript:config.macros.tidIDE.set(\"%0\",\"%1\");'>edit %1...</a></html>",
	editorLabel: "TiddlerEditor",
	systemLabel: "SystemInfo"
};
config.macros.tidIDE.handler= function(place,macroName,params) {
	var here=story.findContainingTiddler(place);
	var selectors="";
	var panels="";
	var showsys=false;
	var title="";
	var id=""; if (here) id=here.id.substr(7);
	var p=params.shift();
	if (!p) p="edit:here"; // default to editor if no params
	var openpanels=[];
	var panelcount=0;
	var fontsize="8pt";
	var fontface="Courier New,fixed";
	while (p) {
		var defOpen=(p.substr(0,1)=="+"); if (defOpen) p=p.substr(1);
		if (p.substr(0,3)=="id:")
			{ id=p.substr(3); }
		else if (p.substr(0,5)=="font:")
			{ fontface=p.substr(5); }
		else if (p.substr(0,5)=="size:")
			{ fontsize=p.substr(5); }
		else if (p.substr(0,4)=="edit") {
			panelcount++;
			defOpen=defOpen || (!params[0] && panelcount==1); // if only one panel to show, default to open
			var toolname=this.editorLabel;
			if (p.indexOf('|')!=-1) toolname=p.substr(0,p.indexOf('|'));
			selectors+=this.html.editorchk.replace(/%toolname%/mg,toolname);
			selectors=selectors.replace(/%showpanel%/mg,defOpen?"CHECKED":"");
			panels+=this.html.editorpanel;
			// editor panel setup...
			panels=panels.replace(/%showpanel%/mg,defOpen?"block":"none");
			panels=panels.replace(/%maxrows%/mg,config.options.txtMaxEditRows);
			panels=panels.replace(/%disabled%/mg,readOnly?"DISABLED":"");
			panels=panels.replace(/%readonlychk%/mg,readOnly?"CHECKED":"");
			panels=panels.replace(/%minoredits%/mg,config.options.chkForceMinorUpdate&&!readOnly?"":"DISABLED");
			panels=panels.replace(/%minorchk%/mg,config.options.chkForceMinorUpdate?"CHECKED":"");
			panels=panels.replace(/%fontsize%/mg,fontsize);
			panels=panels.replace(/%fontface%/mg,fontface);
			var tiddlers=store.getTiddlers("title"); var tiddlerlist=""; 
			for (var t=0; t<tiddlers.length; t++)
				tiddlerlist+='<option value="'+tiddlers[t].title+'">'+tiddlers[t].title+'</option>';
			for (var t in config.shadowTiddlers)
				if (!store.tiddlerExists(t)) tiddlerlist+="<option value='"+t+"'>"+t+" (shadow)</option>";
			panels=panels.replace(/%tiddlerlist%/mg,tiddlerlist);
			var tags = store.getTags(); var taglist="";
			for (var t=0; t<tags.length; t++)
				taglist+="<option value='"+tags[t][0]+"'>"+tags[t][0]+"</option>";
			panels=panels.replace(/%taglist%/mg,taglist);
			if (p.substr(0,5)=="edit:") { 
				title=p.substr(5); 
				if (here && title=="here") title=here.id.substr(7);
			}
		}
		else if (p=="system") {
			panelcount++;
			defOpen=defOpen || (!params[0] && panelcount==1); // if only one panel to show, default to open
			var toolname=this.systemLabel;
			showsys=defOpen;
			if (p.indexOf('|')!=-1) toolname=p.substr(0,p.indexOf('|'));
			selectors+=this.html.systemchk.replace(/%toolname%/mg,toolname);
			selectors=selectors.replace(/%showpanel%/mg,defOpen?"CHECKED":"");
			panels+=this.html.systempanel;
			panels=panels.replace(/%showpanel%/mg,defOpen?"block":"none");
			panels=panels.replace(/%fontsize%/mg,fontsize);
			panels=panels.replace(/%fontface%/mg,fontface);
		}
		else {
			panelcount++;
			defOpen=defOpen || (!params[0] && panelcount==1); // if only one panel to show, default to open
			var toolid=toolname=p;
			if (p.indexOf('|')!=-1)
				{ toolname=p.substr(0,p.indexOf('|')); toolid=p.substr(p.indexOf('|')+1); }
			selectors+=this.html.toolschk.replace(/%toolid%/mg,toolid).replace(/%toolname%/mg,toolname);
			selectors=selectors.replace(/%showpanel%/mg,defOpen?"CHECKED":"");
			panels+=this.html.toolspanel.replace(/%toolid%/mg,toolid);
			panels=panels.replace(/%showpanel%/mg,defOpen?"block":"none");
			if (defOpen) openpanels.push(toolid);
		}
		p=params.shift(); // next param
	}
	var html=this.html.framework;
	if (panelcount<2)
		html=html.replace(/%version%/mg,'').replace(/%selector%/mg,''); // omit header/selectors if just one panel to display
	else {
		html=html.replace(/%version%/mg,
			this.versionMsg.format([version.extensions.tidIDE.major,version.extensions.tidIDE.minor,version.extensions.tidIDE.revision]));
		html=html.replace(/%selector%/mg,selectors+"<hr style='margin:0;padding:0'>");
	}
	html=html.replace(/%panels%/mg,panels);
	html=html.replace(/%id%/mg,id);
	var newIDE=createTiddlyElement(place,"span");
	newIDE.innerHTML=html;
	if (title.length) this.set(id,title);  // pre-load tiddler editor (if needed)
	if (showsys) config.macros.tidIDE.getsys(id); // pre-load system information (if needed)
	if (openpanels.length) for (i=0;i<openpanels.length;i++) { config.macros.tidIDE.loadPanel(id,openpanels[i]); }
	// see [[TextAreaPlugin]] for extended ctrl-F/G (search/search again)and TAB handler definitions
	var elems=newIDE.getElementsByTagName("textarea");
	for (var i=0;i<elems.length;i++) { 
		if (window.addKeyDownHandlers!=undefined) window.addKeyDownHandlers(elems[i]);
	}
}
//}}}

// // CUSTOM PANEL FUNCTIONS 
//{{{
config.macros.tidIDE.loadPanel=function(id,toolid) {
	var place=document.getElementById(id+"_"+toolid+"_panel"); if (!place) return;
	var t=store.getTiddler(toolid);
	place.innerHTML=""; 
	if (t) wikify(t.text,place); else place.innerHTML=this.toolsDef.format([id,toolid]);
}
//}}}

// // EDITOR PANEL FUNCTIONS
//{{{
config.macros.tidIDE.set=function(id,title) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var p=document.getElementById(id+"_preview");
	if (f.dirty && !confirm(config.commands.cancelTiddler.warning.format([f.current]))) return;
	// reset to form defaults
	f.dirty=false;
	f.current="";
	f.created.value=f.created.defaultValue;
	f.modified.value=f.modified.defaultValue;
	f.author.value=f.author.defaultValue;
	f.content.value=f.content.defaultValue;
	f.tags.value=f.tags.defaultValue;
	f.size.value=f.size.defaultValue;
	f.freeze.checked=false;
	f.domview.value="";
	f.htmlview.value="";
	f.status.value="";
	p.innerHTML="";
	if (!title.length) return;
	f.current=title;
	// values for new/shadow tiddlers
	var cdate=new Date();
	var mdate=new Date();
	var modifier=config.options.txtUserName;
	var text=config.views.editor.defaultText.format([title]);
	var tags="";
	// adjust values for shadow tiddlers
	if (store.isShadowTiddler(title))
		{ modifier=config.views.wikified.shadowModifier; text=store.getTiddlerText(title) }
	// get values for specified tiddler (if it exists)
	var t=store.getTiddler(title);
	if (t)	{ var cdate=t.created; var mdate=t.modified; var modifier=t.modifier; var text=t.text; var tags=t.getTags(); }
	if (!t && !store.isShadowTiddler(title)) f.tiddlers.options[f.tiddlers.options.length]=new Option(title,title,false,true); // add item to list
	f.tiddlers.value=title; // select current title (just in case it wasn't already selected)
	f.created.value=cdate.formatString(this.datetimefmt);
	f.modified.value=mdate.formatString(this.datetimefmt);
	f.author.value=modifier;
	f.content.value=text;
	f.tags.value=tags;
	f.minoredits.checked=config.options.chkForceMinorUpdate&&!readOnly;
	f.size.value=f.content.value.length+" bytes";
	if (f.preview.checked) { p.style.display="block"; this.render(id); }
}

config.macros.tidIDE.add=function(id) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var p=document.getElementById(id+"_preview");
	if (f.dirty && !confirm(config.commands.cancelTiddler.warning.format([f.current]))) return;
	var title=prompt(this.titleMsg,config.macros.newTiddler.title);
	while (title && store.tiddlerExists(title) && !confirm(config.messages.overwriteWarning.format([title])))
		title=prompt(this.titleMsg,config.macros.newTiddler.title);
	if (!title || !title.trim().length) return; // cancelled by user
	f.dirty=false; // suppress unneeded confirmation message
	this.set(id,title);
}

config.macros.tidIDE.remove=function(id) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var p=document.getElementById(id+"_preview");
	if (!f.current.length) return;
	if (!store.tiddlerExists(f.current) && store.isShadowTiddler(f.current)) { alert(this.isShadowMsg.format([f.current])); return; }
	if (config.options.chkConfirmDelete && !confirm(config.commands.deleteTiddler.warning.format([f.current]))) return;
	if (store.tiddlerExists(f.current)) {
		story.closeTiddler(f.current);
		store.removeTiddler(f.current);
		store.setDirty(true);
		if(config.options.chkAutoSave) saveChanges();
	}
	f.tiddlers.options[f.tiddlers.selectedIndex]=null; // remove item from list
	f.dirty=false; // suppress unneeded confirmation message
	this.set(id,""); // clear form controls
}

config.macros.tidIDE.save=function(id,saveAs) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var title=f.current;
	if (!title || !title.trim().length || saveAs) { // get a new title
		title=prompt(this.titleMsg,config.macros.newTiddler.title);
		while (title && store.tiddlerExists(title) && !confirm(config.messages.overwriteWarning.format([title])))
			title=prompt(this.titleMsg,config.macros.newTiddler.title);
		if (!title || !title.trim().length) return; // cancelled by user
		f.tiddlers.options[f.tiddlers.options.length]=new Option(title,title,false,true); // add item to list
		f.current=title;
	}
	var author=config.options.txtUserName;
	var mdate=new Date();
	var content=f.content.value;
	var tags=f.tags.value;
	var tiddler=store.saveTiddler(title,title,content,author,mdate,tags);
	if (f.minoredits.checked) {
		var author=f.author.value;
		var mdate=new Date(f.modified.value);
		var cdate=new Date(f.created.value);
		tiddler.assign(null,null,author,mdate,null,cdate);
	}
	store.setDirty(true);
	if(config.options.chkAutoSave) saveChanges();
	story.refreshTiddler(title,null,true);
	f.dirty=false;
}
//}}}

// // EDITOR PANEL: PREVIEW FUNCTIONS
//{{{
if (config.options.txtTidIDEAutoFreeze==undefined)
	config.options.txtTidIDEAutoFreeze=250; // limit (in milliseconds) for auto-freezing preview display

config.macros.tidIDE.render=function(id) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var p=document.getElementById(id+"_preview");
	var d=document.getElementById(id+"_domview");
	var h=document.getElementById(id+"_htmlview");
	p.innerHTML="";
	f.status.value=this.renderMsg;
	var start=new Date();
	wikify(f.content.value.replace(regexpCarriageReturn,''),p);
	var end=new Date();
	this.renderDOM(id);
	this.renderHTML(id);
	f.status.value=f.current+": "+(end-start+1)+"ms";
	// automatically suspend preview updates for slow rendering tiddlers
	if (end-start+1>config.options.txtTidIDEAutoFreeze) {
		f.freeze.checked=true;
		f.status.value+=this.timeoutMsg.format([config.options.txtTidIDEAutoFreeze]);
	}
	if (f.freeze.checked) f.status.value+=this.freezeMsg;
}

config.macros.tidIDE.renderDOM=function(id) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var p=document.getElementById(id+"_preview");
	var d=document.getElementById(id+"_domview");
	var h=document.getElementById(id+"_htmlview");
	p.style.height=(f.dom.checked||f.html.checked)?"10em":"25em";
	if (f.dom.checked) d.value=this.getNodeTree(p,"|  ");
	d.style.display=f.dom.checked?"inline":"none";
	d.style.width=f.html.checked?"49.5%":"100%";
	h.style.width=f.dom.checked?"49.5%":"100%";
}

config.macros.tidIDE.renderHTML=function(id) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var p=document.getElementById(id+"_preview");
	var d=document.getElementById(id+"_domview");
	var h=document.getElementById(id+"_htmlview");
	p.style.height=(f.dom.checked||f.html.checked)?"10em":"25em";
	if (f.html.checked) h.value=this.formatHTML(p.innerHTML);
	h.style.display=f.html.checked?"inline":"none";
	d.style.width=f.html.checked?"49.5%":"100%";
	h.style.width=f.dom.checked?"49.5%":"100%";
}

config.macros.tidIDE.formatHTML=function(txt) {
	if (config.browser.isIE) return txt; // BYPASS - 4/24/2006 due to IE hang problem.  Will fix later...
	var out="";
	var indent="";
	var level=0;
	for (var i=0;i<txt.length;i++) {
		var c=txt.substr(i,1);
		if (c=="<") {
			if (txt.substr(i+1,1)=="/")  indent=indent.substr(0,indent.length-2);
			out+="\n"+indent;
			if (txt.substr(i+1,1)!="/" && txt.substr(i+1,3)!="br>" && txt.substr(i+1,2)!="p>" && txt.substr(i+1,3)!="hr>")  indent+="  ";
		}
		out+=c;
		if (c=="\n")
			out+=indent;
		if (c==">" && txt.substr(i+1,1)!="<")
			out+="\n"+indent;
	}
	return out;
}

config.macros.tidIDE.getNodeTree=function(theNode,theIndent,showPath,inline,thePrefix,thePath)
{
	if (!theNode) return "";
	if (!thePrefix) thePrefix="";
	if (!thePath) thePath="";
	var mquote='"'+(inline?"{{{":"");
	var endmquote=(inline?"}}}":"")+'"';
	// generate output for this node
	var out = thePrefix;
	if (showPath && thePath.length)
		out += (inline?"//":"")+thePath.substr(1)+":"+(inline?"//":"")+"\r\n"+thePrefix;
	if (theNode.className=="DOMViewer")
		return out+'[DOMViewer]\r\n'; // avoid self-referential recursion
	out += (inline?"''":"")+theNode.nodeName.toUpperCase()+(inline?"''":"");
	if (theNode.nodeName=="#text")
		out += ' '+mquote+theNode.nodeValue.replace(/\n/g,'\\n')+endmquote;
	if (theNode.className)
		out += ' class='+mquote+theNode.className+endmquote;
	if (theNode.type)
		out += ' type='+mquote+theNode.type+endmquote;
	if (theNode.id)
		out += ' id='+mquote+theNode.id+endmquote;
	if (theNode.name)
		out += " "+theNode.name+(theNode.value?"="+mquote+theNode.value+endmquote:"");
	if (theNode.href)
		out += ' href='+mquote+theNode.href+endmquote;
	if (theNode.src)
		out += ' src='+mquote+theNode.src+endmquote;
	if (theNode.attributes && theNode.getAttribute("tiddlyLink")!=undefined)
		out += ' tiddler='+mquote+theNode.getAttribute("tiddlyLink")+endmquote;
	out += "\r\n";
	// recursively generate output for child nodes
	thePath=thePath+"."+theNode.nodeName.toLowerCase();
	thePrefix=theIndent+thePrefix;
	for (var i=0;i<theNode.childNodes.length;i++)
	{
		var thisChild=theNode.childNodes.item(i);
		var theNum=(inline?"~~":"(")+(i+1)+(inline?"~~":")");
		out += this.getNodeTree(thisChild,theIndent,showPath,inline,thePrefix,thePath+theNum);
	}
	return out;
}
//}}}

// // DOMViewer macro
//{{{
version.extensions.DOMViewer = version.extensions.tidIDE;
config.macros.DOMViewer = { };
config.macros.DOMViewer.handler = function(place,macroName,params) {
	// set default params
	var inline=false;
	var theRows=15;
	var theIndent="|  ";
	var showPath=false;
	var theTarget=place;
	// unpack options parameters
	if (params[0]=='inline') { inline=true; theIndent=">"; params.shift(); } 
	if (params[0]&&(params[0].substr(0,7)=="indent:")) { theIndent=params[0].substr(7); params.shift(); } 
	if (params[0]&&(params[0].substr(0,5)=="rows:")) { theRows=params[0].substr(5); params.shift(); } 
	if (params[0]=='path') { showPath=true; params.shift(); } 
	if (params[0]) {
		theTarget=document.getElementById(params[0]);
		if (!theTarget)
			if (store.getTiddler(params[0])!=undefined) {
				theTarget=document.getElementById("tiddler"+params[0]);
				if (!theTarget && confirm("DOMViewer asks:\n\nIs it OK to open tiddler '"+params[0]+"' now?")) { 
					story.displayTiddler(null,params[0],1,null,null,false);
					theTarget=document.getElementById("tiddler"+params[0]);
				}
			}
		params.shift();
	}
	// generate and display DOM tree
	if (inline) {
		var out=config.macros.tidIDE.getNodeTree(theTarget,theIndent,showPath,inline);
		wikify(out,place);
	}
	else {
		var out=config.macros.tidIDE.getNodeTree(theTarget,theIndent,showPath,inline);
		var css=".DOMViewer{width:100%;font-size:8pt;color:inherit;background:transparent;border:0px;}";
		setStylesheet(css,"DOMViewerPlugin");
		var theTextArea=createTiddlyElement(place,"textarea",null,"DOMViewer",out);
		theTextArea.rows=theRows;
		theTextArea.cols=60;
		theTextArea.wrap="off";
		theTextArea.theTarget=theTarget;
		theTextArea.theIndent=theIndent;
		theTextArea.showPath=showPath;
	}
}
//}}}

// // SYSTEM PANEL FUNCTIONS
//{{{
config.macros.tidIDE.showObject=function(o) { // generate formatted output for displaying object references
	var t="";
	for (var p in o) {
		if (typeof o[p]=="function") {
			t+="- - - - - - - - - - "+p+" - - - - - - - - - -\n";
			t+=o[p].toString();
			t+="\n- - - - - - - - - - END: "+p+" - - - - - - - - - -\n";
		}
		else
			t+='['+typeof o[p]+'] '+p+": "+o[p]+"\n";
	}
	return t;
}

config.macros.tidIDE.getsys=function(id) {
	var place=document.getElementById(id+"_systempanel"); if (!place) return;
	var f=document.getElementById(id+"_systemform");
	f.sysview.value="";
	// OPTIONS
	while (f.sys_opts.options.length > 1) { f.sys_opts.options[1]=null; } // clear list
	f.config_view.value="";  // clear edit field
	var cookies = { };
	if (document.cookie != "") {
		var p = document.cookie.split("; ");
		for (var i=0; i < p.length; i++) {
			var pos=p[i].indexOf("=");
			if (pos==-1)
				cookies[p[i]]="";
			else
				cookies[p[i].substr(0,pos)]=unescape(p[i].slice(pos+1));
		}
	}
	var c=1;
	var opt=new Array(); for (var i in config.options) opt.push(i); opt.sort();
	for(var i=0; i<opt.length; i++) {
		if ((opt[i].substr(0,3)=="txt")||(opt[i].substr(0,3)=="chk")) {
			var txt = (opt[i].substr(0,3)=="chk"?("["+(config.options[opt[i]]?"x":"_")+"] "):"")+opt[i]+(cookies[opt[i]]?" (cookie)":"");
			var val = config.options[opt[i]];
			f.sys_opts.options[c++]=new Option(txt,val,false,false);
		}
	}
	// STYLESHEETS
	while (f.sys_styles.options.length > 1) { f.sys_styles.options[1]=null; } // clear list
	var c=1;
	var styles=document.getElementsByTagName("style");
	for(var i=0; i < styles.length; i++) {
		var id=styles[i].getAttribute("id"); if (!id) id="(default)";
		var txt=id;
		var val="/* stylesheet:"+txt+" */\n"+styles[i].innerHTML;
		f.sys_styles.options[c++]=new Option(txt,val,false,false);
	}
	// SHADOWS
	while (f.sys_shadows.options.length > 1) { f.sys_shadows.options[1]=null; } // clear list
	var c=1;
	for(var s in config.shadowTiddlers) f.sys_shadows.options[c++]=new Option(s,config.shadowTiddlers[s],false,false);
	// NOTIFICATIONS
	while (f.sys_notify.options.length > 1) { f.sys_notify.options[1]=null; } // clear list
	var c=1;
	for (var i=0; i<store.namedNotifications.length; i++) {
		var n = store.namedNotifications[i];
		var fn = n.notify.toString();
		fn = fn.substring(fn.indexOf("function ")+9,fn.indexOf("{")-1);
		var txt=(n.name?n.name:"any change")+"="+fn;
		var val="/* notify: "+txt+" */\n"+n.notify.toString();
		f.sys_notify.options[c++]=new Option(txt,val,false,false);
	}
	// MACROS
	while (f.sys_macros.options.length > 1) { f.sys_macros.options[1]=null; } // clear list
	var c=1;
	var macros=new Array(); for (var m in config.macros) macros.push(m); macros.sort();
	for(var i=0; i < macros.length; i++)
		f.sys_macros.options[c++]=new Option(macros[i],this.showObject(config.macros[macros[i]]),false,false);
	// TOOLBAR COMMANDS
	while (f.sys_commands.options.length > 1) { f.sys_commands.options[1]=null; } // clear list
	var c=1;
	for(var cmd in config.commands)
		f.sys_commands.options[c++]=new Option(cmd,this.showObject(config.commands[cmd]),false,false);
	// FORMATTERS
	while (f.sys_formatters.options.length > 1) { f.sys_formatters.options[1]=null; } // clear list
	var c=1;
	for(var i=0; i < config.formatters.length; i++)
		f.sys_formatters.options[c++]=new Option(config.formatters[i].name,this.showObject(config.formatters[i]),false,false);
	// PARAMIFIERS
	while (f.sys_params.options.length > 1) { f.sys_params.options[1]=null; } // clear list
	var c=1;
	for(var param in config.paramifiers)
		f.sys_params.options[c++]=new Option(param,this.showObject(config.paramifiers[param]),false,false);
	// GLOBALS
	//global variables and functions (excluding most DOM and ~TiddyWiki core definitions)://
	var DOM0_globals = {
		addEventListener: 1, alert: 1, atob: 1, back: 1, blur: 1, btoa: 1, captureEvents: 1, clearInterval: 1,
		clearTimeout: 1, close: 1, closed: 1, Components: 1, confirm: 1, content: 1, controllers: 1, crypto: 1,
		defaultStatus: 1, defaultStatus: 1, directories: 1, disableExternalCapture: 1, dispatchEvent: 1, document: 1,
		dump: 1, enableExternalCapture: 1, escape: 1, find: 1, focus: 1, forward: 1, frameElement: 1, frames: 1,
		fullScreen: 1, getAttention: 1, getComputedStyle: 1, getSelection: 1, history: 1, home: 1, innerHeight: 1,
		innerWidth: 1, length: 1, location: 1, locationbar: 1, menubar: 1, moveBy: 1, moveTo: 1, name: 1,
		navigator: 1, open: 1, openDialog: 1, opener: 1, outerHeight: 1, outerWidth: 1, pageXOffset: 1,
		pageYOffset: 1, parent: 1, personalbar: 1, pkcs11: 1, print: 1, prompt: 1, prompter: 1, releaseEvents: 1,
		removeEventListener: 1, resizeBy: 1, resizeTo: 1, routeEvent: 1, screen: 1, screenX: 1, screenY: 1,
		scroll: 1, scrollbars: 1, scrollBy: 1, scrollByLines: 1, scrollByPages: 1, scrollMaxX: 1, scrollMaxY: 1,
		scrollTo: 1, scrollX: 1, scrollY: 1, self: 1, setInterval: 1, setResizable: 1, setTimeout: 1, sidebar: 1,
		sizeToContent: 1, status: 1, statusbar: 1, stop: 1, toolbar: 1, top: 1, unescape: 1, updateCommands: 1,
		window: 1, getInterface: 1
	};
	var tw_globals = {
		version: 1, config: 1, DEFAULT_VIEW_TEMPLATE: 1, DEFAULT_EDIT_TEMPLATE: 1, store: 1, story: 1,
		Formatter: 1, anim: 1, readOnly: 1, highlightHack: 1, main: 1, restart: 1, saveTest: 1,  loadSystemConfig: 1,
		processConfig: 1, invokeMacro: 1, Formatter: 1, wikify: 1, wikifyPlain: 1, highlightify: 1, Wikifier: 1, 
		Tiddler: 1, regexpBackSlashEn: 1, regexpBackSlash: 1, regexpBackSlashEss: 1, regexpNewLine: 1, 
		regexpCarriageReturn: 1, TiddlyWiki: 1, displayTiddlers: 1, displayTiddler: 1, Story: 1, displayMessage: 1,
		clearMessage: 1, refreshElements: 1, applyHtmlMacros: 1, refreshPageTemplate: 1, applyPageTemplate: 1,
		refreshDisplay: 1, refreshPageTitle: 1, refreshStyles: 1, loadOptionsCookie: 1, saveOptionCookie: 1,
		saveUsingSafari: 1, startSaveArea: 1, endSaveArea: 1, checkUnsavedChanges: 1, saveChanges: 1,
		getBackupPath: 1, generateRss: 1, allTiddlersAsHtml: 1,
		convertUTF8ToUnicode: 1, manualConvertUTF8ToUnicode: 1, mozConvertUTF8ToUnicode: 1,
		convertUnicodeToUTF8: 1, manualConvertUnicodeToUTF8: 1, mozConvertUnicodeToUTF8: 1,
		saveFile: 1, loadFile: 1, ieSaveFile: 1, ieLoadFile: 1, mozillaSaveFile: 1, mozillaLoadFile: 1,
		operaUrlToFilename: 1, operaSaveFile: 1, operaLoadFile: 1, safariFilenameToUrl: 1, safariLoadFile: 1,
		safariSaveFile: 1, detectPlugin: 1, createTiddlyButton: 1, createTiddlyLink: 1, refreshTiddlyLink: 1,
		createExternalLink: 1, onClickTiddlerLink: 1, createTagButton: 1, onClickTag: 1, onClickTagOpenAll: 1,
		createTiddlyError: 1, Animator: 1, Zoomer: 1, Cascade: 1, Scroller: 1, Slider: 1, Popup: 1,
		createTiddlerPopup: 1, scrollToTiddlerPopup: 1, hideTiddlerPopup: 1, RGB: 1, drawGradient: 1,
		createTiddlyText: 1, createTiddlyElement: 1, addEvent: 1, removeEvent: 1, addClass: 1,
		removeClass: 1, hasClass: 1, resolveTarget: 1, getPlainText: 1, ensureVisible: 1, 
		findWindowWidth: 1, findWindowHeight: 1, findScrollX: 1, findScrollY: 1, findPosX: 1, findPosY: 1,
		insertSpacer: 1, removeChildren: 1, setStylesheet: 1,
		Packages: 1, sun: 1, java: 1, netscape: 1, XPCNativeWrapper: 1, GeckoActiveXObject: 1
	};
	while (f.sys_globals.options.length > 1) { f.sys_globals.options[1]=null; } // clear list
	if (config.browser.isIE) return; // BYPASS - 8/16/2006 // DON'T LIST GLOBALS IN IE... throws object error - WFFL
	try {
		var c=1;
		for (var v in window) if (!(DOM0_globals[v] || tw_globals[v])) {
			var t=window[v];
			if ((typeof window[v])=='object') {
				var t='';
				for (var p in window[v]) {
					t+=((typeof window[v][p])!='function')?('['+typeof window[v][p]+'] '+p):p;
					t+=((typeof window[v][p])!='function')?('='+window[v][p]):'';
					t+='\n';
				}
			}
			f.sys_globals.options[c++]=new Option(((typeof window[v])!='function')?('['+typeof window[v]+'] '+v):v,t,false,false);
		}	
	}
	catch(e) { ; }
}

config.macros.tidIDE.setsys=function(id) {
	var place=document.getElementById(id+"_systempanel"); if (!place) return;
	var f=document.getElementById(id+"_systemform");
	if (f.sys_opts.selectedIndex==0) return; // heading - do nothing
	var name=f.sys_opts.options[f.sys_opts.selectedIndex].text.replace(/\[[Xx_]\] /,'').replace(/ \(cookie\)/,'')
	var value=f.config_view.value;
	config.options[name]=value;
	saveOptionCookie(name);
	f.sys_opts.options[f.sys_opts.selectedIndex].value=value;
	return;
}
//}}}

// // HTML DEFINITIONS
//{{{
config.macros.tidIDE.html = { };
config.macros.tidIDE.html.framework = " \
	<html> %version% <form style='display:inline;margin:0;padding:0;'>%selector%</form> %panels% </html> \
";
//}}}
//{{{
config.macros.tidIDE.html.editorchk = " \
	<input type=checkbox name=editor \
		style='display:inline;width:auto;margin:1px;' \
		title='add/delete/modify tiddlers' %showpanel% \
		onclick='document.getElementById(\"%id%_editorpanel\").style.display=this.checked?\"block\":\"none\"; \
			if (this.checked) config.macros.tidIDE.render(\"%id%\");'>%toolname% \
";
config.macros.tidIDE.html.systemchk = " \
	<input type=checkbox name=system \
		style='display:inline;width:auto;margin:1px;' \
		title='view TiddlyWiki system internals and configurable options' %showpanel% \
		onclick='document.getElementById(\"%id%_systempanel\").style.display=this.checked?\"block\":\"none\"; \
			if (this.checked) config.macros.tidIDE.getsys(\"%id%\");'>%toolname% \
";
config.macros.tidIDE.html.toolschk = " \
	<input type=checkbox name=tools \
		style='display:inline;width:auto;margin:1px;' \
		title='' %showpanel% \
		onclick='document.getElementById(\"%id%_%toolid%_panel\").style.display=this.checked?\"block\":\"none\"; \
			if (this.checked) config.macros.tidIDE.loadPanel(\"%id%\",\"%toolid%\");'>%toolname% \
";
//}}}
//{{{
config.macros.tidIDE.html.toolspanel = " \
	<div id='%id%_%toolid%_panel' style='display:%showpanel%;margin:0;margin-top:0.5em'> \
	</div> \
";
//}}}
//{{{
config.macros.tidIDE.html.systempanel = " \
	<div id='%id%_systempanel' style='display:%showpanel%;margin:0;margin-top:0.5em;white-space:nowrap'> \
		<form id='%id%_systemform' style='display:inline;margin:0;padding:0;'> \
		<!-- configurable options --> \
		<table style='width:100%;border:0;padding:0;margin:0'><tr style='border:0;padding:0;margin:0'> \
		<td style='width:30%;border:0;padding:0;margin:0'> \
			<select size=1 name='sys_opts' style='width:100%;font-size:%fontsize%;' \
				onchange='this.form.config_view.value=this.value'> \
				<option value=\"\">config.options.*</option> \
			</select> \
		</td><td style='width:50%;border:0;padding:0;margin:0;'> \
			<input type=text name='config_view' size=60 style='width:99%;font-size:%fontsize%;' value=''> \
		</td><td style='width:20%;white-space:nowrap;border:0;padding:0;margin:0;'> \
			<input type=button style='width:50%;' value='set option' title='save this TiddlyWiki option value' \
				onclick='config.macros.tidIDE.setsys(\"%id%\");config.macros.tidIDE.getsys(\"%id%\");'><!-- \
			--><input type=button style='width:50%;' value='refresh' title='retrieve current options and system values' \
				onclick='this.form.sysview.style.display=\"none\"; config.macros.tidIDE.getsys(\"%id%\");'> \
		</td></tr><tr style='border:0;padding:0;margin:0'><td colspan=3 \
				style='white-space:nowrap;width:100%;border:0;padding:0;margin:0'> \
			<!-- system objects --> \
			<select size=1  name='sys_styles' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">stylesheets...</option> \
			</select><select size=1  name='sys_shadows' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">shadows...</option> \
			</select><select size=1  name='sys_notify' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">notifications...</option> \
			</select><select size=1  name='sys_globals' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">globals...</option> \
			</select><br><select size=1  name='sys_macros' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">macros...</option> \
			</select><select size=1  name='sys_commands' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">toolbars...</option> \
			</select><select size=1  name='sys_formatters' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">wikifiers...</option> \
			</select><select size=1  name='sys_params' style='width:25%;font-size:%fontsize%;' \
				onchange='this.form.sysview.style.display=\"block\"; this.form.%id%_sysview.value=this.value'> \
				<option value=\"\">paramifiers...</option> \
			</select> \
			<!-- system value display area --> \
			<span style='white-space:normal;'><textarea id='%id%_sysview' name=sysview cols=60 rows=12 \
				onfocus='this.select()' style='width:99.5%;height:16em;font-size:%fontsize%;font-family:%fontface%;display:none'></textarea></span> \
		</td></tr></table> \
		</form> \
	</div> \
";
//}}}
//{{{
config.macros.tidIDE.html.editorpanel = " \
	<div id='%id%_editorpanel' style='display:%showpanel%;margin:0;margin-top:0.5em'> \
	<form id='%id%_editorform' style='display:inline;margin:0;padding:0;'> \
	<!-- tiddler editor list and buttons --> \
	<select size=1 name=tiddlers style='display:inline;width:40%;font-size:%fontsize%;'  \
		onchange='config.macros.tidIDE.set(\"%id%\",this.value); this.value=this.form.current;'> \
	<option value=''>select a tiddler...</option> \
	%tiddlerlist% \
	</select><!-- \
	--><input name=add type=button style='display:inline;width:10%' \
		value='new' title='create a new tiddler' \
		onclick='config.macros.tidIDE.add(\"%id%\")' %disabled%><!-- \
	--><input name=remove type=button style='display:inline;width:10%' \
		value='remove' title='delete this tiddler' \
		onclick='config.macros.tidIDE.remove(\"%id%\")' %disabled%><!-- \
	--><input name=save type=button style='display:inline;width:10%' \
		value='save' title='save changes to this tiddler' \
		onclick='config.macros.tidIDE.save(\"%id%\")' %disabled%><!-- \
	--><input name=saveas type=button style='display:inline;width:10%' \
		value='save as' title='save changes to a new tiddler' \
		onclick='config.macros.tidIDE.save(\"%id%\",true)' %disabled%><!-- \
	--><input name=view type=button style='display:inline;width:10%' \
		value='open' title='open this tiddler for regular viewing' \
		onclick='if (!this.form.current.length) return;	story.displayTiddler(null,this.form.current)'><!-- \
	--><!-- COMMENTED OUT <input name=run type=button style='display:inline;width:9%' \
		value='run' title='evaluate this tiddler as a javascript \"systemConfig\" plugin' \
		onclick='if (!confirm(config.macros.tidIDE.evalMsg.format([this.form.current]))) return false; \
			var err=processConfig(this.form.content.value); \
			if(err)displayMessage(config.messages.customConfigError.format([err,this.form.current]));'> END COMMENT --><!-- \
	--><input name=previewbutton type=button style='display:inline;width:10%;' \
		value='preview' title='show \"live\" preview display' \
		onclick='document.getElementById(\"%id%_previewpanel\").style.display=\"block\"; \
			this.form.preview.checked=true; config.macros.tidIDE.render(\"%id%\")'><!-- \
	hidden field for preview show/hide state: \
	--><input name=preview type=checkbox style='display:none;'>\
	<!-- tiddler content edit --> \
	<div><textarea id='%id%_content' name='content' edit='text' cols=60 rows=%maxrows% \
		style='width:100%;font-size:%fontsize%;font-family:%fontface%;' \
		onkeyup='var f=this.form; f.dirty=true; f.size.value=this.value.length+\" bytes\";  \
			var p=document.getElementById(\"%id%_preview\"); \
			if (f.preview.checked && !f.freeze.checked) { config.macros.tidIDE.render(\"%id%\"); }'></textarea></div> \
	<!-- tag edit and droplist --> \
	<table width='100%' style='border:0;padding:0;margin:0'><tr style='border:0;padding:0;margin:0'> \
	<td style='border:0;padding:0;margin:0'> \
		<input type=text name=tags size=60 style='width:100%;font-size:%fontsize%;' value='' \
			onchange='this.form.dirty=true' %disabled%> \
	</td><td width='1' style='border:0;padding:0;margin:0;'> \
		<select size=1 name=taglist style='font-size:%fontsize%;' \
			onchange='this.form.dirty=true; this.form.tags.value+=\" \"+this.value' %disabled%> \
		<option value=''>select tags...</option> \
		%taglist% \
		</select> \
	</td></tr></table> \
	<!--  created/modified dates, author, current tiddler size --> \
	<div style='float:right;'> \
		created <input type=text name=created size=15 \
			style='display:inline;font-size:%fontsize%;text-align:center;padding:0;' value='' \
			onchange='this.form.dirty=true' %minoredits%> \
		modified <input type=text name=modified size=15 \
			style='display:inline;font-size:%fontsize%;text-align:center;padding:0;' value='' \
			onchange='this.form.dirty=true;' %minoredits%> \
		by <input type=text name=author size=15 \
			style='display:inline;font-size:%fontsize%;padding:0;' value='' \
			onfocus='this.select()' onchange='this.form.dirty=true' %minoredits%> \
		<input type=text name=size size=10 \
			style='display:inline;font-size:%fontsize%;text-align:center;padding:0;' value='' \
			onfocus='this.blur()' onkeydown='return false' DISABLED>  \
	</div> \
	<!-- toggles: read-only, minor edit --> \
	<span style='white-space:nowrap'> \
	<input type=checkbox name=readonly \
		style='display:inline;width:auto;margin:1px;' %readonlychk% \
		title='do not allow tiddler changes to be saved' \
		onclick='readOnly=config.options.chkHttpReadOnly=this.checked;saveOptionCookie(\"chkHttpReadOnly\"); \
			var f=this.form; f.minoredits.disabled=f.tags.disabled=f.taglist.disabled=this.checked; \
			f.add.disabled=f.remove.disabled=f.save.disabled=f.saveas.disabled=this.checked; \
			f.created.disabled=f.modified.disabled=f.author.disabled=this.checked||!f.minoredits.checked;'>readonly \
	<input type=checkbox name=minoredits \
		style='display:inline;width:auto;margin:1px;' %disabled% %minorchk% \
		title='check: save datestamps/author as entered, uncheck: auto-update modified/author' \
		onclick='this.form.created.disabled=this.form.modified.disabled=this.form.author.disabled=!this.checked; \
			config.options.chkForceMinorUpdate=this.checked;saveOptionCookie(\"chkForceMinorUpdate\");'>minor edits \
	</span> \
	<!-- tiddler preview display --> \
	<div id='%id%_previewpanel' style='display:none;white-space:nowrap'> \
	<div id='%id%_preview' class='viewer' style='margin:0;margin-top:.5em;height:25em;overflow:auto;white-space:normal'> \
		&nbsp; \
	</div> \
	<!-- DOM and HTML viewers --> \
	<textarea id='%id%_domview' name=domview cols=60 rows=12 wrap=off \
		onfocus='this.select()' style='display:none;width:100%;height:16em;font-size:%fontsize%;'></textarea><!-- \
	--><textarea id='%id%_htmlview' name=htmlview cols=60 rows=12 wrap=off \
		onfocus='this.select()' style='display:none;width:100%;height:16em;font-size:%fontsize%;'></textarea> \
	<!-- status line, preview option checkboxes, run/refresh buttons --> \
	<table width='100%' style='border:0;padding:0;margin:0'><tr style='border:0;padding:0;margin:0'> \
	<td style='border:0;padding:0;margin:0'> \
		<input type=text '%id%_status' name=status style='padding:0;width:100%;font-size:%fontsize%;'> \
	</td><td style='width:1%;border:0;padding:0;margin:0;text-align:right;white-space:nowrap'> \
		<input type=checkbox name=dom style='display:inline;width:auto;margin:1px;' \
			title='show Document Object Model (DOM) information' \
			onclick='config.macros.tidIDE.renderDOM(\"%id%\");'>DOM \
		<input type=checkbox name=html style='display:inline;width:auto;margin:1px;' \
			title='show rendered HTML' \
			onclick='config.macros.tidIDE.renderHTML(\"%id%\");'>HTML \
		<input type=checkbox name=freeze style='display:inline;width:auto;margin:1px;' \
			title='do not update preview display as changes are made' \
			onclick='var p=document.getElementById(\"%id%_preview\");  \
				if (this.checked) this.form.status.value+=config.macros.tidIDE.freezeMsg; \
				else config.macros.tidIDE.render(\"%id%\");'>freeze \
		<!-- COMMENTED OUT <input type=button style='display:inline;width:auto;' value='run' \
			title='evaluate this tiddler as a javascript \"systemConfig\" plugin' \
			onclick='if (!confirm(config.macros.tidIDE.evalMsg.format([this.form.current]))) return false; \
				var err=processConfig(this.form.content.value); \
				if(err)displayMessage(config.messages.customConfigError.format([err,this.form.current]));'> END COMMENT --><!-- \
		--><input type=button style='display:inline;width:auto;' value='refresh' \
			title='update preview display' \
			onclick='config.macros.tidIDE.render(\"%id%\")'><!-- \
		--><input type=button style='display:inline;width:auto;' value='hide' \
			title='hide preview display' \
			onclick='document.getElementById(\"%id%_previewpanel\").style.display=\"none\"; \
				this.form.preview.checked=false; config.macros.tidIDE.render(\"%id%\")'> \
	</td></tr></table> \
	</div> \
	</form> \
	</div> \
";
//}}}
/***
|''Name''|TiddlerPopupMacro|
|''Version''|0.1|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#TiddlerPopupMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|Shows the contents of the specified tiddler in a popup.|
!Notes
This is a sample macro, created only for educational purposes.
!Usage
{{{
<<tiddlerPopup [tiddler name]>>
}}}
!!Example
<<tiddlerPopup [[ColorPalette]]>>
!Revision History
!!v0.1 (2007-11-19)
* initial release
!To Do
* parameters for {{{buttonClass}}}, {{{popupClass}}}, {{{id}}}, {{{accessKey}}}
* customizable order (title, tags, contents)
!Code
***/
//{{{
config.macros.tiddlerPopup = {
	label: "label",
	tooltip: "tooltip",
	buttonClass: null,
	id: null,
	accessKey: null
};

config.macros.tiddlerPopup.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var title = params[0] || tiddler.title;
	this.label = title;
	this.tooltip = "show " + title;
	createTiddlyButton(place, this.label, this.tooltip,
		function(e) { config.macros.tiddlerPopup.show(e, this, title) },
		this.buttonClass, this.id, this.accessKey);
};

config.macros.tiddlerPopup.show = function(ev, el, title) {
	// prevent event bubbling
	ev.cancelBubble = true;
	if(ev.stopPropagation) ev.stopPropagation();
	// show tiddler contents
	var tiddler = store.getTiddler(title);
	var popup = Popup.create(el, "div");
	if(tiddler) {
		var contents = "tags: " + tiddler.tags.join(" ") + "\n----\n"
			+ "[[" + tiddler.title + "]]\n----\n"
			+ tiddler.text;
	} else {
		if(store.getTiddlerText(title)) { // shadow tiddler
			var contents = "[[" + title + "]]\n----\n" + store.getTiddlerText(title);
		} else {
			var contents = "Error: Tiddler [[" + title + "]] not found.";
		}
	}
	wikify(contents, popup);
	Popup.show();
}
//}}}
/***
|''Name''|TiddlerPreviewPlugin|
|''Description''|provides a toolbar command for previewing tiddlers in edit mode|
|''Author''|FND|
|''Contributors''|Saq Imtiaz|
|''Version''|0.2.5|
|''Status''|@@beta@@|
|''Source''|http://svn.tiddlywiki.org/contributors/FND/plugins/TiddlerPreviewPlugin.js|
|''CodeRepository''|http://svn.tiddlywiki.org/contributors/FND/|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''CoreVersion''|2.2|
!Usage
Previews are accessed via the {{{previewTiddler}}} command, which must be added to the [[tiddler toolbar|http://www.tiddlywiki.org/wiki/Tiddler_Toolbar]].
!Configuration Options
<<option chkPopupPreview>> use popup for preview
!Revision History
!!v0.2 (2008-12-06)
* initial release
!To Do
* styling inconsistencies in preview (e.g. tag buttons)
* disable in view mode
* smooth scrolling
!Code
***/
//{{{
if(!version.extensions.TiddlerPreviewPlugin) { //# ensure that the plugin is only installed once
version.extensions.TiddlerPreviewPlugin = { installed: true };

config.optionsDesc.chkPopupPreview = "use popup for preview";

config.commands.previewTiddler = {
	text: "preview",
	tooltip: "preview tiddler contents",
	className: "preview",

	handler: function(ev, src, title) {
		var tiddlerElem = story.findContainingTiddler(src);
		if(config.options.chkPopupPreview) {
			this.generatePopup(title, tiddlerElem, src, ev);
		} else {
			this.generatePane(title, tiddlerElem);
		}
		return false;
	},

	generatePane: function(title, tiddlerElem) {
		var containers = tiddlerElem.getElementsByTagName("div");
		var pane = containers[containers.length - 1];
		if(pane && hasClass(pane, this.className)) {
			removeChildren(pane);
		} else {
			pane = createTiddlyElement(tiddlerElem, "div", null,
				this.className + " viewer");
		}
		this.displayPreview(pane, tiddlerElem, title);
		pane.ondblclick = function(ev) {
			window.scrollTo(0, ensureVisible(this.parentNode));
			stopEvent(ev);
			return false;
		};
		window.scrollTo(0, ensureVisible(pane));
	},

	generatePopup: function(title, tiddlerElem, src, ev) {
		var popup = Popup.create(src, "div",
			this.className + " popupTiddler viewer");
		this.displayPreview(popup, tiddlerElem, title);
		Popup.show();
		stopEvent(ev);
		return false;
	},

	displayPreview: function(container, tiddlerElem, title) {
		var tiddler = merge(new Tiddler(title), store.getTiddler(title));
		var newTitle = title;
		if(tiddlerElem) {
			var fields = {};
			story.gatherSaveFields(tiddlerElem, fields);
			tiddler.fields = store.tiddlerExists(newTitle) ?
				store.fetchTiddler(newTitle).fields :
				(newTitle != title && store.tiddlerExists(title) ?
					store.fetchTiddler(title).fields :
					merge({}, config.defaultCustomFields));
			for(var p in fields) {
				if(TiddlyWiki.isStandardField(p)) {
					if(p == "tags") {
						tiddler[p] = fields[p].readBracketedList();
					} else {
						tiddler[p] = fields[p];
					}
				} else {
					tiddler.fields[p] = fields[p];
				}
			}
			var template = story.chooseTemplateForTiddler(title, DEFAULT_VIEW_TEMPLATE);
			container.innerHTML = story.getTemplateForTiddler(title, template, tiddler);
			applyHtmlMacros(container, tiddler);
			forceReflow();
		}
	}
};

config.shadowTiddlers.StyleSheetPreview = ("/*{{{*/\n" +
	".%0 {\n" +
	"\tpadding: 5px;\n" +
	"\tbackground-color: #eee;\n" +
	"}\n\n" +
	".%0 .toolbar {\n" +
	"\tdisplay: none;\n" +
	"}\n" +
	"/*}}}*/").format([config.commands.previewTiddler.className]);
store.addNotification("StyleSheetPreview", refreshStyles);

} //# end of "install only once"
//}}}
/***
|Name|TiddlerToCPlugin|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#TiddlerToCPlugin]]|
|Version|0.7|
|Author|FND|
|Contributors|[[Saq|http://tw.lewcid.org]]|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|create a table of contents from a tiddler's headings|
!Notes
Doug Compton has written a similar, though much more advanced plugin for this purpose, called [[DcTableOfContentsPlugin|http://devpad.tiddlyspot.com/#DcTableOfContentsPlugin]].
!Usage
Add {{{<<ToC>>}}} to the desired tiddler(s). Alternatively, a parameter can be used to display the table of contents for another tiddler: {{{<<ToC "tiddlerName">>}}}.
The styling can be modified in the [[StyleSheetTableOfContents]] shadow tiddler.
<<ToC>>
!Changelog
!!v0.5a (2007-05-20)
* initial release
!!v0.5b (2007-05-20)
* renamed to TiddlerToCPlugin (to prevent confusion with the existing [[TableOfContentsPlugin|http://tiddlytools.com/#TableOfContentsPlugin]])
!!v0.6 (2007-05-21)
* several bugfixes and significant improvements regarding the macro code (thanks Saq)
!!v0.7 (2007-08-29)
* fixed error for tiddlers not containing any headings
!Issues / To Do
* add links to sections (problematic, as there are no anchors, yet?)
* introduce thresholds (minimum amount of headings to show a ToC, maximum depth)
!Code
***/
//{{{
/*
** Styles (can be customized in the StyleSheetTableOfContents shadow tiddler)
*/

config.shadowTiddlers.StyleSheetTableOfContents = "/*{{{*/\n"
	+ ".ToC {\n\tfloat: left; /* auto-width */\n\tmargin: 0 2em 2em 0;\n\tborder: 1px solid #aaa;\n\tpadding: 5px;\n\tbackground-color: #eee;\n}\n\n"
	+ ".ToC ol {\n\tmargin: 0 1em;\n}\n\n"
	+ "h1 {\n\tclear: left;\n}\n"
	+ "/*}}}*/";
store.addNotification("StyleSheetTableOfContents", refreshStyles);

/*
** Macro Code
*/

config.macros.ToC = { label: "Add Table of Contents", prompt: "Add Table of Contents" }; // DEBUG: obsolete?
config.macros.ToC.handler =
	function(place, macroName, params, wikifier, paramString, tiddler) {
		// process parameters
		if (params[0]) { // tiddler name
			tiddler = store.getTiddler(params[0]);
		}
		// create table of contents
		generateToC(place, tiddler);
		return false; // DEBUG: ?
}

/*
** Main Code
*/

generateToC = function(place, tiddler) {
	// retrieve headings
	var RegEx = /^!+(.*)$/gim;
	var tiddlerContents = tiddler.text.match(RegEx);
	// create ToC
	if(tiddlerContents) {
		var ToC = "";
		for(var i = 0; i < tiddlerContents.length; i++) {
			ToC += tiddlerContents[i] + "\n";
		}
		// replace headings markup with list markup
		for(var i = 0; i < 6; i++) { // DEBUG: inefficient!? (use a single RegEx instead? problem: JavaScript RegEx limitations)
			ToC = ToC.replace(/^(#*)!/gim, "$1#");
		}
		// add ToC wrapper container
		ToC = "{{ToC{\n''Table of Contents''\n" + ToC + "}}}\n";
		// add ToC to tiddler
		wikify(ToC, place);
	}
	return false;
}
//}}}
This is the sandbox for testing the TiddlerToCPlugin.
The styling can be changed in the StyleSheetTableOfContents shadow tiddler.

Table of contents for the current tiddler:
<<ToC>>
@@display(block):clear(both):@@
Table of contents for the StyleSheet tiddler:
<<ToC "StyleSheet">>
@@display(block):clear(both):@@
!Heading 1
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
!!Heading 1-1
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
!!Heading 1-2
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
!Heading 2
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
!!Heading 2-1
Excepteur sint occaecat cupidatat non proident.
!!Heading 2-2
Sunt in culpa qui officia deserunt mollit anim id est laborum.
/***
|''Name''|TiddlerWriteMacro|
|''Version''|0.1|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#TiddlerPopupMacro]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
|''Type''|macro|
|''Requires''|N/A|
|''Overrides''|N/A|
|''Description''|Shows the contents of the specified tiddler.|
!Notes
This is a sample macro, created only for educational purposes.
!Usage
{{{
<<tiddlerWrite tiddlerName>>
}}}
!!Example
<<tiddlerWrite [[ColorPalette]]>>
!Revision History
!!v0.1 (2007-11-19)
* initial release
!Code
***/
//{{{
config.macros.tiddlerWrite = {};
config.macros.tiddlerWrite.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var title = params[0];
	if(title == tiddler.title) {
		title = "Error: Can't use the same tiddler from which the macro is called (infinite recursion)!";
	}
	var tiddler = store.getTiddler(title);
	if(tiddler) {
		var contents = "tags: " + tiddler.tags.join(" ") + "\n----\n"
			+ "[[" + tiddler.title + "]]\n----\n"
			+ tiddler.text;
	} else {
		if(store.getTiddlerText(title)) { // shadow tiddler
			var contents = "[[" + title + "]]\n----\n" + store.getTiddlerText(title);
		} else {
			var contents = "Error: Tiddler [[" + title + "]] not found.";
		}
	}
	wikify("<<<\n" + contents + "\n<<<", place);
}
//}}}
/***
!Metadata:
|''Name:''|TiddlyCalendar|
|''Description:''|Tiddlers Calendar and Date picker|
|''Version:''|1.1.0|
|''Date:''|Oct 22, 2009|
|''Source:''|http://sourceforge.net/project/showfiles.php?group_id=150646|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License]]|
|''~CoreVersion:''|2.2.3|
|''Browser:''|Firefox 1.5+; InternetExplorer 6.0|
|''Optional''|DatePlugin|
!Usage:
{{{<<tCalendar [year [month [count]]]>>}}}
{{{<<tCalendar [last [n] | next [n] {year(s) | month(s)}]>>}}}
eg,
{{{<<tCalendar>>}}},
{{{<<tCalendar 2007 10 3>>}}},
{{{<<tCalendar thisyear>>}}},
{{{<<tCalendar last year>>}}},
{{{<<tCalendar next 4 months>>}}}
{{{<<tCalendar lastModified>>}}}
!Revision History:
|''Version''|''Date''|''Note''|
|1.1.0|Oct 22, 2009|Speed up rendering the calendar, by using 'DocumentFrament' object.|
|1.0.1|Dec 20, 2007|Add parameter 'lastModified' control for showing the month calendar including the last modified tiddler|
|1.0.0|Nov 21, 2007|Initial release|
!Code section:
***/
//{{{
version.extensions.tCalendar = {major: 1, minor: 1, revision: 0, date: new Date("Oct 22, 2009")};

//# Calendar object
function Calendar()
{
	this.styles = Calendar.styles;

	this.callback = {
		fn: null,
		fnEnable: false,
		option: null,
		params: {date:null, title:null, celldate:null, cellClass:null, dateFmt:null}
	};
	return this;
};

Calendar.locale = 'en';
Calendar[Calendar.locale] = {
	dates: {
		days: ["Su", "M", "Tu", "W", "Th", "F", "Sa"],
		yearFmt: "YYYY",
		monthFmt: "mmm YYYY",
		dateFmt: "MMM DD, YYYY",
		longHolidayFmt: "0DD/0MM/YYYY",
		shortHolidayFmt: "0DD/0MM",
		startOfWeek: 0, /* 0,1*/
		weekends: [true, false, false, false, false, false, true], /* Default: 0 (Sun) and 6 (Sa) are true*/
		holidays: [] /* using short (or long) holidayFmt*/
	}
};

Calendar.styles = '/*{{{*/'
		+ '\ntable.calendarWrapper {border-collapse:collapse; border:2px solid #c6dbff;}'
		+ '\n.calendarWrapper td {border-collapse:collapse; border:1px solid #c6dbff; text-align:center;margin:0; padding:0 0.05em;}'
/*		+ '\ntable.calendar {border-collapse:separate; border:1px solid #c6dbff;}'*/
		+ '\ntable.calendar {border-collapse:collapse; border:0;}'
		+ '\n.calendar tbody, .calendar th, .calendar td, .calendar tr {border:0; text-align:center; font-size:1em; padding:0 0.1em;}'
		+ '\n.calendar th {color:#000; background-color:#c6dbff;}'
		+ '\n#sidebarOptions .calendar td {font-size:0.96em; margin:0; padding:0;}'
		+ '\n#sidebarTabs .calendar td, #mainMenu .calendar td  {padding:0 0.25em;}'
		+ '.calendar .naviBar select {border:0;}'
		+ '\n.calendar .today a {padding:0; border:1px solid blue;}'
		+ '\n.calendar .weekend {background-color:#deeeff;}'
		+ '\n.calendar .hasChanged {font-family:bold; background-color:#fe8; color:darkblue;}'
		+ '\n.calendar .holiday {font-weight:bold; font-size:1.06em; color:red;}'
		+ '\n.datePopup {background:#efffff;}'
		+ '\n.datePopup .isCreated {color:#df6300;}'
		+ '\n.datePopup .isExcluded {filter:alpha(opacity=60); -moz-opacity:0.6; opacity:0.6;}'
/*		+ '.viewer .calendarOptios {display:block;}'*/
		+ '\n/*}}}*/';

Calendar.prototype.getLocale = function()
{
	var locale = config.options.txtLocale ? config.options.txtLocale : Calendar.locale;
	return Calendar[locale] ? locale : 'en';
};

Calendar.prototype.show = function(place, year, month, count)
{
	this.locale=this.getLocale();
	var y, m = new Date().getMonth()+1, c = 1;
	c = isNaN(count) ? (isNaN(year) && isNaN(month) ? c : (!isNaN(year) && isNaN(month) ? 12 : c)) : parseInt(count);
	m = isNaN(month) ? (isNaN(year) ? m : (isNaN(month) ? 1 : parseInt(month))) : parseInt(month);
	y = isNaN(year) ? new Date().getFullYear() : parseInt(year);

	this.dateFmt = (this.callback.params.dateFmt) ? this.callback.params.dateFmt : Calendar[this.locale].dates.dateFmt;
	var buffer = document.createDocumentFragment();
	for (var i=0; i<c; i++){
		var firstDate = new Date(y,m-1+i,1);
		if ((m+i)%12 == 1 || i==0){
			var wrapper = createTiddlyElement(buffer,'table',null,'calendarWrapper');
			var tbody = createTiddlyElement(wrapper,'tbody');
			if (c > 1 && m==1 && c%12==0){
				this.naviBar(wrapper,tbody,firstDate,true);
			}
		}
		if (i%3 == 0)
			var tr = createTiddlyElement(tbody,'tr',null,'monthRow');
		var td = createTiddlyElement(tr,'td');
		td.vAlign = "top";

		this.selectMonth(td, firstDate);
	}
	if (c>3)
		Calendar.dummyDateCell(tr,(3-c%3)%3,2);
	place.appendChild(buffer);
};

Calendar.prototype.selectMonth = function(place, firstDate)
{
	var year = firstDate.getFullYear();

	var calElm = createTiddlyElement(place,'table',null,'calendar');
	var monElm = createTiddlyElement(calElm,'tbody');

	this.naviBar(place,monElm,firstDate);

	if (store.isDirty() || !Calendar.tiddlers)
		Calendar.hashTiddlers(firstDate);

	this.showMonth(monElm, firstDate);
};

Calendar.prototype.naviBar = function(place,monElm,firstDate,isYearView)
{
	var cal = this;
	var monthHeader = createTiddlyElement(createTiddlyElement(monElm,'tr'),'td',null, 'naviBar', null, {colSpan:7});

	var _selectMonthHandler = function(s,date,isYearView){
		if (isYearView){
			cal.show(s.parentNode,date.getFullYear(),1,12);
			removeNode(s);
		} else {
			cal.selectMonth(s, date,cal.dateFmt);
			removeNode(s.firstChild);
		}
	};

	var onchange = function(ev){
		var e = ev ? ev : window.event;
		var date=null;
		for (var i=0, options=this.options; i<options.length; i++){
			if (options[i].selected)
				date = new Date(options[i].value);
		}
		_selectMonthHandler.call(this,place,date,isYearView);
		return false;
	};

	var year = firstDate.getFullYear();
	var n = 3;
	var y = isYearView ? year - n : year;
	var m = isYearView ? 0 : new Date(firstDate).getMonth()- n;
	var c = null;
	var options = [];
	var fmt = isYearView ? Calendar[this.locale].dates.yearFmt : Calendar[this.locale].dates.monthFmt;
	for (var i=0; i<n*2+1; i++){
		c= isYearView ? new Date(y+i,1,1) : new Date(y,m+i,1); 
		options.push({caption: c.formatString(fmt), name: c});
	}

	var sel=createTiddlyDropDown(monthHeader,onchange,options);
	sel.selectedIndex = n;
};

Calendar.prototype.showMonth = function(monElm, firstDate)
{
	var year = new Date(firstDate).getFullYear();
	var month = new Date(firstDate).getMonth()+1; 
	var lastDate = new Date(year,month,0).getDate();
	var nextFirstDay = new Date(year,month,1).getDay();
	var offset = (7 + firstDate.getDay() - Calendar[this.locale].dates.startOfWeek)%7;

	var buffer = document.createDocumentFragment();
	var	dayHearder = createTiddlyElement(buffer,'tr');
	for (var i=0, ii=0, text=null; i<7; i++){
		ii = (Calendar[this.locale].dates.startOfWeek + i)%7;
		text = Calendar[this.locale].dates.days[ii];
//#		createTiddlyElement(theParent,theElement,theID,theClass,theText,attribs)
		createTiddlyElement(dayHearder,'th',null,null,text); 
	}

	var d=1, dayRow=null, celldate=null, isWeekend = false;
	while (d<=lastDate){
		dayRow = createTiddlyElement(buffer,'tr');

		if (offset > 0)
			Calendar.dummyDateCell(dayRow,offset,6);

		for (var i=offset; i<7 && d <= lastDate; i++, d++){
			celldate = new Date(year, month-1, d);
			isWeekend = Calendar[this.locale].dates.weekends[(i + Calendar[this.locale].dates.startOfWeek)%7];
			this.showDate(dayRow, d, celldate, isWeekend);
		}

		offset=0;
	}
	var n = 7 - (7 + nextFirstDay - Calendar[this.locale].dates.startOfWeek)%7;
	if (n < 7)
		Calendar.dummyDateCell(dayRow,n,6);
	monElm.appendChild(buffer);
};

Calendar.prototype.showDate = function(dayRow, date, celldate, isWeekend)
{
	var now = new Date();
	var dateFmt = this.dateFmt;
	var today = now.formatString(dateFmt);
	var cellClass = 'dateCell';
	var title = celldate.formatString(dateFmt);
	var day = celldate.getDay();
	var isToday = today == title;
	var isHoliday = this.isHoliday(celldate);

	if (isToday)
		cellClass += ' today';
	if (isWeekend)
		cellClass += ' weekend';
	if (isHoliday) 
		cellClass += ' holiday';

	var dateCell=createTiddlyElement(dayRow,'td',null,cellClass);

	var ymd = celldate.convertToLocalYYYYMMDDHHMM().substr(0,8);
	var callback = this.callback;
	var option = callback.option;
	if (!option){
		if (Calendar.tiddlers[ymd]){
			cellClass += ' hasChanged';
			option = 'popup';
		} else {
			option = 'displayTiddler';
		}
	}

	var params = callback.params;
	merge (params,{date:date, title:title, celldate:celldate, cellClass:cellClass, dateFmt:dateFmt});
	if (callback.fn instanceof Function && callback.fnEnable){
		callback.fn(dateCell, params);
	} else
		Calendar.optionHandler(dateCell, option, params, celldate);
};

Calendar.prototype.isHoliday = function(date) 
{
	return Calendar[this.locale].dates.holidays.containsAny([
		date.formatString(Calendar[this.locale].dates.longHolidayFmt),
		date.formatString(Calendar[this.locale].dates.shortHolidayFmt)]);
};

Calendar.dummyDateCell = function (srcElm,n,max)
{
	for (var i=0; i< n && i<max; i++)
		createTiddlyElement(srcElm,'td');
};

Calendar.hashTiddlers = function(date)
{
	if (date)
		var ymd = date.convertToLocalYYYYMMDDHHMM().substr(0,8);
	var isChanged = false;
	var tiddlers = {};

	store.forEachTiddler(function(title, tiddler){
		var modified = tiddler.modified.convertToLocalYYYYMMDDHHMM().substr(0,8);
		var created = tiddler.created.convertToLocalYYYYMMDDHHMM().substr(0,8);

//		if (modified.substr(0,6) == ymd.substr(0,6)){
//			var dd = modified.substr(6,2);
			var extraCellClass = '';
			extraCellClass += (tiddler.modified == tiddler.created) ? ' isCreated' : '';
			extraCellClass += tiddler.isTagged("excludeLists") ? ' isExcluded' : '';
			if (!tiddlers[modified])
				tiddlers[modified]=[];
			tiddlers[modified].push({title:tiddler.title, modified:tiddler.modified, ymd:modified, extraCellClass:extraCellClass});
//		}
	});

	this.tiddlers = tiddlers;
};

Calendar.optionHandler = function(srcElm,option,params,celldate)
{
	var fn = Calendar.optionType[option];
	var action = function(ev) {
		var e = ev ? ev : window.event;
			var fn = Calendar.optionType[option];
		if (fn instanceof Function)
			fn.call(this,e,srcElm,params);
		return false;
	};
//#	createTiddlyButton(parent,text,tooltip,action,className,id,accessKey,attribs);
	createTiddlyButton(srcElm, params.date, params.title, action, params.cellClass, null,null,params);
};

Calendar.optionType = {
	displayTiddler: function(e) {
		story.displayTiddler(null,this.title)
	},
	popup: function(e,daetCell) {
		var celldate = new Date(this.getAttribute('celldate'));
		Calendar.onClickDatePopup(e,daetCell,this.title,celldate);
	},
	pickDate: function(e) {
		Calendar.pickDate.call(this,e);
	}
};

Calendar.onClickDatePopup = function (ev,detaCell,title,celldate)
{
	var e = ev ? ev : window.event;
	if (store.isDirty())
		Calendar.hashTiddlers(celldate);

	var ymd = celldate.convertToLocalYYYYMMDDHHMM().substr(0,8);
	var tiddlers = Calendar.tiddlers[ymd];
	var popup = Popup.create(detaCell,null,'datePopup popup');
	createTiddlyElement(popup,'br');
	this.optionHandler(popup, "displayTiddler", {title:title, date:title});

	if (tiddlers){
		createTiddlyElement(popup,'hr');
		for (var i=0; i<tiddlers.length; i++)
			this.optionHandler(createTiddlyElement(popup,"li"), "displayTiddler",{date:tiddlers[i].title, title:tiddlers[i].title, cellClass:tiddlers[i].extraCellClass});
	}
	Popup.show();
	e.cancelBubble = true;
	if(e.stopPropagation) e.stopPropagation();
	return false;
};

Calendar.pickDate = function(ev)
{
	var e = ev ? ev : window.event;
	var inputId = this.getAttribute('inputId');
	if (inputId){
		var input = document.getElementById(inputId);
		if (input)
			input.value = this.title;
	}
	return false;
};
//}}}
/***
!Initialize Calendar
***/
//{{{
config.shadowTiddlers.CalendarStyle = Calendar.styles;
config.notifyTiddlers.pushUnique({name: 'CalendarStyle', notify: refreshStyles});
var calendar = new Calendar(); /* Create global Calendar object */
var datepicker = new Calendar(); /*Create global Date picker */
//}}}
/***
!Macros
***/
//{{{

config.macros.tCalendar = {
	init: function(){
		var fnEnable = config.options.chkCalendarCallback == undefined ? false : config.options.chkCalendarCallback;
		calendar.callback = {
			fn: this.showDate,
			fnEnable: (window.showDate instanceof Function && fnEnable),
			option: null,
			params: {date: null, dateFmt:null, celldate:null}
		};
	}
};

config.macros.tCalendar.handler = function(place,macroName,params)
{
	this.init();
	var mode = params[2] ? params[2] : (params[1] ? params[1] : params[0]);
	var modeType = params[0];
	var modeCount = isNaN(params[1]) ? 1 : parseInt(params[1]);

	var now = new Date();
	var y = now.getFullYear();
	var m = now.getMonth()+1;
	var c = isNaN(params[1]) ? 1 : parseInt(params[1]);
	switch (mode) {
		case 'month':
		case 'months':
			m = modeType == 'last' ? m - c : m + 1;
			break;
		case 'thisyear':
			m = 1;
			c = 12;
			break;
		case 'year':
		case 'years':
			y = modeType == 'last' ? y - c : y + 1;
			m = 1;
			c = 12 * c;
			break;
		case 'lastModified':
			var lastModified = this.getlastModified();
			y = lastModified.getFullYear();
			m = lastModified.getMonth()+1;
			c = 1;
			break;
		default:
			y = params[0];
			m = params[1];
			c = params[2];
	}
	calendar.show(place,y,m,c);
};

config.macros.tCalendar.showDate = function(dateCell,params)
{
	var isWeekend = (params.cellClass.indexOf('weekend') != -1);
//# For co-working with showDate() of DatePlugin
//#	showDate(place,date,mode,format,linkformat,autostyle,weekend)
	window.showDate(dateCell, params.celldate,'popup','DD',params.dateFmt,true,isWeekend);
};

config.macros.tCalendar.getlastModified = function()
{
	var tiddlers = store.reverseLookup("tags","excludeLists",false,'modified');
	return tiddlers[tiddlers.length-1].modified;
};

config.macros.datePicker = {
	onClick: function(ev) {
		var e = ev ? ev : window.event;
		var inputId = this.getAttribute("inputId");
		var dateFmt = this.getAttribute("dateFmt");
		dateFmt = dateFmt == 'null' ? null : dateFmt; /* For Opera */
		datepicker.callback = {
			fn: null,
			fnEnable: false,
			option: 'pickDate',
			params: {inputId:inputId, dateFmt:dateFmt}
		};

		var popup = Popup.create(this);
		datepicker.show(popup);
		Popup.show();

		e.cancelBubble = true;
		if(e.stopPropagation) e.stopPropagation();
		return false;
	}
};

config.macros.datePicker.handler = function(place,macroName,params)
{
	if (!params) return;
	var id = params[0];
	var dateFmt = params[1] ? params[1] : null;
	var pickParams = {inputId:id, dateFmt:dateFmt};

	var inputElm = createTiddlyElement(place,'input',id);
	var btn = createTiddlyButton(place, '?', 'Date Picker', this.onClick,'datepicker',null,null,pickParams);
};
//}}}
/***
|''Name:''|easyGraphs |
|''Description:''|An attempt to bring nice easy to use maps to tiddlywiki using geojson|
|''Author:''|JonRobson |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonRobson/verticals/GeoTiddlyWiki|
|''Version:''|0.0.5 |
|''Date:''|4/11/08 |
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''~CoreVersion:''|2.4|
|''Dependencies:''|This plugin requires a tiddler geojson containing geojson data eg.[[geojson]]|
***/

//{{{

var mygraph;
config.macros.TiddlyDiagram = {
	handler: function(place,macroName,params,wikifier,paramString,tiddler){
		
		
		var x = new EasyGraph();
		
		var json = {};
		if(tiddler.fields.tiddlydiagram){
			json =eval(tiddler.fields.tiddlydiagram);
			try{
				x.loadfromjson(json);
			}catch(e){}
		}
		

		var controller = {
			saveHandler: function(easyDiagram,json){
				var t = easyDiagram.getTransformation();
				json.transformation = t;
				console.log(json);
				var title = tiddler.title;
				var text = tiddler.text;
				var tags = tiddler.tags;
				var fields = tiddler.fields;
				fields.tiddlydiagram = json.toSource();
				store.saveTiddler(title,title,text,null,null,tags,fields);
			}
			,renderLabel: function(domElement,value){
				console.log("renderlabel with",value);
				domElement.innerHTML = "";
				wikify(value,domElement);
			}
		};
		var mydiagram = new EasyDiagram(place,x,controller);
		if(json.transformation)mydiagram.setTransformation(json.transformation);
		mygraph = mydiagram;
		mygraph.render();
		
	}
};

var EasyDiagram = function(wrapper,easyGraph,controller){
	if(!easyGraph){
		easyGraph = new EasyGraph();
	}
	if(!controller){
		controller = {
			renderLabel: function(domElement,value){
				domElement.innerHTML = value;
			}
			,saveHandler: function(easyDiagram,json){
				alert(json);
			}
		};
	}
	
	this.labelHolders = {};
	this.controller = controller;
	this.tempshapes = {};
	this.easyShapeToNode = {};
	this.wrapper = wrapper;
	this.easyGraph = easyGraph;	
	wrapper.style.position = "relative";
	var width = 600;
	var height = 400;
	wrapper.style.width = width + "px";
	wrapper.style.height = height + "px";
	this.canvas = document.createElement("canvas");
	this.canvas.width = width;
	this.canvas.height = height;
	
	this.canvas.style.border = "solid 1px black";
	
	this.wrapper.appendChild(this.canvas);
	this.easyClicking = new EasyClicking(this.wrapper);
	this.setupMouseHandlers();
		
	this.easyController = new EasyMapController(this,this.wrapper);
	this.easyController.addControl("pan");
	this.easyController.addControl("mousepanning");
	this.easyController.addControl("mousewheelzooming");
	this.easyController.addControl("zoom");
	this.transform({});
		
	this.createDrawingControls();
	
	
};

EasyDiagram.prototype = {
	getEasyGraph: function(){
		return this.easyGraph;
	}
	,getTemporaryShape: function(name){
		if(!this.tempshapes[name]) 
			return false;
		else
			return this.tempshapes[name];
	}
	,addTemporaryShape: function(name,easyShape){
		this.tempshapes[name] = easyShape;
	}
	,deleteTemporaryShape: function(name){
		delete this.tempshapes[name];
	}
	,setDrawingCommand: function(json){
		if(!json){
			json = {type:'false'};
		}
		
		if(!json.type) throw "json must have a type property!";
		this.toolCommand = json;
	
	}
	,getDrawingCommand: function(){
		if(!this.toolCommand) this.toolCommand = {type:false};
		return this.toolCommand;
	}
	,createDrawingControls: function(){
		
		var tooltip = document.createElement("div");
		tooltip.style.position = "absolute";	
		//tooltip.style.zIndex = 30;
		tooltip.innerHTML = "..";
		this.tooltip = tooltip;
		
		var drawNode = document.createElement("button");
		drawNode.style.position = "absolute";
		drawNode.innerHTML = "new node";
		drawNode.style.top = 0;
		drawNode.style.left = this.wrapper.style.width;
		
		var drawEdge = document.createElement("button");
		drawEdge.style.position = "absolute";
		drawEdge.innerHTML = "new edge";
		drawEdge.style.top = 40+"px";
		drawEdge.style.left = this.wrapper.style.width;
		
		
		var deleteNode = document.createElement("button");
		deleteNode.style.position = "absolute";
		deleteNode.innerHTML = "delete";
		deleteNode.style.top = 80+"px";
		deleteNode.style.left = this.wrapper.style.width;
		
		 var save = document.createElement("button");
		save.style.position = "absolute";
		save.innerHTML = "save";
		save.style.top = 120+"px";
		save.style.left = this.wrapper.style.width;
		
		var easyGraph = this.easyGraph;
		var easyDiagram = this;
		easyDiagram.toolCommand = false;
		
		save.onclick = function(e){

			easyDiagram.controller.saveHandler(easyDiagram,easyGraph.burntojson());
		}
		deleteNode.onclick = function(e){
			easyDiagram.setDrawingCommand({type: "delete"});
		}
		drawEdge.onclick = function(e){
			easyDiagram.setDrawingCommand({type: "drawEdge",start: false, end: false});
		};
		drawNode.onclick = function(e){
			var uniqueid = Math.random();
			easyDiagram.setDrawingCommand({type: "newNode"});
			easyGraph.addNode({id:uniqueid,properties:{label: "new node",shape:'polygon'}});
			easyDiagram.selectedShape = easyGraph.getNode(uniqueid).getEasyShape();	
			easyDiagram.render();
		}
		
		this.wrapper.appendChild(tooltip);
		this.wrapper.appendChild(drawEdge);
		this.wrapper.appendChild(drawNode);
		this.wrapper.appendChild(deleteNode);
		this.wrapper.appendChild(save);
	}
	,getNodeFromShape: function(easyShape){
		if(this.easyShapeToNode[easyShape.properties.id])
			return this.easyShapeToNode[easyShape.properties.id]
		else
			return false;
	}
	,selectShape: function(s){
		var command =this.getDrawingCommand();
		var easyDiagram = this;
		if(s && !easyDiagram.selectedShape){//highlight with box?
			if(command.type == 'editlabel' || command.type == 'drawEdge') return;
						
			easyDiagram.selectedShape = s;
			easyDiagram.selectedShape.properties.fill = "rgb(0,255,0)";
		}
		else{

			if(easyDiagram.selectedShape){
				easyDiagram.selectedShape.properties.fill = "rgb(255,0,0)";
			}
			easyDiagram.selectedShape= false;

		}
		
		easyDiagram.render();
		
	}
	,setTooltip: function(e){
		
		var newpos =EasyClickingUtils.getMouseFromEvent(e);
		newpos.x + 20;
		newpos.y + 20;
		//this.tooltip.style.left = newpos.x + "px";
		//this.tooltip.style.top = newpos.y + "px";
		
		var command = this.getDrawingCommand();
		if(command.type){
		this.tooltip.innerHTML =command.type;
		}
		else
		this.tooltip.innerHTML = "";
	
	}
	,drawTemporaryLines: function(x,y){
		var line =this.getTemporaryShape("pathinprogress");
		if(line){
			var c = line.getCoordinates();
			c[2]= x;
			c[3]= y;
			line.setCoordinates(c);
		}
	}
	,moveSelectedShapes: function(x,y){
		if(this.selectedShape) {
			var shape = this.selectedShape;
			var node = this.getNodeFromShape(shape);
			node.setPosition(x - 20,y - 20);
		}
	}
	,deleteShape: function(easyShape){
		var n = this.getNodeFromShape(easyShape);
		
		if(n.properties.shape != 'path'){
			var edit = this.getLabelHolder(n.id,"editlabel");
			var view =this.getLabelHolder(n.id,"label");
			edit.style.display = "none";
			view.style.display = "none";
			this.getEasyGraph().deleteNode(n);
			this.render();
		}
	}
	
	,setTransformation: function(t){
		this.easyController.setTransformation(t);
	}
	,getTransformation: function(){
		return this.tmatrix;
	}
	,setupMouseHandlers: function(){
		var easyDiagram = this;
		var easyGraph = this.easyGraph;
		this.wrapper.onmousemove = function(e){						
			var t = easyDiagram.getTransformation();
			var newpos =EasyClickingUtils.getRealXYFromMouse(e,t);
			easyDiagram.moveSelectedShapes(newpos.x,newpos.y);
			easyDiagram.drawTemporaryLines(newpos.x,newpos.y);
			easyDiagram.setTooltip(e);
			easyDiagram.render();
		}
		this.wrapper.onmousedown = function(e){
			if(!e) e = window.event;
			var s = easyDiagram.easyClicking.getShapeAtClick(e);
			var target = EasyClickingUtils.resolveTarget(e);
			if(target.className == "easyControl") return;
			if(e.button <= 1){//left mouse
				var command = easyDiagram.getDrawingCommand();
				if(command){
					if(s){			
						
						if(command.type == 'drawEdge'){
							if(!command.start){
								command.start = s.properties.id;
								var t = easyDiagram.getTransformation();
								var startpos =EasyClickingUtils.getRealXYFromMouse(e,t);
								var p = new EasyShape({shape:"path",stroke: '#000000',lineWidth: '1'},[startpos.x,startpos.y,startpos.x,startpos.y]);
								easyDiagram.addTemporaryShape("pathinprogress",p);					
							}
							else if(!command.end){
								easyGraph.addEdge(command.start, s.properties.id);
								easyDiagram.setDrawingCommand(false);
								easyDiagram.deleteTemporaryShape("pathinprogress");
								easyDiagram.render();
							}
						}
						else if(command.type == 'delete'){
							easyDiagram.deleteShape(s);
						}
					}
				}
				easyDiagram.selectShape(s);
			}
			else{//right mouse
				console.log("clicked right mouse");
				easyDiagram.selectedShape = false;
				easyDiagram.toolCommand.start = false;
				easyDiagram.deleteTemporaryShape("pathinprogress");
				
			}
		}

	}

	,transform: function(matrix){
		var o1 = parseInt(this.canvas.width) /2;
		var o2 = parseInt(this.canvas.height) /2;
		this.tmatrix = EasyTransformations.clone(matrix);
		this.tmatrix.origin={x:o1,y:o2};
		this.easyClicking.setTransformation(this.tmatrix);
		this.render();
	}
	
	,render: function(){
		this.easyClicking.clearMemory();

		if(this.canvas.getContext){
			var ctx =this.canvas.getContext('2d');
			ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
		}
		this._renderEdges();
		
		
		for(i in this.easyGraph.nodes){
			var node = this.easyGraph.nodes[i];
			this._renderNode(node);
		}
		this._renderTemporaryShapes();
		
	}

	,_renderTemporaryShapes: function(){
		for(i in this.tempshapes){
			this.tempshapes[i].render(this.canvas, this.tmatrix);
		}
	}
	,isNodeVisible: function(x,y){
		if(x < 0 || x > this.canvas.width || y >this.canvas.height || y < 0)
		return false;
		else
		return true;
	}
	
	,getLabelHolder: function(id,reference){
		if(this.labelHolders[id]){
			if(this.labelHolders[id][reference]){
				return this.labelHolders[id][reference]
			}
			else
				return false;
		}
		else
			return false;
	}
	,setLabelHolder: function(id,reference,domElement){
		if(!this.labelHolders[id]) this.labelHolders[id] = {};
		this.labelHolders[id][reference] = domElement;
	}
	,_renderEdges: function(directed){
		var edgeCoords = [];
		for(i in this.easyGraph.nodes){
			try{
				var node =this.easyGraph.nodes[i];
				var npos = node.getPosition();
				if(!npos.x || !npos.y) {
					this.easyGraph.calculateNodePositions();
					this.render();
					return;
				}				


				var children = this.easyGraph.getNodeChildren(node.id);
				for(var j=0; j < children.length; j++){
					var child = this.easyGraph.getNode(children[j]);
					if(child){
						var cpos = child.getPosition();
						if(!cpos.x || !cpos.y) {
							this.easyGraph.calculateNodePositions();
							this.render();
							return;
						}
						if(edgeCoords.length >0) edgeCoords.push("M");
						edgeCoords.push(npos.x);
						edgeCoords.push(npos.y);
						edgeCoords.push(cpos.x);
						edgeCoords.push(cpos.y);
					}
				}
				//update coordinates using children
			}
			catch(e){
				console.log(e);
				throw e;
			}
		}


		var e = new EasyShape({shape:"path",stroke: '#000000',lineWidth: '1'},edgeCoords);
		this.edgeShape = e;		
		this.edgeShape.render(this.canvas, this.tmatrix);
	}
	,_renderNode: function(node){	
		var npos = node.getPosition();
		var shape = node.easyShape;
		this.easyShapeToNode[shape.properties.id] = node;

		if(!this.getLabelHolder(node.id,"label")){
			var nodelabel = document.createElement("div");
			var nodelabeledit = document.createElement("input");
			nodelabel.style.display = "";
			nodelabeledit.style.display = "none";
			this.controller.renderLabel(nodelabel,node.getProperty("label"))
			nodelabeledit.value = node.getProperty("label");
			nodelabel.style.position = "absolute";
			nodelabeledit.style.position = "absolute";
			
			this.wrapper.appendChild(nodelabeledit);
			this.wrapper.appendChild(nodelabel);
			this.setLabelHolder(node.id,"label",nodelabel);
			this.setLabelHolder(node.id,"editlabel",nodelabeledit);
			
			var easyDiagram = this;
			nodelabeledit.onblur = function(e){
				node.setProperty("mode",0); //?
				easyDiagram.setDrawingCommand(false);
				nodelabeledit.style.display = "none";
				nodelabel.style.display = "";
				node.setProperty("label",nodelabeledit.value);
				easyDiagram.controller.renderLabel(nodelabel,nodelabeledit.value)
			}
			nodelabel.ondblclick = function(e){
				easyDiagram.setDrawingCommand({type:'editlabel'});
				node.setProperty("mode",1);//?
				nodelabeledit.style.display = "";
				nodelabel.style.display = "none";
			};
		}
		var bb = shape.getBoundingBox();
		var label = {};
		label.x = bb.x1 + 5;//parseFloat((bb.x2 - bb.x1) / 2);
		label.y = bb.y1 + 5;//parseFloat((bb.y2 - bb.y1) / 2);
		
		label = EasyTransformations.applyTransformation(label.x, label.y,this.tmatrix);
		
		var viewlabel = this.getLabelHolder(node.id,"label");
		var editlabel = this.getLabelHolder(node.id,"editlabel");
		if(viewlabel && editlabel){
			if(this.isNodeVisible(label.x,label.y)){			
				if(node.getProperty("mode") == 1){
					viewlabel.style.display = "none";
					editlabel.style.display = "";				
				}
				else{
					viewlabel.style.display = "";
					editlabel.style.display = "none";	
				}


			
				viewlabel.style.top = label.y + "px";
				viewlabel.style.left = label.x + "px";
				editlabel.style.top = label.y + "px";
				editlabel.style.left = label.x + "px";
				this.easyClicking.addToMemory(shape);
				shape.render(this.canvas,this.tmatrix);
			}
			else{
				viewlabel.style.display = "none";
				editlabel.style.display = "none";	
			}
		}
	}
};var EasyGraph = function(positionCalculationFunction){

	this.nodes = {};
	this.nodeParents = {};
	this.nodeChildren = {};
	
	var easyGraph = this;
	if(!positionCalculationFunction){
		this.positionCalculationFunction = function(node){
			var oldpos = node.getPosition();
			if(oldpos.x && oldpos.y) return oldpos;
			
			var range = 200;
			var nodepos = {};
			var parents =easyGraph.getNodeParents(node.id);
			var partners =EasyGraphUtils.getPartners(node.id,easyGraph);
			var siblings = EasyGraphUtils.getSiblings(node.id,easyGraph);
			for(var i=0; i < siblings.length; i++){
				var sib = easyGraph.getNode(siblings[i]);
				var pos = sib.getPosition();
				if(pos.x){
					nodepos.x = pos.x;
				}
			}
			
			for(var i=0; i < partners.length; i++){
				var partner = easyGraph.getNode(partners[i]);
				var pos = partner.getPosition();
				if(pos.x){
					nodepos.x = pos.x;
				}
			}
			
			for(var i=0; i < parents.length; i++){
				var parentPos;
				var parent =easyGraph.getNode(parents[i]);
				parentPos = parent.getPosition();
				if(parentPos.x){
					if(nodepos.x){
						if(parentPos.x >= nodepos.x)
							nodepos.x = parentPos.x + 200;
					}
					else{
						nodepos.x = parentPos.x + 200;
					}
				}
			}
			if(!nodepos.x) {
				nodepos.x = 5;
			}
			var children =easyGraph.getNodeChildren(node.id); 
			for(var i=0; i < children.length; i++){
				
			}
		
			nodepos.y = Math.random() * 400;
			
			
			
			
			return nodepos;
		};
	}

	return false;
};

EasyGraph.prototype = {

	/*querying */
	getNode: function(id){
		if(!this.nodes[id]) 
			return false;
		else
			return this.nodes[id];
	}	
	,getNodeChildren: function(id){
		//console.log(id, this.nodeChildren,"getch");
		if(!this.nodeChildren[id]) {
			return [];
		}
		else{
			return this.nodeChildren[id];
		}
	}

	,getNodeParents: function(id){
		if(!this.nodeParents[id]) return [];
		return this.nodeParents[id];
	}
	/*manipulating */

	,addNode: function(nodejson){
		this.nodes[nodejson.id] = new EasyGraphNode(nodejson);
		return false;
	}
	,deleteNode: function(nodejson){
		var id = nodejson.id;
		delete this.nodes[id];
		
		/*delete it's attachment to children */
		var children = this.getNodeChildren();
		for(var i=0; i < children.length; i++){
			this.deleteEdge(id, children[i]);
		}
		
		
		var parents = this.getNodeParents();
		for(var i=0; i < parents.length; i++){
			this.deleteEdge(parents[i],id);
		}
		
		
		return false
	}
		
	,addEdge: function(id1,id2){

		if(!this.nodes[id1]) {
			var json = {};
			json.id = id1;
			json.properties = {};
			this.addNode(json);
		}
		if(!this.nodes[id2]) {
			var json = {};
			json.id = id2;
			json.properties = {};
			this.addNode(json);
		}
		

		if(!this.nodeChildren[id1])this.nodeChildren[id1] = [];
		if(!this.nodeParents[id2]) this.nodeParents[id2] = [];
		
		this.nodeChildren[id1].push(id2);
		this.nodeParents[id2].push(id1);
		return false;	
	}
	,deleteEdge: function(id1,id2){		
		var childrenOfOne = this.getNodeChildren(id1);	
		var newkids = [];
		for(var i=0; i < childrenOfOne.length; i++){
			if(i != id2) newkids.push(i);
		}
		this.nodeChildren[id1] = newkids;
		
		
		var parentsOfTwo = this.getNodeParents(id2);
		
		var newparents = [];
		for(var i=0; i < parentsOfTwo.length; i++){
			if(i != id1) newparents.push(i);
		}
		this.nodeParents[id2] = newparents;
		
		
		return false;
	}
	,setFocusedNode: function(id){
		console.log("not implemented yet");
		return false;	
	}
	,calculateNodePositions: function(){
		for(i in this.nodes){
			var newpos =this.positionCalculationFunction(this.nodes[i]);
			this.nodes[i].setPosition(newpos.x,newpos.y);
		}
		return false;
	}
	
	,burntojson: function(){
		var json = {};
		json.nodes = [];
		var i;
		for(i in this.nodes){
			var node = this.nodes[i].burntojson();
			json.nodes.push(node);
		}
		
		json.edges = [];
		for(i in this.nodes){
			var children = this.getNodeChildren(i);
			for(var c = 0; c < children.length; c++){
				var child = children[c];
				json.edges.push([i,child]);
			}
		}
		
		return json;
	}
	,loadfromjson: function(json){
		var i;
		for(var i=0; i< json.nodes.length;i++){
			this.addNode(json.nodes[i]);
		}
		
		for(var i=0; i< json.edges.length;i++){
			var pair = json.edges[i];
			this.addEdge(pair[0],pair[1]);
		}
		
	}
};

var EasyGraphNode = function(json){
	/*recognised/reserved properties are:
	fill, label, position,shape,width,height
	*/

	var id = json.id;
	var properties = json.properties;
	this.id = id;		
	this.properties = this.completeProperties(properties);
	
	var pos = this.getProperty("position");
	var x = pos.x;
	var y = pos.y;
	var w = this.getProperty("width") /2 ;
	var h = this.getProperty("height") /2;
	//console.log(x,y);
	this.easyShape = new EasyShape(properties,[x-w,y-h,x+w,y-h, x+w,y+h,x - w,y+h]);
	
	return false;
};

EasyGraphNode.prototype = {
	burntojson: function(){
		var json = {};
		json.id = this.id;
		json.properties = this.properties;
		return json;
	}
	,completeProperties: function(properties){
		if(!properties){
			properties = {};
		}
		if(!properties.width) properties.width = 100;
		if(!properties.height) properties.height = 100;
		if(!properties.shape)properties.shape = "polygon";
		if(!properties.id) properties.id= this.id;
		if(!properties.fill) properties.fill = "#ff0000";
		if(!properties.position) properties.position = {x:0,y:0};
		
		return properties;
	}
	,getEasyShape: function(){
		return this.easyShape;
	}
	,getProperty: function(name){
		if(!this.properties[name]) 
			return false;
		else
			return this.properties[name];
	}
	,setProperty: function(name,value){
		this.properties[name] = value;
	}
	,getPosition: function(){
		return this.getProperty("position");
	}
	,setPosition: function(x,y){
		//setCoords();
		var w = this.getProperty("width") /2 ;
		var h = this.getProperty("height") /2;
		//console.log(x,y);
		this.setProperty("position",{x:x,y:y});
		this.easyShape.setCoordinates([x-w,y-h,x+w,y-h, x+w,y+h,x - w,y+h]);
		
	}
};
var EasyGraphUtils = {

	getPartners: function(id,easyGraph){
		var partners = [];
		var childrenNodes = easyGraph.getNodeChildren(id);
		var marked = {};
		marked[id] = true;
		
		for(var i=0; i < childrenNodes.length; i++){
			var child = childrenNodes[i];
			var partnerNodes = easyGraph.getNodeParents(child);
			for(var j=0; j < partnerNodes.length; j++){
				var partner = partnerNodes[j];
				
				
				if(!marked[partner]){
					partners.push(partner);	
					marked[partner] = true;				
				}

			}
		}
		console.log(id,"has partners", partners);
		return partners;
		
	}
	,getSiblings: function(id,easyGraph){
		
		var parentnodes = easyGraph.getNodeParents(id);
		
		var siblings = [];
		var marked = {};
		marked[id] = true;
		
		for(var i=0; i < parentnodes.length; i++){
			var parent = parentnodes[i];
			var siblingNodes = easyGraph.getNodeChildren(parent);
			for(var j=0; j < siblingNodes.length; j++){
				var sib = siblingNodes[j];
				
				
				if(!marked[sib]){
					console.log("value is ",marked[sib]);
					siblings.push(sib);	
					marked[sib] = true;				
				}

			}
		}
		
		return siblings;
		
	}
};
var EasyTransformations= {
	clone: function(transformation){
	
		var t = {};
		t.translate = {x:0,y:0};
		t.scale = {x:1,y:1};

		if(transformation.translate && transformation.translate.x){
			t.translate.x = transformation.translate.x;
			t.translate.y = transformation.translate.y;
		}
		
		if(transformation.scale && transformation.scale.x){
			t.scale.x = transformation.scale.x;
			t.scale.y = transformation.scale.y;		
		}
		
		return t;
	}
	,applyTransformation: function(x,y,t){
		var res= {};
		res.x = x;
		res.y = y;



		if(t.translate){
			res.x +=  t.translate.x;
			res.y += t.translate.y;
		}
		if(t.scale){
			res.x *= t.scale.x;
			res.y *= t.scale.y;
		}

		if(t.origin){
			res.x += t.origin.x;
			res.y += t.origin.y;
		}
		return res;
		
	}
	,mergeTransformations: function(a,b){
		if(!b) return a;
		if(!a) return b;
		
		var result = {};
		var i;
		for(i in a){
			result[i] = a[i];
		}
		
		for(i in b){
			if(result[i]){
				var oldt = result[i];
				var newt = b[i];
				
				result[i].x = oldt.x + newt.x;
				result[i].y = oldt.y + newt.y;
			}
			else{
				result[i] = b[i];
			}
		}
		return result;
	}
	
};/*requires EasyShapes and EasyController */

var EasyMapController = function(targetjs,elem){ //elem must have style.width and style.height
	this.setMaxScaling(99999999);
	if(!elem.style.position) elem.style.position = "relative";
	this.wrapper = elem; //a dom element to detect mouse actions
	this.targetjs = targetjs; //a js object to run actions on (with pan and zoom functions)	

	var controlDiv = this.wrapper.controlDiv;
	if(!controlDiv) {
		controlDiv = document.createElement('div');
		controlDiv.style.position = "absolute";
		controlDiv.style.top = "0";
		controlDiv.style.left = "0";
		this.wrapper.appendChild(controlDiv);
		this.wrapper.controlDiv = controlDiv;
	}
	this.transformation = {'translate':{x:0,y:0}, 'scale': {x:1, y:1},'rotate': {x:0,y:0,z:0}};	
	//looks for specifically named function in targetjs
	if(!this.targetjs.transform) alert("no transform function defined in " + targetjs+"!");
	this.wrapper.easyController = this;
	

};
EasyMapController.prototype = {
	addMouseWheelZooming: function(){ /*not supported for internet explorer*/
		var mw = this.wrapper.onmousewheel;
		var that = this;
		var onmousewheel = function(e){
	        	if (!e) /* For IE. */
	                e = window.event;
			e.preventDefault();		
					
			/* thanks to http://adomas.org/javascript-mouse-wheel */
			var delta = 0;

	
			var t = EasyClickingUtils.resolveTarget(e);
			
			if(t != that.wrapper && t.parentNode !=that.wrapper) return;
	       	 	if (e.wheelDelta) { /* IE/Opera. */
		                delta = e.wheelDelta/120;
		                /** In Opera 9, delta differs in sign as compared to IE.
		                 */
		                if (window.opera)
		                        delta = -delta;
		        } else if (e.detail) { /** Mozilla case. */
		                /** In Mozilla, sign of delta is different than in IE.
		                 * Also, delta is multiple of 3.
		                 */
		                delta = -e.detail/3;
		        }
	
			var sensitivity = 0.3;
			if(!this.lastdelta) this.lastdelta = delta;
			
			if(delta > this.lastdelta + sensitivity || delta < this.lastdelta - sensitivity){
				
			
				var s =that.transformation.scale;
				
				var pos = EasyClickingUtils.getMouseFromEventRelativeToCenter(e);
				var t=  that.transformation.translate;
				
				var newx,newy;
				if(delta > 0){
					newx = parseFloat(s.x) * 2;
					newy = parseFloat(s.y) * 2;					
				}
				else{
					newx = parseFloat(s.x) / 2;
					newy = parseFloat(s.y) / 2;
				}

				if(newx > 0 && newy > 0){
					s.x = newx;
					s.y = newy;
					that.transform();					
				}

			}
			
			this.lastdelta = delta;
			
			return false;

		}

		
		var element = this.wrapper;
		if (element.addEventListener){
		        /** DOMMouseScroll is for mozilla. */
		
		        element.addEventListener('DOMMouseScroll', onmousewheel, false);
		
		}
		else if(element.attachEvent){
			element.attachEvent("mousewheel", onmousewheel); //safari
		}
		else{ //it's ie.. or something non-standardised. do nowt
		//window.onmousewheel = document.onmousewheel = onmousewheel;	
		}

		
	},

	addMousePanning: function(){
		var that = this;
		var md = that.wrapper.onmousedown;
		var mu = that.wrapper.onmouseup;	
		var mm = that.wrapper.onmousemove;
		var onmousemove = function(e){
			if(!this.easyController)return;
			var p =this.easyController.panning_status;
			if(!p) return;
			var t =  EasyClickingUtils.resolveTarget(e);

			if(t.tagName == "INPUT") return;
			if(t.getAttribute("class") == "easyControl") return;
			
			var pos =  EasyClickingUtils.getMouseFromEventRelativeToElement(e,p.clickpos.x,p.clickpos.y,p.elem);		
			if(!pos)return;
			
			var t = that.transformation;
			//if(this.transformation) t = this.transformation;
			var sc = t.scale;

			/* work out deltas */
			var xd =parseFloat(pos.x /sc.x);
			var yd = parseFloat(pos.y / sc.y);
			t.translate.x = p.translate.x + xd;
			t.translate.y =p.translate.y +yd;

			that.transform();
			
			if(pos.x > 5 || pos.y > 5) p.isClick = false;
			if(pos.x < 5 || pos.y < 5) p.isClick = false;
			return false;	
		};
		
		this.wrapper.onmousedown = function(e){
					
			if(md) md(e);
			var target =  EasyClickingUtils.resolveTarget(e);
			if(!target) return;

			if(target.getAttribute("class") == "easyControl") return;

			var t = that.transformation.translate;
			var sc =that.transformation.scale; 
			var realpos = EasyClickingUtils.getMouseFromEvent(e);
			if(!realpos) return;
			this.easyController = that;
			
			var element = EasyClickingUtils.resolveTargetWithEasyClicking(e);
			that.panning_status =  {clickpos: realpos, translate:{x: t.x,y:t.y},elem: element,isClick:true};
			
			that.wrapper.onmousemove = onmousemove;
			that.wrapper.style.cursor= "move";
			this.style.cursor = "move";
		
		};
		
		this.wrapper.onmouseup = function(e){
			that.wrapper.style.cursor= '';
			that.wrapper.onmousemove = mm;
			
			if(!this.easyController && mu){mu(e); return;};
			if(this.easyController.panning_status && this.easyController.panning_status.isClick && mu){ mu(e);}
			this.easyController.panning_status = null;
			
			return false;
		};
	
	
	},
	setTransformation: function(t){
		if(!t.scale && !t.translate && !t.rotate) alert("bad transformation applied - any call to setTransformation must contain translate,scale and rotate");
		this.transformation = t;
		//console.log("transformation set",t);
		//this.wrapper.transformation = t;
		this.targetjs.transform(t);
		//console.log("transformation set to ",t);
	},
	createButtonLabel: function(r,type){
		var properties=  {'shape':'path', stroke: '#000000',lineWidth: '1'};
		
		var coords=[];
		if(type == 'earrow'){
			coords =[r,0,-r,0,'M',r,0,0,-r,"M",r,0,0,r];
		}
		else if(type =='warrow'){
			coords =[-r,0,r,0,'M',-r,0,0,r,"M",-r,0,0,-r]; 
		}
		else if(type == 'sarrow'){
			coords =[0,-r,0,r,'M',0,r,-r,0,"M",0,r,r,0];	
		}
		else if(type == 'narrow'){
			coords =[0,-r,0,r,'M',0,-r,r,0,"M",0,-r,-r,0];	
		}
		else if(type == 'plus'){
			coords =[-r,0,r,0,"M",0,-r,0,r];
		}
		else if(type == 'minus'){
			coords = [-r,0,r,0];
		}
		
		return new EasyShape(properties,coords);
	},	
	createButton: function(canvas,width,direction,offset,properties) {
		if(!width) width = 100;
		var r = width/2;

		offset = {
			x: offset.x || 0,
			y: offset.y || 0
		};
		var coords = [
			offset.x, offset.y,
			offset.x + width, offset.y,
			offset.x + width, offset.y + width,
			offset.x, offset.y + width
		];
		properties.shape = 'polygon';
		properties.fill ='rgba(150,150,150,0.7)';
		var button = new EasyShape(properties,coords);
		button.render(canvas,{translate:{x:0,y:0}, scale:{x:1,y:1},origin:{x:0,y:0}});
		var label = this.createButtonLabel(r,properties.buttonType);
		label.render(canvas,{translate:{x:0,y:0}, scale:{x:1,y:1},origin:{x:offset.x + r,y:offset.y + r}});
		
		canvas.easyClicking.addToMemory(button);
		return button;
	},	
	addControl: function(controlType) {
		switch(controlType) {
			//case "zoom":
			case "pan":
				this.addPanningActions();
				break;
			case "zoom":
				this.addZoomingActions();
				break;
			case "mousepanning":
				this.addMousePanning();
				break;
			case "mousewheelzooming":
				this.addMouseWheelZooming();
				break;
			case "rotation":
		
				this.addRotatingActions();
				break;
			default:
				break;
		}
	
	},
	
	_createcontrollercanvas: function(width,height){
		var newCanvas = document.createElement('canvas');
		newCanvas.style.width = width;
		newCanvas.style.height = height;
		newCanvas.width = width;
		newCanvas.height = height;
		newCanvas.style.position = "absolute";
		newCanvas.style.left = 0;
		newCanvas.style.top = 0;
		newCanvas.style.zIndex = 3;
		newCanvas.setAttribute("class","easyControl");
		this.wrapper.appendChild(newCanvas);

		if(!newCanvas.getContext) {
			newCanvas.browser = 'ie';
		}
		newCanvas.easyController = this;
		newCanvas.easyClicking = new EasyClicking(newCanvas);
		
		//newCanvas.memory = [];
		return newCanvas;
	},
	addPanningActions: function(controlDiv){
		var panCanvas = this._createcontrollercanvas(44,44);		
		this.createButton(panCanvas,10,180,{x:16,y:2},{'actiontype':'N','name':'pan north','buttonType': 'narrow'});
		this.createButton(panCanvas,10,270,{x:30,y:16},{'actiontype':'E','name':'pan east','buttonType': 'earrow'});
		this.createButton(panCanvas,10,90,{x:16,y:16},{'actiontype':'O','name':'re-center','buttonType': ''});
		this.createButton(panCanvas,10,90,{x:2,y:16},{'actiontype':'W','name':'pan west','buttonType': 'warrow'});
		this.createButton(panCanvas,10,0,{x:16,y:30},{'actiontype':'S','name':'pan south','buttonType': 'sarrow'});			
		panCanvas.onmouseup = this._panzoomClickHandler;		

	},
	addRotatingActions: function(){
		
		var rotateCanvas = this._createcontrollercanvas(44,40);	
		this.createButton(rotateCanvas,10,180,{x:16,y:2},{'actiontype':'rotatezup','name':'pan north','buttonType': 'narrow'});
		this.createButton(rotateCanvas,10,0,{x:16,y:30},{'actiontype':'rotatezdown','name':'pan south','buttonType': 'sarrow'});			
			
		this.createButton(rotateCanvas,10,270,{x:30,y:16},{'actiontype':'rotatezright','name':'rotate to right','buttonType': 'earrow'});
		this.createButton(rotateCanvas,10,90,{x:2,y:16},{'actiontype':'rotatezleft','name':'rotate to left','buttonType': 'warrow'});
		rotateCanvas.onmouseup = this._panzoomClickHandler;

	},	
	addZoomingActions: function(){
		var zoomCanvas = this._createcontrollercanvas(20,30);

		var left = 14;
		var top = 50;
		zoomCanvas.style.left = left +"px";
		zoomCanvas.style.top = top + "px";
		this.createButton(zoomCanvas,10,180,{x:2,y:2},{'actiontype':'in','name':'zoom in','buttonType': 'plus'});		
		this.createButton(zoomCanvas,10,180,{x:2,y:16},{'actiontype':'out','name':'zoom out','buttonType': 'minus'});
		zoomCanvas.onmouseup = this._panzoomClickHandler;	
	},	
	
	setMaxScaling: function(max){
		this._maxscale = max;
	}
	,transform: function(){
		var t = this.transformation;
		var s = t.scale;
		var tr = t.translate;
		if(s.x <= 0) s.x = 0.1125;
		if(s.y <= 0) s.y = 0.1125;

		this.targetjs.transform(this.transformation);


	},
	_panzoomClickHandler: function(e) {
		
		if(!e) {
			e = window.event;
		}
		
		var controller = this.easyController;
	
		var hit = this.easyClicking.getShapeAtClick(e);	
		if(!hit) {
			return false;
		}
		if(!hit.properties) return false;
		
		var pan = {};
		var t =controller.transformation;
		//console.log(t.rotate,"hit");
		var scale =t.scale;
		pan.x = parseFloat(30 / scale.x);
		pan.y = parseFloat(30 / scale.y);

		if(!t.scale) t.scale = {x:1,y:1};
		if(!t.translate) t.translate = {x:0,y:0};
		if(!t.rotate) t.rotate = {x:0,y:0,z:0};

		switch(hit.properties.actiontype) {
			case "W":
				t.translate.x += pan.x;
				break;
			case "O":
				t.translate.x = 0;
				t.translate.y = 0;
				break;

			case "E":
				t.translate.x -= pan.x;
				break;
			case "N":
				t.translate.y += pan.y;
				break;
			case "S":
				t.translate.y -= pan.y;
				break;
			case "in":
				scale.x *= 2;
				scale.y *= 2;
				break;
			case "out":
				scale.x /= 2;
				scale.y /= 2;			
				break;
			case "rotatezright":
				if(!t.rotate.z) t.rotate.z = 0;
				//console.log("right",t.rotate.z);
				t.rotate.z -= 0.1;
				var left =6.28318531;
				
				if(t.rotate.z <0 )t.rotate.z =left;
				break;
			case "rotatezup":
				if(!t.rotate.y) t.rotate.y = 0;
				t.rotate.y += 0.1;
				break;
			case "rotatezdown":
				if(!t.rotate.y) t.rotate.y = 0;
				t.rotate.y -= 0.1;
				break;
			case "rotatezleft":
				if(!t.rotate.z) t.rotate.z = 0;
				t.rotate.z += 0.1;
				break;
			default:
				break;
		}
		controller.transform();

		return false;
	}
};//geojson should be handled here - maybe create from geojson

/*coordinates are a string consisting of floats and move commands (M)*/
var EasyShape = function(properties,coordinates,geojson){
	this.grid = {};
	this.coords = [];
	if(geojson){
		this._constructFromGeoJSONObject(properties,coordinates);
	}
	else{
		this._constructBasicShape(properties,coordinates);
	}

	this._iemultiplier = 1000; //since vml doesn't accept floats you have to define the precision of your points 100 means you can get float coordinates 0.01 and 0.04 but not 0.015 and 0.042 etc..
};
EasyShape.prototype={
	getBoundingBox: function(){ /* returns untransformed bounding box */
		return this.grid;
	}

	,render: function(canvas,transformation,projection,optimisations, browser){
		var optimisations = true;
		
		if(!transformation){
			transformation = {};
		}
		if(!transformation.origin)transformation.origin = {x:0,y:0};
		if(!transformation.scale)transformation.scale = {x:1,y:1};
		if(!transformation.translate)transformation.translate = {x:0,y:0};
		
		var frame = this._calculateVisibleArea(canvas,transformation);
		var shapetype = this.properties.shape;
		if(shapetype == 'point'){
			this._calculatePointCoordinates(transformation);
		} 
		else if(shapetype == 'path' || shapetype =='polygon'){
			
		}
		else{
			console.log("no idea how to render" +this.properties.shape+" must be polygon|path|point");
			return;
		}		
		//optimisations = false;
		if(!projection && optimisations){
			if(shapetype != 'point' && shapetype != 'path' && frame){ //check if worth drawing				
				if(!this._optimisation_shapeIsTooSmall(transformation)) {
					if(this.vml) this.vml.style.display = "none";
					return;	
				}
				if(!this._optimisation_shapeIsInVisibleArea(frame)){
					if(this.vml) this.vml.style.display = "none";
					return;	
				}	
			}
		}	

		if(this.vml) this.vml.style.display = '';
		
		if(!canvas.getContext) {
			//this has been taken from Google ExplorerCanvas
			if (!document.namespaces['easyShapeVml_']) {
			        document.namespaces.add('easyShapeVml_', 'urn:schemas-microsoft-com:vml');
			}

			  // Setup default CSS.  Only add one style sheet per document
			 if (!document.styleSheets['easyShape']) {
			        var ss = document.createStyleSheet();
			        ss.owningElement.id = 'easyShape';
			        ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
			            // default size is 300x150 in Gecko and Opera
			            'text-align:left;}' +
			            'easyShapeVml_\\:*{behavior:url(#default#VML)}';
			}
			
			this._ierender(canvas,transformation,projection,optimisations); 

	
		}
		else{
			this._canvasrender(canvas,transformation,projection,optimisations);

		}
		
	}
	
	,setCoordinates: function(coordinates){
		this.coords = coordinates;
		this.grid = {}; //an enclosing grid
		this._calculateBounds();
		if(this.vml) this.vml.path = false; //reset path so recalculation will occur
	}
	,getCoordinates: function(){
		return this.coords;
	}
	,_calculateBounds: function(coords){
		if(this.properties.shape == 'path'){
			this.grid = {x1:0,x2:1,y1:0,y2:1};
			return;
		}
		if(!coords) coords = this.coords;
		this.grid.x1 = coords[0];
		this.grid.y1 = coords[1];
		this.grid.x2 = coords[0];
		this.grid.y2 = coords[1];
		
		this._deltas = []
		var d = this._deltas;

		var lastX, lastY;
		var index = 0;
	
		lastX = coords[0];
		lastY = coords[1];
		for(var i=0; i < coords.length-1; i+=2){
			var xPos = parseFloat(coords[i]); //long
			var yPos = parseFloat(coords[i+1]); //lat
			var deltax =xPos - lastX;
			var deltay= yPos - lastY;
			if(deltax < 0) deltax = - deltax;
			if(deltay < 0) deltay = -deltay;
			d.push(deltax);
			d.push(deltay);
			if(xPos < this.grid.x1) this.grid.x1 = xPos;
			if(yPos < this.grid.y1) this.grid.y1 = yPos;	
			if(xPos > this.grid.x2) this.grid.x2 = xPos;
			if(yPos > this.grid.y2) this.grid.y2 = yPos;
			
			lastX = xPos;
			lastY = yPos;
		}
	}
	,_constructPointShape: function(properties,coordinates){
		var x = coordinates[0]; var y = coordinates[1];
		this.pointcoords = [x,y];
		var ps = 0.5;
		var newcoords =[x-ps,y-ps,x+ps,y-ps,x+ps,y+ps,x-ps, y+ps];
		this._constructPolygonShape(properties,newcoords);
	}
	
	,_constructPolygonShape: function(properties,coordinates){
		this.properties = properties;
		this.setCoordinates(coordinates);
		if(!properties.stroke)properties.stroke = '#000000';		
		if(properties.colour){
			properties.fill =  properties.colour;
		}
	}
	,_constructBasicShape: function(properties, coordinates){
		if(properties.shape == 'point'){
			this._constructPointShape(properties,coordinates);
		}
		else if(properties.shape == 'polygon' || properties.shape == 'path')
		{
			this._constructPolygonShape(properties,coordinates);
		}
		else{
			console.log("don't know how to construct basic shape " + properties.shape);
		}		
		
		
	}	
	
	 /*following 3 functions may be better in EasyMaps*/
	,_constructFromGeoJSONObject: function(properties,coordinates){
		if(properties.shape == 'polygon'){
			this._constructFromGeoJSONPolygon(properties,coordinates);	
		}
		else if(properties.shape == 'point'){
			this._constructPointShape(properties,coordinates);
		}
		else{
			console.log("don't know what to do with shape " + element.shape);
		}
	}
	,_constructFromGeoJSONPolygon: function(properties,coordinates){		
		var newcoords = this._convertGeoJSONCoords(coordinates[0]);
		this._constructBasicShape(properties,newcoords);
				//we ignore any holes in the polygon (for time being.. coords[1][0..n], coords[2][0..n])
	}	
	,_convertGeoJSONCoords: function(coords){
	//converts [[x1,y1], [x2,y2],...[xn,yn]] to [x1,y1,x2,y2..xn,yn]
		var res = [];
		if(!coords) return res;
		for(var i=0; i < coords.length; i++){
			//geojson says coords order should be longitude,latitude eg. 0,51 for London

			// longitude goes from -180 (W) to 180 (E), latitude from -90 (S) to 90 (N)
			// in our data, lat goes from 90 (S) to -90 (N), so we negate
			
			var x = coords[i][0];
			var y = - coords[i][1];
			
			//var y = -coords[i][0];
			//var x = coords[i][1];
			res.push(x);
			res.push(y);
		}

		return res;
	}	



	 /*RENDERING */
	,_canvasrender: function(canvas,transformation,projection,optimisations){
		var c;	
		var shapetype = this.properties.shape;	
		if(projection)
			c = this._applyProjection(projection,transformation);
		else
			c = this.coords;
		
		if(c.length == 0) return;
		
		/*var initialX,initialY;
		var start;
		if(c[0] == 'M'){//starts with an "M"
			initialX = parseFloat(c[1]);
			initialY = parseFloat(c[2]);
			start = 3;
		}
		else{
			initialX = parseFloat(c[0]);
			initialY = parseFloat(c[1]);
			start = 2;			
		}*/

		
		var threshold = 2;

		var ctx = canvas.getContext('2d');

		if(this.properties.lineWidth) ctx.lineWidth = this.properties.lineWidth;
		
		var o = transformation.origin;
		var tr = transformation.translate;
		var s = transformation.scale;
		var r = transformation.rotate;
		ctx.save();

		ctx.translate(o.x,o.y);
		ctx.scale(s.x,s.y);
		ctx.translate(tr.x,tr.y);
		//if(r && r.x)ctx.rotate(r.x,o.x,o.y);

		ctx.beginPath();
		
		//ctx.moveTo(initialX,initialY);

		var move = true;
		for(var i=0; i < c.length-1; i+=2){
			if(c[i]== "M") {
				i+= 1; 
				move=true;
			}
			var x = parseFloat(c[i]);
			var y = parseFloat(c[i+1]);	
			if(x == NaN || y == NaN){
				throw "error in EasyShape render: the coordinates for this EasyShape contain invalid numbers";
			}
			else{
				if(move){
					ctx.moveTo(x,y);
					
					//console.log("i found and moved to",x,y);
					move = false;
				}
				else{
					//console.log("line to", x,y);
					ctx.lineTo(x,y);
				}
			}
			
		}
		ctx.closePath();

		if(!this.properties.hidden) {
			ctx.strokeStyle = this.properties.stroke;
			if(typeof this.properties.fill == 'string') 
				fill = this.properties.fill;
			else
				fill = "#ffffff";

			
			ctx.stroke();
			if(shapetype != 'path') {
				ctx.fillStyle = fill;
				ctx.fill();
			}
		}
		ctx.restore();
	}
	,_createvmlpathstring: function(vml,transformation,projection){ //mr bottleneck
		if(!vml) return;
		var o = transformation.origin;
		var t = transformation.translate;
		var s = transformation.scale;
		var path;
		
		var buffer = [];
		
		if(projection){
			c = this._applyProjection(projection,transformation);
		}
		else{
			c = this.coords;
		}	
		if(c.length < 2) return;
		

		
		var x =o.x  + c[0];
		var y =o.y+c[1];		
		x *=this._iemultiplier;
		y *= this._iemultiplier;
		x = parseInt(x);
		y = parseInt(y);

		//path = "M";
		buffer.push("M");
		//path+= x + "," +y + " L";
		buffer.push([x,",",y," L"].join(""))
		var lineTo = true;
		for(var i =2; i < c.length; i+=2){
			if(c[i] == 'M') {
				//path += " M";
				buffer.push(" M");
				lineTo = false;
				i+=1;
			}
			else if(!lineTo) {
				//path += " L";
				buffer.push(" L");
				lineTo = true;
			}
			else if(lineTo){
				//path += " ";
				buffer.push(" ");
			}
			var x =o.x+c[i];
			var y =o.y+c[i+1];
			x *= this._iemultiplier;
			y *= this._iemultiplier;
			x = parseInt(x);
			y = parseInt(y);
			buffer.push([x,",",y].join(""));
			//path += x +"," + y;
			
			//if(i < c.length - 2) path += "";
		}
		//path += " XE";	
		buffer.push(" XE");
		//console.log(buffer.join(""));

	path = buffer.join("");
	//if(path != vml.getAttribute("path")){
		
		vml.setAttribute("path", path);	
//	}

	}

	,_cssTransform: function(vml,transformation,projection){
		var d1,d2,t;
		if(!vml) return;
	
		if(vml.tagName == 'shape' && (!vml.path || this.properties.shape =='point')) {
			//causes slow down..
			this._createvmlpathstring(vml,transformation,projection);
		//	this.vml.parentNode.replaceChild(clonedNode,this.vml);
		}

		var o = transformation.origin;
		var t = transformation.translate;
		var s = transformation.scale;
		if(!this.initialStyle) {
			var initTop = parseInt(vml.style.top);
			if(!initTop) initTop = 0;
			initTop += o.y;
			var initLeft = parseInt(vml.style.left);
			if(!initLeft) initLeft = 0;
			initLeft += o.x;
			var w =parseInt(vml.style.width);
			var h = parseInt(vml.style.height)
			this.initialStyle = {top: initTop, left: initLeft, width: w, height: h};
		}
		var scalingRequired = true;
		var translatingRequired = true;
		if(this._lastTransformation){
			if(s.x == this._lastTransformation.scale.x && s.y == this._lastTransformation.scale.y){			
				scalingRequired = false;
			}

		}

	
		var initialStyle= this.initialStyle;

		var style = vml.style;			
		var newtop,newleft;
		newtop = initialStyle.top;
		newleft = initialStyle.left;

		//scale
		if(scalingRequired){
			var newwidth = initialStyle.width * s.x;
			var newheight = initialStyle.height * s.y; 	
		}
		//translate into right place

		var temp;
		temp = (t.x - o.x);
		temp *= s.x;
		newleft += temp;

		temp = (t.y - o.y);
		temp *= s.x;
		newtop += temp;						

		style.left = newleft +"px";
		style.top = newtop +"px";
		
		if(scalingRequired){
			style.width = newwidth +"px";
			style.height = newheight + "px";
		}
		this._lastTransformation = {scale:{}};
		this._lastTransformation.scale.x = s.x;
		this._lastTransformation.scale.y = s.y;
	}	
	
	
	,_ierender: function(canvas,transformation,projection,optimisations,appendTo){
		var shape;
		if(this.vml){
			shape = this.vml;
		
			if(this.properties.fill && shapetype != 'path'){
				shape.filled = "t";
				shape.fillcolor = this.properties.fill;			
			}
			this._cssTransform(shape,transformation,projection);
			return;
		}
		else{
			shape = document.createElement("easyShapeVml_:shape");
			var o = transformation.origin;
			var t = transformation.translate;
			var s = transformation.scale;


			//path ="M 0,0 L50,0, 50,50, 0,50 X";
			var nclass= "easyShape";
			var shapetype =this.properties.shape;
			if(shapetype == 'path') nclass= "easyShapePath";
			shape.setAttribute("class", nclass);
			shape.style.height = canvas.height;
			shape.style.width = canvas.width;
			shape.style.position = "absolute";
			shape.style['z-index'] = 1;
			shape.stroked = "t";
			shape.strokecolor = "#000000";

			if(this.properties.fill && shapetype != 'path'){
				shape.filled = "t";
				shape.fillcolor = this.properties.fill;			
			}
			shape.strokeweight = ".75pt";

			var xspace = parseInt(canvas.width);
			xspace *=this._iemultiplier;
			var yspace =parseInt(canvas.height);
			yspace *= this._iemultiplier;
			coordsize = xspace +"," + yspace;

			shape.coordsize = coordsize;
			shape.easyShape = this;
			if(!appendTo){
				appendTo = canvas;
			}
			
			
			this._cssTransform(shape,transformation,projection);	
			this.vml = shape;
			appendTo.appendChild(shape);
		}
		
	
	}

	
	,_applyProjection: function(projection,transformation){
		var c = this.coords;
		if(!projection) return c;
		if(!projection.xy){
			return;
		}	
		if(projection.init) projection.init();
		var newc = [];
		for(var i=0; i < c.length-1; i+=2){
			var moved = false;
			if(c[i] == "M"){
				i+= 1;
			}
			var x = parseFloat(c[i]);
			var y = parseFloat(c[i+1]);
			
			var projectedCoordinate = projection.xy(c[i],c[i+1],transformation);
			newx= projectedCoordinate.x;
			newy= projectedCoordinate.y;
			
			if(projectedCoordinate.move){
				moved  =true;
			}
			

			cok = true;
			//check we haven't wrapped around world (For flat projections sss)
			
			if(!projection.nowrap){
				var diff;
				if(newx > x) diff = newx - x;
				if(x > newx) diff = x - newx;
				if(diff > 100) cok = false; //too extreme change
			}
			
			if(cok){
				if(typeof newx == 'number' && typeof newy =='number'){
					if(moved){
						newc.push("M");
					}
					newc.push(newx);
					newc.push(newy);
				}
	
			}
			
			
		}	


		this._tcoords = newc;
		this._calculateBounds(this._tcoords);
		return newc;
	}
	,_calculateVisibleArea: function(canvas,transformation){
		var left = 0,top = 0;
		var right =  parseInt(canvas.width) + left; 
		var bottom = parseInt(canvas.height) + top;
		var topleft =  EasyClickingUtils.undotransformation(left,top,transformation);
		var bottomright =  EasyClickingUtils.undotransformation(right,bottom,transformation);				
		var frame = {};
		frame.top = topleft.y;
		frame.bottom = bottomright.y;
		frame.right = bottomright.x;
		frame.left = topleft.x;
		return frame;
	}
	
	,_calculatePointCoordinates: function(transformation){
		if(!this.pointcoords) {
			this.pointcoords = [this.coords[0],this.coords[1]];
		}
		var x =parseFloat(this.pointcoords[0]);
		var y =parseFloat(this.pointcoords[1]);
		this.setCoordinates([x,y]);
		var ps = 5 / parseFloat(transformation.scale.x);
		//should get bigger with scale increasing
		var smallest = 1 / this._iemultiplier;
		var largest = 2.5 * transformation.scale.x;
		if(ps < smallest) ps = smallest;
		if(ps > largest) ps = largest;
		var newcoords =[[x-ps,y-ps],[x+ps,y-ps],[x+ps,y+ps],[x-ps, y+ps]];
		var c = this._convertGeoJSONCoords(newcoords);
		this.setCoordinates(c);
	}
	,_optimisation_shapeIsInVisibleArea: function(frame){
		var g = this.grid;
		if(g.x2 < frame.left) {
			return false;}
		if(g.y2 < frame.top) {
			return false;}
		if(g.x1 > frame.right){
			return false;
		}
		if(g.y1 > frame.bottom){
			return false;	
		}
		return true;
	}
	
	,_optimisation_shapeIsTooSmall: function(transformation,projection){
		var g = this.grid;
		var s = transformation.scale;
		var t1 = g.x2 -g.x1;
		var t2 =g.y2- g.y1;
		var delta = {x:t1,y:t2};
		delta.x *= s.x;
		delta.y *= s.y;
		var area = delta.x * delta.y;
		if(area < 40) 
		{return false;}//too small
		else
			return true;
	}
	
	/*
	render the shape using canvas ctx 
	using ctx and a given transformation in form {translate: {x:<num>, y:<num>}, scale:{translate: {x:<num>, y:<num>}}
	projection: a function that takes xy coordinates and spits out a new x and y
	in a given viewableArea 
	optimisations: boolean - apply optimisations if required
	*/
};
/*
EasyClicking adds the ability to associate a dom element with lots of EasyShapes using addToMemory function
The getShapeAtClick function allows click detection on this dom element when used in a dom mouse event handler
*/

// Depends on JQuery for offset function
// Get the current horizontal page scroll position
function findScrollX()
{
	return window.scrollX || document.documentElement.scrollLeft;
}
// Get the current vertical page scroll position
function findScrollY()
{
	return window.scrollY || document.documentElement.scrollTop;
}

/*Turn a dom element into one where you can find EasyShapes based on clicks */
var EasyClicking = function(element,easyShapesList){
	if(element.easyClicking) {
		var update = element.easyClicking;
		return update;
	}

	this.memory = [];
	element.easyClicking = this;
	if(easyShapesList) this.memory = easyShapesList;
	
	
};

EasyClicking.prototype = {
	setTransformation: function(transformation){
		if(transformation) this.transformation = transformation;	
	}
	,addToMemory: function(easyShape){
		if(!this.memory) this.memory = [];
		easyShape._easyClickingID = this.memory.length;
		this.memory.push(easyShape);
	}
	
	,clearMemory: function(){
		this.memory = [];
	},
	getMemory: function(){
		return this.memory;
	}
	,getMemoryID: function(easyShape){
		if(easyShape && easyShape._easyClickingID)
			return easyShape._easyClickingID;
		else{
			return false;
		}
	}
	,getShapeAtClick: function(e){
		if(!e) {
			e = window.event;
		}
		
		var node = EasyClickingUtils.resolveTarget(e);
		if(node.getAttribute("class") == 'easyShape') { //vml easyShape
			return node.easyShape;
		}
		var target = EasyClickingUtils.resolveTargetWithEasyClicking(e);
	
		if(!target) return;
		var offset = jQuery(target).offset();
	

		x = e.clientX + window.findScrollX() - offset.left;
		y = e.clientY + window.findScrollY() - offset.top;

		//counter any positioning
		//if(target.style.left) x -= parseInt(target.style.left);
		//if(target.style.top) y -= parseInt(target.style.top);

	
		//var memory = target.memory;
		//var transformation = target.transformation;
		//console.log('memory length: '+memory.length);
		if(this.memory.length > 0){
			var shape = false;
			if(target.easyClicking){
			shape = target.easyClicking.getShapeAtPosition(x,y);
			}
			return shape;
		} else{
			//console.log("no shapes in memory");
			//return false;
		}
	},
	getShapeAtPosition: function(x,y) {
		var shapes = this.memory;
		if(this.transformation){
			var pos =  EasyClickingUtils.undotransformation(x,y,this.transformation);
			x = pos.x;
			y = pos.y;
		
		}
		var hitShapes = [];
	
		for(var i=0; i < shapes.length; i++){
			var g = shapes[i].grid;
			if(x >= g.x1 && x <= g.x2 && y >=  g.y1 && y <=g.y2){
				hitShapes.push(shapes[i]);
			}
		}
		var res = this._findNeedleInHaystack(x,y,hitShapes);
		
		
		return res;
	},
	_findNeedleInHaystack: function(x,y,shapes){
		var hits = [];
		for(var i=0; i < shapes.length; i++){
			if(this._inPoly(x,y,shapes[i])) {
				hits.push(shapes[i]);
			}
		}

		if(hits.length == 0){
			return null;
		}
		else if(hits.length == 1) 
			return hits[0];
		else {//the click is in a polygon which is inside another polygon
		
			var g = hits[0].grid;
			var min = Math.min(g.x2 - x,x - g.x1,g.y2 - y,y - g.y1);
		
			var closerEdge = {id:0, closeness:min};
			for(var i=1; i < hits.length; i++){
				g = hits[i].grid;
			var min = Math.min(g.x2 - x,x - g.x1,g.y2 - y,y - g.y1);
			
				if(closerEdge.closeness > min) {
					closerEdge.id = i; closerEdge.closeness = min;
				}
				return hits[closerEdge.id];
			}
		
		}

	},                     
	_inPoly: function(x,y,poly) {
		/* _inPoly adapted from inpoly.c
		Copyright (c) 1995-1996 Galacticomm, Inc.  Freeware source code.
		http://www.visibone.com/inpoly/inpoly.c.txt */
		var coords;
		if(poly._tcoords){
			coords = poly._tcoords;
			//console.log("using tcoords",x,y,poly.coords.length,poly._tcoords.length);
		}
		else
			coords= poly.coords;
		var npoints = coords.length;
		if (npoints/2 < 3) {
			//points don't describe a polygon
			return false;
		}
		var inside = false;
		var xold = coords[npoints-2];
		var yold = coords[npoints-1];
		var x1,x2,y1,y2,xnew,ynew;
		for (var i=0; i<npoints; i+=2) {
			xnew=coords[i];
			ynew=coords[i+1];
			if (xnew > xold) {
				x1=xold;
				x2=xnew;
				y1=yold;
				y2=ynew;
			} else {
				x1=xnew;
				x2=xold;
				y1=ynew;
				y2=yold;
			}
			if ((xnew < x) == (x <= xold)
				&& (y-y1)*(x2-x1) < (y2-y1)*(x-x1)) {
				   inside=!inside;
				}
			xold=xnew;
			yold=ynew;
		 }
		 return inside;
	}

};


var EasyClickingUtils = {
	getRealXYFromMouse: function(e,t){
		var newpos =EasyClickingUtils.getMouseFromEvent(e);
		newpos = EasyClickingUtils.undotransformation(newpos.x,newpos.y,t);
		return newpos;
	}
	
	,undotransformation: function(x,y,transformation){ //porting to EasyTransformations?
	
		var pos = {};
		var t =transformation;
		var tr =t.translate;
		var s = t.scale;
		var o = t.origin;
		if(!x || !y) 
			return false;
		pos.x = x;
		pos.y = y;
	

		pos.x -= o.x;
		pos.y -= o.y;

		if(pos.x != 0)
			pos.x /= s.x;
		
		if(pos.y != 0)
			pos.y /= s.y;
			
		pos.x -= tr.x;
		pos.y -= tr.y;			
		return pos;
	}	
	,resolveTarget:function(e)
	{
		if(!e) e = window.event;
		var obj;
		if(e.target)
			obj = e.target;
		else if(e.srcElement)
			obj = e.srcElement;
		if(obj.nodeType == 3) // defeat Safari bug
			obj = obj.parentNode;
		return obj;
	}
	
	
	,getMouseFromEvent : function(e){
			if(!e) e = window.event;
			var target = this.resolveTargetWithEasyClicking(e);
			if(!target)return false;

			var offset = jQuery(target).offset();

			
			if(!offset.left) return false;
			x = e.clientX + window.findScrollX() - offset.left;
			y = e.clientY + window.findScrollY() - offset.top;
			return {'x':x, 'y':y};		
			
	}


	,resolveTargetWithEasyClicking: function(e)
	{
		var node = EasyClickingUtils.resolveTarget(e);
		var first = node;
		while(node && !node.easyClicking){
			node = node.parentNode;
		}
		if(!node) node = first;
		return node;
	}
	,getMouseFromEventRelativeToElement: function (e,x,y,target){
		if(!e) e = window.event;

		var offset = jQuery(target).offset();
		if(!offset.left) return false;
		
		oldx = e.clientX + window.findScrollX() - offset.left;
		oldy = e.clientY + window.findScrollY() - offset.top;
		var pos = {'x':oldx, 'y':oldy};

		if(!pos) return false;
		pos.x -= x;
		pos.y -= y;
		

		return pos;
		
	}

	,getMouseFromEventRelativeTo: function (e,x,y){
	
		var pos = this.getMouseFromEvent(e);
		if(!pos) return false;
		pos.x -= x;
		pos.y -= y;

		return pos;
	
	}
	,getMouseFromEventRelativeToCenter: function(e){
		var w,h;
		var target = this.resolveTargetWithEasyClicking(e);
		if(!target)return;
		if(target.style.width)
			w = parseInt(target.style.width);
		else if(target.width)
			w =parseInt(target.width);

		if(target.style.height)
			h = parseInt(target.style.height);
		else if(target.height)
			h = parseInt(target.height);
	
		if(!w || !h) throw "target has no width or height (easymaputils)";
	
		return this.getMouseFromEventRelativeTo(e,w/2,h/2);
	}	
	

};
[[TiddlyWiki]] - a reusable non-linear personal web notebook
http://www.tiddlywiki.com


/***
|''Name''|ToggleElementMacro|
|''Description''|toggles the visibility of the element specified|
|''Author''|FND|
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#ToggleElementMacro]]|
|''Version''|0.6|
|''Status''|@@experimental@@|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.1|
!Notes
This macro was created for use with the [[overflow technique|http://cleanlayout.tiddlyspot.com/#StyleSheet]] (cf. [[[twdev] StyleSheetLayout: overflow technique|http://groups.google.at/group/TiddlyWikiDev/browse_thread/thread/b55011665c5e04d9/]]).
!Usage
{{{
<<toggleElement
	[element ID]
	[button label]
	[button tooltip]
	[button class]
	[button access key]
	[startup mode]
>>
}}}
All parameters are optional.
If the last parameter is {{{"hide"}}}, the respective element will be hidden when the macro is first rendered.
In order to use the default value for a certain property, the respective parameter can either be omitted or defined as empty by using {{{""}}}.
!!Examples
|!Code|!Result|
|{{{<<toggleElement>>}}}| <<toggleElement>> |
|{{{<<toggleElement "mainMenu" "Toggle MainMenu" "" "tiddlyLinkExisting">>}}}| <<toggleElement "mainMenu" "Toggle MainMenu" "" "tiddlyLinkExisting">> |
|{{{<<toggleElement "mainMenu" "Toggle MainMenu" "" "" "" "hide">>}}}| <<toggleElement "mainMenu" "Toggle MainMenu" "" "" "" "hide">> |
!Revision History
!!v0.5 (2007-09-22)
* initial proof-of-concept implementation
!!v0.6 (2007-11-11)
* added parameter for hiding element by default
* renamed to [[ToggleElementMacro]] (from [[ToggleElementPlugin]])
!To Do
* use named parameters
* documentation (esp. parameters)
* separate button labels depending on element's toggle state
* add animations (using [[AnimationsLibrary]]; cf. [[ToggleElementPlugin (animated)]])
!Code
***/
//{{{
config.macros.toggleElement = {
	elementID: "sidebar",
	label: "Toggle Sidebar",
	prompt: "Switch sidebar on and off",
	buttonClass: "",
	accessKey: ""
};

config.macros.toggleElement.handler = function(place, macroName, params) {
	// process command line parameters
	var elementID = params[0] || this.elementID;
	var label = params[1] || this.label;
	var prompt = params[2] || this.prompt;
	var buttonClass = params[3] || this.buttonClass;
	var accessKey = params[4] || this.accessKey;
	// startup mode
	if(params[5] == "hide") {
		this.toggle(elementID);
	}
	// create toggle button
	createTiddlyButton(place, label, prompt,
		function() { config.macros.toggleElement.toggle(elementID); },
		buttonClass, null, accessKey);
};

config.macros.toggleElement.toggle = function(id) {
	var e = document.getElementById(id);
	if(e) {
		if(e.style.display != "none") {
			e.style.display = "none";
		} else {
			e.style.display = "";
		}
	}
};
//}}}
/%
|Name|ToggleRightSidebar|
|Source|http://www.TiddlyTools.com/#ToggleRightSidebar|
|Version|1.0.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|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|show/hide right sidebar (SideBarOptions)|

Usage: <<tiddler ToggleRightSidebar>>

Config settings:
	config.options.txtToggleRightSideBarLabelShow (◄)
	config.options.txtToggleRightSideBarLabelHide (►)
	config.options.txtToggleRightSideBarTipShow ("show right sidebar")
	config.options.txtToggleRightSideBarTipHide ("hide right sidebar")

%/<script label="show/hide right sidebar">
	var sb=document.getElementById('sidebar'); if (!sb) return;
	var show=sb.style.display=='none';
	if (!show) { sb.style.display='none'; var margin='1em'; }
	else { sb.style.display='block'; var margin=config.options.txtDisplayAreaRightMargin||''; }
	if (typeof(place)!='undefined') {
		place.innerHTML=show?
			config.options.txtToggleRightSideBarLabelHide:config.options.txtToggleRightSideBarLabelShow;
		place.title=show?
			config.options.txtToggleRightSideBarTipHide:config.options.txtToggleRightSideBarTipShow;
	}
	document.getElementById('displayArea').style.marginRight=margin;
	config.options.chkShowRightSidebar=show;
	saveOptionCookie('chkShowRightSidebar');
	var sm=document.getElementById('storyMenu'); if (sm) config.refreshers.content(sm);
	return false;
</script><script>
	if (config.options.chkShowRightSidebar==undefined)
		config.options.chkShowRightSidebar=true;
	if (!config.options.txtDisplayAreaRightMargin||!config.options.txtDisplayAreaRightMargin.length)
		config.options.txtDisplayAreaRightMargin="18em";
	if (config.options.txtToggleRightSideBarLabelShow==undefined)
		config.options.txtToggleRightSideBarLabelShow=config.browser.isSafari?"&#x25c0;":"&#x25c4;";
	if (config.options.txtToggleRightSideBarLabelHide==undefined)
		config.options.txtToggleRightSideBarLabelHide="&#x25ba;";
	if (config.options.txtToggleRightSideBarTipShow==undefined)
		config.options.txtToggleRightSideBarTipShow="show right sidebar";
	if (config.options.txtToggleRightSideBarTipHide==undefined)
		config.options.txtToggleRightSideBarTipHide="hide right sidebar";

	var show=config.options.chkShowRightSidebar;
	document.getElementById('sidebar').style.display=show?"block":"none";
	document.getElementById('displayArea').style.marginRight=show?
		config.options.txtDisplayAreaRightMargin:"1em";
	place.lastChild.innerHTML=show?
		config.options.txtToggleRightSideBarLabelHide:config.options.txtToggleRightSideBarLabelShow;
	place.lastChild.title=show?
		config.options.txtToggleRightSideBarTipHide:config.options.txtToggleRightSideBarTipShow;
	place.lastChild.style.fontWeight="normal";
</script>
/***
|Name:|ToggleTagPlugin|
|Description:|Makes a checkbox which toggles a tag in a tiddler|
|Version:|3.1.0a|
|Date:|27-Jun-2011|
|Source:|http://mptw.tiddlyspot.com/#ToggleTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
{{{<<toggleTag }}}//{{{TagName TiddlerName LabelText}}}//{{{>>}}}
* TagName - the tag to be toggled, default value "checked"
* TiddlerName - the tiddler to toggle the tag in, default value the current tiddler
* LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}'
(If a parameter is '.' then the default will be used)
* TouchMod flag - if non empty then touch the tiddlers mod date. Note, can set config.toggleTagAlwaysTouchModDate to always touch mod date
!!Examples
|Code|Description|Example|h
|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|
|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|
|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|
|{{{<<toggleTag TagName TiddlerName 'click me'>>}}}|Same but with custom label|<<toggleTag TagName TiddlerName 'click me'>>|
|{{{<<toggleTag . . 'click me'>>}}}|dot means use default value|<<toggleTag . . 'click me'>>|
!!Notes
* If TiddlerName doesn't exist it will be silently created
* Set label to '-' to specify no label
* See also http://mgtd-alpha.tiddlyspot.com/#ToggleTag2
!!Known issues
* Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing
* Should convert to use named params
***/
//{{{

if (config.toggleTagAlwaysTouchModDate == undefined) config.toggleTagAlwaysTouchModDate = false;

merge(config.macros,{

  toggleTag: {

    createIfRequired: true,
    shortLabel: "[[%0]]",
    longLabel: "[[%0]] [[%1]]",

    handler: function(place,macroName,params,wikifier,paramString,tiddler) {
      var tiddlerTitle = tiddler ? tiddler.title : '';
      var tag   = (params[0] && params[0] != '.') ? params[0] : "checked";
      var title = (params[1] && params[1] != '.') ? params[1] : tiddlerTitle;
      var defaultLabel = (title == tiddlerTitle ? this.shortLabel : this.longLabel);
      var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel;
      var touchMod = (params[3] && params[3] != '.') ? params[3] : "";
      label = (label == '-' ? '' : label); // dash means no label
      var theTiddler = (title == tiddlerTitle ? tiddler : store.getTiddler(title));
      var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) {
        if (!store.tiddlerExists(title)) {
          if (config.macros.toggleTag.createIfRequired) {
            var content = store.getTiddlerText(title); // just in case it's a shadow
            store.saveTiddler(title,title,content?content:"",config.options.txtUserName,new Date(),null);
          }
          else
            return false;
        }
        if ((touchMod != "" || config.toggleTagAlwaysTouchModDate) && theTiddler)
            theTiddler.modified = new Date();
        store.setTiddlerTag(title,this.checked,tag);
        return true;
      });
    }
  }
});

//}}}

|~ViewToolbar|closeTiddler closeOthers +editTiddler > fields syncing permalink references jump <|
|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|
<<browse "YAPC EUROPE RIGA" "http://translate.google.ru/?hl=ru&tab=wT" "100%" "500px">>
/***
Required by Tiddlyspot
***/
//{{{

config.options.chkHttpReadOnly = false; // make it so you can by default see edit controls via http

if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false; // disable autosave in d3

config.tiddlyspotSiteId = 'devpad';

// probably will need to redo this for TW 2.2
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[Welcome to Tiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[Welcome to Tiddlyspot]] ");
}

merge(config.shadowTiddlers,{

'Welcome to Tiddlyspot':[
 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki Guides|http://tiddlywikiguides.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),

'TspotControls':[
 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<<br>>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[announcements|http://announce.tiddlyspot.com/]], [[blog|http://tiddlyspot.com/blog/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),

'TspotSidebar':[
 "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),

'TspotOptions':[
 "tiddlyspot password:",
 "<<option pasUploadPassword>>",
 ""
].join("\n")

});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin | Ok |
| 10/1/2008 18:46:1 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 10/1/2008 18:52:39 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 10/1/2008 18:59:27 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |
| 10/1/2008 19:5:36 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 7/2/2008 16:37:2 | FND | [[/|http://devpad.tiddlyspot.com/#DcTableOfContentsPlugin]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 8/2/2008 23:32:5 | FND | [[/|http://devpad.tiddlyspot.com/#EvalMacro]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 10/2/2008 14:54:35 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 31/3/2008 8:16:25 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 18/4/2008 11:34:40 | FND | [[/|http://devpad.tiddlyspot.com/#EvalMacro]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 12/5/2008 14:22:20 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 30/5/2008 22:5:44 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 1/6/2008 3:35:5 | FND | [[/|http://devpad.tiddlyspot.com/#ConditionalTableFormattingMacro]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 16/7/2008 14:50:40 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 16/7/2008 14:51:19 | FND | [[/|http://devpad.tiddlyspot.com/#SearchTagPlugin]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 19/8/2008 15:59:49 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |
| 19/8/2008 16:11:27 | FND | [[/|http://devpad.tiddlyspot.com/#SimpleSearchPlugin]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 26/8/2008 13:26:43 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 15/10/2008 12:59:28 | FND | [[/|http://devpad.tiddlyspot.com/#DcTableOfContentsPlugin]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 29/10/2008 8:56:10 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 31/10/2008 16:28:9 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 4/11/2008 16:58:52 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 5/11/2008 13:2:29 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 26/11/2008 9:47:48 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 4/12/2008 15:39:45 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 6/12/2008 18:25:34 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |
| 6/12/2008 18:26:27 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 6/12/2008 18:33:5 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 25/1/2009 21:50:27 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 25/1/2009 21:51:26 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 19/3/2009 11:23:4 | FND | [[/|http://devpad.tiddlyspot.com/#eMailMacro%20templatesTest%20TagNavigatorTest%20SimpleCommentsTest%20TiddlerToCTest]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 6/5/2009 16:15:9 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 6/5/2009 18:56:0 | FND | [[/|http://devpad.tiddlyspot.com/#CommentsFormatter]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |
| 6/5/2009 18:56:31 | FND | [[/|http://devpad.tiddlyspot.com/#CommentsFormatter]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 6/5/2009 20:32:22 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 7/5/2009 16:24:12 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 8/7/2009 10:45:16 | FND | [[/|http://devpad.tiddlyspot.com/]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
| 9/2/2010 17:51:1 | FND | [[/|http://devpad.tiddlyspot.com/#SimpleSearchPlugin%20templatesTest%20TagNavigatorTest%20SimpleCommentsTest%20TiddlerToCTest]] | [[store.cgi|http://devpad.tiddlyspot.com/store.cgi]] | . | index.html | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|3.4.5|
|''Date:''|Oct 15, 2006|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadDoc|
|''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.0.0|
|''Browser:''|Firefox 1.5; InternetExplorer 6.0; Safari|
|''Include:''|config.lib.file; config.lib.log; config.lib.options; PasswordTweak|
|''Require:''|[[UploadService|http://tiddlywiki.bidix.info/#UploadService]]|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 3, minor: 4, revision: 5, 
	date: new Date(2006,9,15),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	documentation: 'http://tiddlywiki.bidix.info/#UploadDoc',
	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.0.0',
	browser: 'Firefox 1.5; InternetExplorer 6.0; Safari'
};
//}}}

////+++!![config.lib.file]

//{{{
if (!config.lib) config.lib = {};
if (!config.lib.file) config.lib.file= {
	author: 'BidiX',
	version: {major: 0, minor: 1, revision: 0}, 
	date: new Date(2006,3,9)
};
config.lib.file.dirname = function (filePath) {
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(0, lastpos);
	} else {
		return filePath.substring(0, filePath.lastIndexOf("\\"));
	}
};
config.lib.file.basename = function (filePath) {
	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);
};
window.basename = function() {return "@@deprecated@@";};
//}}}
////===

////+++!![config.lib.log]

//{{{
if (!config.lib) config.lib = {};
if (!config.lib.log) config.lib.log= {
	author: 'BidiX',
	version: {major: 0, minor: 1, revision: 1}, 
	date: new Date(2006,8,19)
};
config.lib.Log = function(tiddlerTitle, logHeader) {
	if (version.major < 2)
		this.tiddler = store.tiddlers[tiddlerTitle];
	else
		this.tiddler = store.getTiddler(tiddlerTitle);
	if (!this.tiddler) {
		this.tiddler = new Tiddler();
		this.tiddler.title = tiddlerTitle;
		this.tiddler.text = "| !date | !user | !location |" + logHeader;
		this.tiddler.created = new Date();
		this.tiddler.modifier = config.options.txtUserName;
		this.tiddler.modified = new Date();
	if (version.major < 2)
		store.tiddlers[tiddlerTitle] = this.tiddler;
	else
		store.addTiddler(this.tiddler);
	}
	return this;
};

config.lib.Log.prototype.newLine = function (line) {
	var now = new Date();
	var newText = "| ";
	newText += now.getDate()+"/"+(now.getMonth()+1)+"/"+now.getFullYear() + " ";
	newText += now.getHours()+":"+now.getMinutes()+":"+now.getSeconds()+" | ";
	newText += config.options.txtUserName + " | ";
	var location = document.location.toString();
	var filename = config.lib.file.basename(location);
	if (!filename) filename = '/';
	newText += "[["+filename+"|"+location + "]] |";
	this.tiddler.text = this.tiddler.text + "\n" + newText;
	this.addToLine(line);
};

config.lib.Log.prototype.addToLine = function (text) {
	this.tiddler.text = this.tiddler.text + text;
	this.tiddler.modifier = config.options.txtUserName;
	this.tiddler.modified = new Date();
	if (version.major < 2)
	store.tiddlers[this.tiddler.tittle] = this.tiddler;
	else {
		store.addTiddler(this.tiddler);
		story.refreshTiddler(this.tiddler.title);
		store.notify(this.tiddler.title, true);
	}
	if (version.major < 2)
		store.notifyAll(); 
};
//}}}
////===

////+++!![config.lib.options]

//{{{
if (!config.lib) config.lib = {};
if (!config.lib.options) config.lib.options = {
	author: 'BidiX',
	version: {major: 0, minor: 1, revision: 0}, 
	date: new Date(2006,3,9)
};

config.lib.options.init = function (name, defaultValue) {
	if (!config.options[name]) {
		config.options[name] = defaultValue;
		saveOptionCookie(name);
	}
};
//}}}
////===

////+++!![PasswordTweak]

//{{{
version.extensions.PasswordTweak = {
	major: 1, minor: 0, revision: 3, date: new Date(2006,8,30),
	type: 'tweak',
	source: 'http://tiddlywiki.bidix.info/#PasswordTweak'
};
//}}}
/***
!!config.macros.option
***/
//{{{
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordType = "password"; // password | text

config.macros.option.onChangeOption = function(e)
{
	var opt = this.getAttribute("option");
	var elementType,valueField;
	if(opt) {
		switch(opt.substr(0,3)) {
			case "txt":
				elementType = "input";
				valueField = "value";
				break;
			case "pas":
				elementType = "input";
				valueField = "value";
				break;
			case "chk":
				elementType = "input";
				valueField = "checked";
				break;
		}
		config.options[opt] = this[valueField];
		saveOptionCookie(opt);
		var nodes = document.getElementsByTagName(elementType);
		for(var t=0; t<nodes.length; t++) 
			{
			var optNode = nodes[t].getAttribute("option");
			if (opt == optNode) 
				nodes[t][valueField] = this[valueField];
			}
		}
	return(true);
};

config.macros.option.handler = function(place,macroName,params)
{
    var opt = params[0];
    if(config.options[opt] === undefined) {
        return;}
    var c;
    switch(opt.substr(0,3)) {
		case "txt":
			c = document.createElement("input");
			c.onkeyup = this.onChangeOption;
			c.setAttribute ("option",opt);
			c.className = "txtOptionInput "+opt;
			place.appendChild(c);
			c.value = config.options[opt];
			break;
		case "pas":
			// input password
			c = document.createElement ("input");
			c.setAttribute("type",config.macros.option.passwordType);
			c.onkeyup = this.onChangeOption;
			c.setAttribute("option",opt);
			c.className = "pasOptionInput "+opt;
			place.appendChild(c);
			c.value = config.options[opt];
			// checkbox link with this password "save this password on this computer"
			c = document.createElement("input");
			c.setAttribute("type","checkbox");
			c.onclick = this.onChangeOption;
			c.setAttribute("option","chk"+opt);
			c.className = "chkOptionInput "+opt;
			place.appendChild(c);
			c.checked = config.options["chk"+opt];
			// text savePasswordCheckboxLabel
			place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
			break;
		case "chk":
			c = document.createElement("input");
			c.setAttribute("type","checkbox");
			c.onclick = this.onChangeOption;
			c.setAttribute("option",opt);
			c.className = "chkOptionInput "+opt;
			place.appendChild(c);
			c.checked = config.options[opt];
			break;
	}
};
//}}}
/***
!! Option cookie stuff
***/
//{{{
window.loadOptionsCookie_orig_PasswordTweak = window.loadOptionsCookie;
window.loadOptionsCookie = function()
{
	var cookies = document.cookie.split(";");
	for(var c=0; c<cookies.length; c++) {
		var p = cookies[c].indexOf("=");
		if(p != -1) {
			var name = cookies[c].substr(0,p).trim();
			var value = cookies[c].substr(p+1).trim();
			switch(name.substr(0,3)) {
				case "txt":
					config.options[name] = unescape(value);
					break;
				case "pas":
					config.options[name] = unescape(value);
					break;
				case "chk":
					config.options[name] = value == "true";
					break;
			}
		}
	}
};

window.saveOptionCookie_orig_PasswordTweak = window.saveOptionCookie;
window.saveOptionCookie = function(name)
{
	var c = name + "=";
	switch(name.substr(0,3)) {
		case "txt":
			c += escape(config.options[name].toString());
			break;
		case "chk":
			c += config.options[name] ? "true" : "false";
			// is there an option link with this chk ?
			if (config.options[name.substr(3)]) {
				saveOptionCookie(name.substr(3));
			}
			break;
		case "pas":
			if (config.options["chk"+name]) {
				c += escape(config.options[name].toString());
			} else {
				c += "";
			}
			break;
	}
	c += "; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";
	document.cookie = c;
};
//}}}
/***
!! Initializations
***/
//{{{
// define config.options.pasPassword
if (!config.options.pasPassword) {
	config.options.pasPassword = 'defaultPassword';
	window.saveOptionCookie('pasPassword');
}
// since loadCookies is first called befor password definition
// we need to reload cookies
window.loadOptionsCookie();
//}}}
////===

////+++!![config.macros.upload]

//{{{
config.macros.upload = {
	accessKey: "U",
	formName: "UploadPlugin",
	contentType: "text/html;charset=UTF-8",
	defaultStoreScript: "store.php"
};

// only this two configs need to be translated
config.macros.upload.messages = {
	aboutToUpload: "About to upload TiddlyWiki to %0",
	backupFileStored: "Previous file backuped in %0",
	crossDomain: "Certainly a cross-domain isue: access to an other site isn't allowed",
	errorDownloading: "Error downloading",
	errorUploadingContent: "Error uploading content",
	fileLocked: "Files is locked: You are not allowed to Upload",
	fileNotFound: "file to upload not found",
	fileNotUploaded: "File %0 NOT uploaded",
	mainFileUploaded: "Main TiddlyWiki file uploaded to %0",
	passwordEmpty: "Unable to upload, your password is empty",
	urlParamMissing: "url param missing",
	rssFileNotUploaded: "RssFile %0 NOT uploaded",
	rssFileUploaded: "Rss File uploaded to %0"
};

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.handler = function(place,macroName,params){
	// parameters initialization
	var storeUrl = params[0];
	var toFilename = params[1];
	var backupDir = params[2];
	var uploadDir = params[3];
	var username = params[4];
	var password; // for security reason no password as macro parameter
	var label;
	if (document.location.toString().substr(0,4) == "http")
		label = this.label.saveLabel;
	else
		label = this.label.uploadLabel;
	var prompt;
	if (storeUrl) {
		prompt = this.label.promptParamMacro.toString().format([this.toDirUrl(storeUrl, uploadDir, username)]);
	}
	else {
		prompt = this.label.promptOption;
	}
	createTiddlyButton(place, label, prompt, 
						function () {
							config.macros.upload.upload(storeUrl, toFilename, uploadDir, backupDir, username, password); 
							return false;}, 
						null, null, this.accessKey);
};
config.macros.upload.UploadLog = function() {
	return new config.lib.Log('UploadLog', " !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |" );
};
config.macros.upload.UploadLog.prototype = config.lib.Log.prototype;
config.macros.upload.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {
	var line = " [[" + config.lib.file.basename(storeUrl) + "|" + storeUrl + "]] | ";
	line += uploadDir + " | " + toFilename + " | " + backupDir + " |";
	this.newLine(line);
};
config.macros.upload.UploadLog.prototype.endUpload = function() {
	this.addToLine(" Ok |");
};
config.macros.upload.basename = config.lib.file.basename;
config.macros.upload.dirname = config.lib.file.dirname;
config.macros.upload.toRootUrl = function (storeUrl, username)
{
	return root = (this.dirname(storeUrl)?this.dirname(storeUrl):this.dirname(document.location.toString()));
}
config.macros.upload.toDirUrl = function (storeUrl,  uploadDir, username)
{
	var root = this.toRootUrl(storeUrl, username);
	if (uploadDir && uploadDir != '.')
		root = root + '/' + uploadDir;
	return root;
}
config.macros.upload.toFileUrl = function (storeUrl, toFilename,  uploadDir, username)
{
	return this.toDirUrl(storeUrl, uploadDir, username) + '/' + toFilename;
}
config.macros.upload.upload = function(storeUrl, toFilename, uploadDir, backupDir, username, password)
{
	// parameters initialization
	storeUrl = (storeUrl ? storeUrl : config.options.txtUploadStoreUrl);
	toFilename = (toFilename ? toFilename : config.options.txtUploadFilename);
	backupDir = (backupDir ? backupDir : config.options.txtUploadBackupDir);
	uploadDir = (uploadDir ? uploadDir : config.options.txtUploadDir);
	username = (username ? username : config.options.txtUploadUserName);
	password = config.options.pasUploadPassword; // for security reason no password as macro parameter
	if (!password || password === '') {
		alert(config.macros.upload.messages.passwordEmpty);
		return;
	}
	if (storeUrl === '') {
		storeUrl = config.macros.upload.defaultStoreScript;
	}
	if (config.lib.file.dirname(storeUrl) === '') {
		storeUrl = config.lib.file.dirname(document.location.toString())+'/'+storeUrl;
	}
	if (toFilename === '') {
		toFilename = config.lib.file.basename(document.location.toString());
	}

	clearMessage();
	// only for forcing the message to display
	 if (version.major < 2)
		store.notifyAll();
	if (!storeUrl) {
		alert(config.macros.upload.messages.urlParamMissing);
		return;
	}
	// Check that file is not locked
	if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {
		if (BidiX.GroupAuthoring.lock.isLocked() && !BidiX.GroupAuthoring.lock.isMyLock()) {
			alert(config.macros.upload.messages.fileLocked);
			return;
		}
	}
	
	var log = new this.UploadLog();
	log.startUpload(storeUrl, toFilename, uploadDir,  backupDir);
	if (document.location.toString().substr(0,5) == "file:") {
		saveChanges();
	}
	var toDir = config.macros.upload.toDirUrl(storeUrl, toFilename, uploadDir, username);
	displayMessage(config.macros.upload.messages.aboutToUpload.format([toDir]), toDir);
	this.uploadChanges(storeUrl, toFilename, uploadDir, backupDir, username, password);
	if(config.options.chkGenerateAnRssFeed) {
		//var rssContent = convertUnicodeToUTF8(generateRss());
		var rssContent = generateRss();
		var rssPath = toFilename.substr(0,toFilename.lastIndexOf(".")) + ".xml";
		this.uploadContent(rssContent, storeUrl, rssPath, uploadDir, '', username, password, 
			function (responseText) {
				if (responseText.substring(0,1) != '0') {
					displayMessage(config.macros.upload.messages.rssFileNotUploaded.format([rssPath]));
				}
				else {
					var toFileUrl = config.macros.upload.toFileUrl(storeUrl, rssPath, uploadDir, username);
					displayMessage(config.macros.upload.messages.rssFileUploaded.format(
						[toFileUrl]), toFileUrl);
				}
				// for debugging store.php uncomment last line
				//DEBUG alert(responseText);
			});
	}
	return;
};

config.macros.upload.uploadChanges = function(storeUrl, toFilename, uploadDir, backupDir, 
		username, password) {
	var original;
	if (document.location.toString().substr(0,4) == "http") {
		original =  this.download(storeUrl, toFilename, uploadDir, backupDir, username, password);
		return;
	}
	else {
		// standard way : Local file
		
		original = loadFile(getLocalPath(document.location.toString()));
		if(window.Components) {
			// it's a mozilla browser
			try {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
									.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
				converter.charset = "UTF-8";
				original = converter.ConvertToUnicode(original);
			}
			catch(e) {
			}
		}
	}
	//DEBUG alert(original);
	this.uploadChangesFrom(original, storeUrl, toFilename, uploadDir, backupDir, 
		username, password);
};

config.macros.upload.uploadChangesFrom = function(original, storeUrl, toFilename, uploadDir, backupDir, 
		username, password) {
	var startSaveArea = '<div id="' + 'storeArea">'; // Split up into two so that indexOf() of this source doesn't find it
	var endSaveArea = '</d' + 'iv>';
	// Locate the storeArea div's
	var posOpeningDiv = original.indexOf(startSaveArea);
	var posClosingDiv = original.lastIndexOf(endSaveArea);
	if((posOpeningDiv == -1) || (posClosingDiv == -1))
		{
		alert(config.messages.invalidFileError.format([document.location.toString()]));
		return;
		}
	var revised = original.substr(0,posOpeningDiv + startSaveArea.length) + 
				allTiddlersAsHtml() + "\n\t\t" +
				original.substr(posClosingDiv);
	var newSiteTitle;
	if(version.major < 2){
		newSiteTitle = (getElementText("siteTitle") + " - " + getElementText("siteSubtitle")).htmlEncode();
	} else {
		newSiteTitle = (wikifyPlain ("SiteTitle") + " - " + wikifyPlain ("SiteSubtitle")).htmlEncode();
	}

	revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
	revised = revised.replaceChunk("<!--PRE-HEAD-START--"+">","<!--PRE-HEAD-END--"+">","\n" + store.getTiddlerText("MarkupPreHead","") + "\n");
	revised = revised.replaceChunk("<!--POST-HEAD-START--"+">","<!--POST-HEAD-END--"+">","\n" + store.getTiddlerText("MarkupPostHead","") + "\n");
	revised = revised.replaceChunk("<!--PRE-BODY-START--"+">","<!--PRE-BODY-END--"+">","\n" + store.getTiddlerText("MarkupPreBody","") + "\n");
	revised = revised.replaceChunk("<!--POST-BODY-START--"+">","<!--POST-BODY-END--"+">","\n" + store.getTiddlerText("MarkupPostBody","") + "\n");

	var response = this.uploadContent(revised, storeUrl, toFilename, uploadDir, backupDir, 
		username, password, function (responseText) {
					if (responseText.substring(0,1) != '0') {
						alert(responseText);
						displayMessage(config.macros.upload.messages.fileNotUploaded.format([getLocalPath(document.location.toString())]));
					}
					else {
						if (uploadDir !== '') {
							toFilename = uploadDir + "/" + config.macros.upload.basename(toFilename);
						} else {
							toFilename = config.macros.upload.basename(toFilename);
						}
						var toFileUrl = config.macros.upload.toFileUrl(storeUrl, toFilename, uploadDir, username);
						if (responseText.indexOf("destfile:") > 0) {
							var destfile = responseText.substring(responseText.indexOf("destfile:")+9, 
							responseText.indexOf("\n", responseText.indexOf("destfile:")));
							toFileUrl = config.macros.upload.toRootUrl(storeUrl, username) + '/' + destfile;
						}
						else {
							toFileUrl = config.macros.upload.toFileUrl(storeUrl, toFilename, uploadDir, username);
						}
						displayMessage(config.macros.upload.messages.mainFileUploaded.format(
							[toFileUrl]), toFileUrl);
						if (backupDir && responseText.indexOf("backupfile:") > 0) {
							var backupFile = responseText.substring(responseText.indexOf("backupfile:")+11, 
							responseText.indexOf("\n", responseText.indexOf("backupfile:")));
							toBackupUrl = config.macros.upload.toRootUrl(storeUrl, username) + '/' + backupFile;
							displayMessage(config.macros.upload.messages.backupFileStored.format(
								[toBackupUrl]), toBackupUrl);
						}
						var log = new config.macros.upload.UploadLog();
						log.endUpload();
						store.setDirty(false);
						// erase local lock
						if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {
							BidiX.GroupAuthoring.lock.eraseLock();
							// change mtime with new mtime after upload
							var mtime = responseText.substr(responseText.indexOf("mtime:")+6);
							BidiX.GroupAuthoring.lock.mtime = mtime;
						}
						
						
					}
					// for debugging store.php uncomment last line
					//DEBUG alert(responseText);
				}
			);
};

config.macros.upload.uploadContent = function(content, storeUrl, toFilename, uploadDir, backupDir, 
		username, password, callbackFn) {
	var boundary = "---------------------------"+"AaB03x";		
	var request;
	try {
		request = new XMLHttpRequest();
		} 
	catch (e) { 
		request = new ActiveXObject("Msxml2.XMLHTTP"); 
		}
	if (window.netscape){
			try {
				if (document.location.toString().substr(0,4) != "http") {
					netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');}
			}
			catch (e) {}
		}		
	//DEBUG alert("user["+config.options.txtUploadUserName+"] password[" + config.options.pasUploadPassword + "]");
	// compose headers data
	var sheader = "";
	sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
	sheader += config.macros.upload.formName +"\"\r\n\r\n";
	sheader += "backupDir="+backupDir
				+";user=" + username 
				+";password=" + password
				+";uploaddir=" + uploadDir;
	// add lock attributes to sheader
	if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {
		var l = BidiX.GroupAuthoring.lock.myLock;
		sheader += ";lockuser=" + l.user
				+ ";mtime=" + l.mtime
				+ ";locktime=" + l.locktime;
	}
	sheader += ";;\r\n"; 
	sheader += "\r\n" + "--" + boundary + "\r\n";
	sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+toFilename+"\"\r\n";
	sheader += "Content-Type: " + config.macros.upload.contentType + "\r\n";
	sheader += "Content-Length: " + content.length + "\r\n\r\n";
	// compose trailer data
	var strailer = new String();
	strailer = "\r\n--" + boundary + "--\r\n";
	//strailer = "--" + boundary + "--\r\n";
	var data;
	data = sheader + content + strailer;
	//request.open("POST", storeUrl, true, username, password);
	try {
		request.open("POST", storeUrl, true);		
	}
	catch(e) {
		alert(config.macros.upload.messages.crossDomain + "\nError:" +e);
		exit;
	}
	request.onreadystatechange = function () {
				if (request.readyState == 4) {
				     if (request.status == 200)
						callbackFn(request.responseText);
					else
						alert(config.macros.upload.messages.errorUploadingContent + "\nStatus: "+request.status.statusText);
				}
		};
	request.setRequestHeader("Content-Length",data.length);
	request.setRequestHeader("Content-Type","multipart/form-data; boundary="+boundary);
	request.send(data); 
};


config.macros.upload.download = function(uploadUrl, uploadToFilename, uploadDir, uploadBackupDir, 
	username, password) {
	var request;
	try {
		request = new XMLHttpRequest();
	} 
	catch (e) { 
		request = new ActiveXObject("Msxml2.XMLHTTP"); 
	}
	try {
		if (uploadUrl.substr(0,4) == "http") {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
			}
		else {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		}
	} catch (e) { }
	//request.open("GET", document.location.toString(), true, username, password);
	try {
		request.open("GET", document.location.toString(), true);
	}
	catch(e) {
		alert(config.macros.upload.messages.crossDomain + "\nError:" +e);
		exit;
	}
	
	request.onreadystatechange = function () {
		if (request.readyState == 4) {
			if(request.status == 200) {
				config.macros.upload.uploadChangesFrom(request.responseText, uploadUrl, 
					uploadToFilename, uploadDir, uploadBackupDir, username, password);
			}
			else
				alert(config.macros.upload.messages.errorDownloading.format(
					[document.location.toString()]) + "\nStatus: "+request.status.statusText);
		}
	};
	request.send(null);
};

//}}}
////===

////+++!![Initializations]

//{{{
config.lib.options.init('txtUploadStoreUrl','store.php');
config.lib.options.init('txtUploadFilename','');
config.lib.options.init('txtUploadDir','');
config.lib.options.init('txtUploadBackupDir','');
config.lib.options.init('txtUploadUserName',config.options.txtUserName);
config.lib.options.init('pasUploadPassword','');
setStylesheet(
	".pasOptionInput {width: 11em;}\n"+
	".txtOptionInput.txtUploadStoreUrl {width: 25em;}\n"+
	".txtOptionInput.txtUploadFilename {width: 25em;}\n"+
	".txtOptionInput.txtUploadDir {width: 25em;}\n"+
	".txtOptionInput.txtUploadBackupDir {width: 25em;}\n"+
	"",
	"UploadOptionsStyles");
if (document.location.toString().substr(0,4) == "http") {
	config.options.chkAutoSave = false; 
	saveOptionCookie('chkAutoSave');
}
config.shadowTiddlers.UploadDoc = "[[Full Documentation|http://tiddlywiki.bidix.info/l#UploadDoc ]]\n"; 

//}}}
////===

////+++!![Core Hijacking]

//{{{
config.macros.saveChanges.label_orig_UploadPlugin = config.macros.saveChanges.label;
config.macros.saveChanges.label = config.macros.upload.label.saveToDisk;

config.macros.saveChanges.handler_orig_UploadPlugin = config.macros.saveChanges.handler;

config.macros.saveChanges.handler = function(place)
{
	if ((!readOnly) && (document.location.toString().substr(0,4) != "http"))
		createTiddlyButton(place,this.label,this.prompt,this.onClick,null,null,this.accessKey);
};

//}}}
////===

/***
|''Name:''|UploadPlugin|
|''Type:''|Plugin|
|''Version:''|3.3.1 (30/03/2006)|
|''Source:''|[[TiddlyWiki.BidiX.info/#UploadPlugin|http://tiddlywiki.BidiX.info/#UploadPlugin]]|
|''Documentation:''|[[TiddlyWiki.BidiX.info/#UploadPluginDoc|http://tiddlywiki.BidiX.info/#UploadPluginDoc]]|
|''Author:''|BidiX[at]BidiX.info |
|''Required:''| TW 2.0.6 or better, PHP 4.4 (perhaps less  but not working on 4.1.2) |

!Description
UploadPlugin, with [[store.php]], provides @@upload@@ and @@save to web@@ functions. See HowToUpload ([[HowToUpload|http://TiddlyWiki.bidix.info/#HowToUpload]]).
UploadPlugin uses Username and Password from UploadOptions stored in cookies to authenticate itself to [[store.php]].
French translation available as a separate tiddler UploadPluginMsgFR

!!UploadPlugin
*If the TiddlyWiki is viewed from @@local disk@@ :
**{{{<<saveChanges>>}}} 
***display as ''save to disk''
***work as usual
**{{{<<upload>>}}}
***display as ''upload''
***after saving to disk, upload in the storeUrl directory.
*If the TiddlyWiki is viewed from @@website@@ and is @@readOnly@@ (in core TiddlyWiki since 2.0.6) :
**{{{<<saveChanges>>}}} 
***print nothing
***has been disabled
**{{{<<upload>>}}}
***display as '''save to web''
***save in the uploadDir directory.
*If GenerateAnRssFeed in AdvancedOptions is set :
**generate the content of the RSSFeed 
**upload the RssFile in uploadDir directory
**Caution : use the SiteUrl tiddler to specify the right url of the TiddlyWiki in the generated RssFile
*DisplayMessage
*Log upload action in UploadLog
hint : if UploadLog is the first tiddler in the Timeline Tab, no tiddler has been updated 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 to toFilename
** return status

!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 in this order. 
}}}

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 : tested Ok
*Internet Explorer : tested Ok
*Safari : reported ok on OS X
*Others : Not tested, please report status.

!Revisions
*V 3.3.1 (30/03/2006)
**bug in backup folder when uploading rssfile fixed
*V 3.3.0 (12/03/2006)
**Code refactoring
**suppress saveChanges hijacking
*V3.2.2 (25/02/2006)
**Use PasswordTweak 1.0.1
**uploaddir is a relative path
**backupdir is a relative path
+++[previous revisions]
*V3.2.1 (13/02/2006)
**name and password added to open.request (Thanks to TedPavlic)
*V3.2.0 (14/02/2006)
**Use PassworDTweak (http://tiddlyWiki.bidix.info/#PasswordTweak) for password
*V3.1.0 (12/02/2006)
**UploadOptions in Cookies
**Username and password from UploadOptions pass to store.php script for authentification check
*V3.0.3 (03/02/2006)
**Firefox 1.5.0.1 crashes due to global var fixed
*V3.0.2 (25-Jan-2006)
**HTTPS compatible
*V3.0.1 (18-Jan-2006)
**UTF8toUnicode conversion problem in Firefox
*V3.0.0 (15-Jan-2006)
**Asynchronous upload
**Synchronous upload before unload of the page
**All strings extracted in macro config
**Compatibility checked with TW 2.0.2 & TW 1.2.39 for both FF 1.5 and IE 6
*V2.0.2 (8-Jan-2006)
**conversion of SiteTitle and SiteSubtitle in web page Title
*V2.0.1 (8-Jan-2006)
**Compatibilty with TiddlyWiki 2.0.1
*V2.0.0 (3-Jan-2006)
**Save to web
**Compatibilty with TiddlyWiki 1.2.39 and TiddlyWiki 2.0.0 Beta 6
*v1.1.0 (27-Dec-2005)
**Upload RSS File
*v1.0.3 (26-Dec-2005)
**UploadLog tiddler
*v1.0.2 (24-Dec-2005)
**Optional parameter toFilename
**Optional parameter backupDir
*v1.0.1 (23-Dec-2005)
**reformatting code
* v1.0.0 (17-Dec-2005)
** first public working version
===

// 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() {};
//}}}
http://eriwen.com/tools/wikify-yourself/
http://superuser.com/questions/87724/which-tiddlywiki-plugins-do-you-use
http://swik.net/tiddlywiki+plugin
http://www.guyrutenberg.com/2011/06/25/latex-for-tiddlywiki-a-mathjax-plugin/
http://www.guyrutenberg.com/category/tips/
http://atamanenko.blogspot.com
http://sidebarpluginvault.tiddlyspot.com/
http://tiddlypocketbook.com/
http://tiddlysnip.com/#FAQ
http://www.moreofit.com/similar-to/tiddlywiki.abego-software.de/Top_10_Sites_Like_Abego-software_Tiddlywiki/

нереальная tiddywiki
http://tbgtd.tiddlyspot.com/#desk
  if(!config.shadowTiddlers.VGraphStyle){
      config.shadowTiddlers.VGraphStyle = "/*{{{*/\n" +
      ".changeAlgorithm {z-index:10;position:absolute;right:0px;bottom:0px;}\n"+
      ".VGraph {height:400px;width:600px;position:relative;border:solid 1px black;}\n"+
      "#contentWrapper .VGraph {margin-left:150px;}\n#contentWrapper #tiddlerDisplay .VGraph {margin-left:0px;}\n"+
      "/*}}}*/"
    store.addNotification("VGraphStyle", refreshStyles);
  }   
config.macros.VGraphDefaultLabelMacro = {
    handler: function(place,macroName,params,wikifier,paramString,tiddler,options){
        wikify("[["+tiddler.title+"]]",place);
    }
};
config.macros.VGraph= {
    _vgrs: {}
    ,handler: function(place,macroName,params,wikifier,paramString,tiddler,options){
        /*setup options */
        
        var newplace= document.createElement("div");
        newplace.className = "VGraph"
        place.appendChild(newplace);
        place = newplace;
            var div = document.createElement("div");
               
               place.appendChild(div);
               var w = jQuery(place).width();
               var h = jQuery(place).height();
               if(!w) w = 500;
               if(!h) h= 300;
               jQuery(div).css({width:w,height:h,"position":"relative"});
               place = div;
     
       
        var nodes = store.getTiddlers();
        if(!options){
            options = {};
        }
        options.pointsize = 20;
        merge(options,{nodeWidth:20,nodeHeight:10,defaultNodeColor:"rgb(200,200,200)",lineColor:"rgb(200,200,200)",lineWidth:"2"});
     
        if(!paramString)paramString = "";
        var namedprms = paramString.parseParams(null, null, true);
        for(var i=0; i < namedprms.length;i++){
            var nameval = namedprms[i];
            options[nameval.name] = nameval.value;
            
        }
        if(!options.lineType){
            options.lineType = 'bezier';
        }
        if(!options.parentFields) {
            options.parentFields = ["tags"];
        }
        
        if(!options.excludeTags){
            options.excludeTags =[];
        }
        if(!options.styleNode){
            options.styleNode = function(tiddler,json){
                json.properties.label = json.id;
            }
        }
        if(!options.labelMacro)options.labelMacro = "VGraphDefaultLabelMacro";
        if(options.labelMacro){
            var paramStart = options.labelMacro.indexOf(" ");
            var paramString = options.labelMacro.substr(paramStart+1);
            if(paramStart == -1){
                paramStart = options.labelMacro.length;
            }
            var macro = options.labelMacro.substr(0,paramStart);
            
            
        
            var params = paramString.split(" ");
            //console.log("macro",macro,paramString);
            
            if(config.macros[macro]){
                options.plotNode = function(el,shape){
                    var tiddler =store.getTiddler(shape.properties.id);
                    if(!tiddler)tiddler = {title:shape.properties.id,tags:[],fields:{}};
                    tiddler.vismoShape = shape;
                    config.macros[macro].handler(el,false,params,false,paramString,tiddler);
                }
            }
        }
   
        if(!options.root){
            options.root = "_VGraphBridge_";
            options.connectOrphans = true;
        }
        var graph = this.constructGraph(nodes,options);
           
        options.graph = graph;
        

        

        if(!options.algorithm)options.algorithm = "walkers";

        var vgr =  this.setup(place,options);
        
       
        config.macros.VGraph.algorithmDropdown(place,vgr,vgr.options.algorithm);
        
        return vgr;
    }
    
    ,algorithmDropdown: function(place,vgr,selected){
        var that = this;
        var algorithmStr = "<select class='changeAlgorithm'><option value='-1'>change layout algorithm</option>";
        var algs =VismoGraphAlgorithms.available();
       
        for(var i=0;i < algs.length; i++){
            var alg_id = algs[i];
            var alg = VismoGraphAlgorithms[alg_id];
            var selectStr = "";
            if(selected == alg_id){
                selectStr = " selected";
            }
            if(alg.name){
                algorithmStr += "<option value='"+alg_id+"'"+selectStr+">"+alg.name+"</option>";
            }
        }
        algorithmStr += "</select>";
        
        jQuery(place).append(algorithmStr);
        jQuery(".changeAlgorithm",place).change(function(e){
           if(this.value == "-1") return;
           
            vgr.algorithm(this.value);
            vgr.clear();
            vgr.compute();
        });
    }
    
    
    ,makeNode: function(id,options){
        var json={id:id,properties:{name:id}};
        var tiddler = store.getTiddler(id);
        if(!tiddler) tiddler = {title:id,fields:{},tags:[]};
        if(options.styleNode)options.styleNode(tiddler,json);
        return json;
    }
    ,constructGraph: function(tiddlers,options){
        var parentFields =options.parentFields;
        var childFields = options.childFields;
        var ignoreTags = options.excludeTags;
        var prepNode = options.styleNode;
        var n = [];
        var edges = [];
        var tempnodes = {};
        
        if(options.connectOrphans){
            var bridgeNode = "_VGraphBridge_";
            tempnodes[bridgeNode] = this.makeNode(bridgeNode,options);
            tempnodes[bridgeNode].properties.hidden= true;
        }
        var anOrphan = {};
        for(var i=0; i< tiddlers.length; i++){
            var node = tiddlers[i];
            var id1 = node.title;

            var tags = node.tags;
            
            if(this._includeTiddlerInGraph(node,ignoreTags)){ 
              if(!tempnodes[id1])tempnodes[id1] = this.makeNode(id1,options);
              /*define parents of that tiddler */
             
              for(var j=0; j < parentFields.length; j++){
                var field = parentFields[j];
                var isOrphan = true;
                //console.log(field);
                if(field == 'tags'){
                    
                    for(var k=0; k < node.tags.length; k++){ 
                       var tag = node.tags[k];
                        
                       if(!tempnodes[tag])tempnodes[tag] =this.makeNode(tag,options);
                       edges.push([tag,id1]);
                       isOrphan = false;
                       
                       var tagTiddler = store.getTiddler(tag);
                       if(!tagTiddler && !anOrphan[tag]){
                           edges.push(["_VGraphBridge_",tag]);
                           anOrphan[tag] = true;
                       }
                    }
                }
                else if(node[field]) {
                    edges.push([node[field],id1]);
                    isOrphan = false;
                }
                else if(node.fields[field]){
                    edges.push([node.fields[field],id1]);
                    isOrphan = false;
                }
                //console.log(id1,isOrphan);
                if(isOrphan && options.connectOrphans){
                    //console.log("orphan");
                    edges.push(["_VGraphBridge_",id1]);
                }
              }

            }
        }

        for(var l in tempnodes){
            n.push(tempnodes[l]);
        }
        
     
        //console.log(tempnodes,n,edges);
        var graph = new VismoGraph({nodes:n,edges:edges});
        return graph;
    }
    ,setup: function(place,options){
        this.options = options;
        this.setuptooltip(place);
        var that = this;
        var vgr_id = Math.random();
        options.dblclick = function(e,s){if(!s)return;story.displayTiddler(null,s.properties.name);};
        options.mousedown = function(e,s){
          
            if(s && that._vgrs){
                that._vgrs[vgr_id].centerOn(s.properties.id);
            }
        };
        this.options.vismoController = {labels:true,controlFill:options.lineColor,controlShape: "circle",controlStroke:"rgb(255,255,255)"};
     
        
        this._vgrs[vgr_id] =  new VismoGraphRenderer(place,options);
        return this._vgrs[vgr_id];
    }
    ,graph: function(){
        return this.vgr.graph();
    }
    ,setuptooltip: function(place){
        
        var tooltip = document.createElement("div");
        tooltip.className = "ft_tooltip";
        place.appendChild(tooltip);
        jQuery(tooltip).css({position:"absolute",display:"none"});
        
        var that = this;
        this.options.move = function(e,s){ jQuery(tooltip).css({display:"none"});if(s){var bb = s.getBoundingBox();jQuery(tooltip).text(s.getProperty("name"));jQuery(tooltip).css({top:e.screenY - e.clientY,left:0,display:""});}};
        
        
        
    }

    ,_includeTiddlerInGraph: function(tiddler,ignoreTags){
        for(var i=0; i < ignoreTags.length; i++){
            var tag = ignoreTags[i];
            if(tiddler.tags.indexOf(tag) != -1) return false;
        }
        return true;
    }
};
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date [[YYYY-0MM-0DD 0hh:0mm]]'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date [[YYYY-0MM-0DD]]'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'><div macro='ToC'></div></div>
<div class='tagClear'></div>
<!--}}}-->
/*
Algorithms for Vismo
*/
var VismoGraphAlgorithms = {
    available: function(){
        var i;
        var available = [];
        for(i in VismoGraphAlgorithms){
       
            if(i.indexOf("_") != 0 && i != "available"){
              
                available.push(i);
            }
        }
        return available;
    }
};VismoGraphAlgorithms.random ={  
     name: "Random"
    ,reset: function(graph){
       var nodes = graph.getNodes();
       for(var i=0; i < nodes.length; i++){
           var node = nodes[i];
           node.XPosition = false;
           node.YPosition = false;
       }
    }
    ,compute: function (graph,options) {	
        var root = options.root;
        var nodes = graph.getNodes();
        var w= 400;
        var h = 400;
        for(var i=0; i < nodes.length;i++){
            var node = nodes[i];
            
            node.XPosition = - (w/2)+ Math.random() * (w);
            node.YPosition =- (h/2)+ Math.random()  * (h);
        }
    }

};VismoGraphAlgorithms.walkers ={   
    name: "Walkers"
    ,_MaxDepth: 100,
    reset: function(graph){
       var nodes = graph.getNodes();
       for(var i=0; i < nodes.length; i++){
           var node = nodes[i];
           node.XPosition = false;
           node.YPosition = false;
           node.leftNeighbor = false;
           node.rightNeighbor = false;
           node.prelim = false;
           node.modifier = false;
       }
    }
    ,compute: function (graph,options) {	
        console.log("in compute walkers");
        var root = options.root;
        this.nodeWidth = options.nodeWidth | 40;
        this.nodeHeight = options.nodeHeight | 40;
        ////////////console.log(" lets _positiongraph (magic here)");
        this.nodeWidth +=5;
        this.nodeHeight += 5;
        this.reset(graph);
    	this.maxLevelHeight = [];
    	this.maxLevelWidth = [];			
    	this.previousLevelNode = [];
    	////////////console.log(root);
    	var rootnode = graph.getNode(root);		
    	this._firstWalk(graph,rootnode, 0);
	    this.rootXOffset = 0 + rootnode.XPosition;
    	this.rootYOffset = 0 + rootnode.YPosition;

    	this._secondWalk(graph, rootnode, 0, 0, 0);	
    },
    _setLevelHeight: function (node, level) {	
    	if (this.maxLevelHeight[level] == null) 
    		this.maxLevelHeight[level] = 0;
        if(this.maxLevelHeight[level] < node.h)
            this.maxLevelHeight[level] = node.h;	
    },
    _setLevelWidth: function (node, level) {
    	if (this.maxLevelWidth[level] == null) 
    		this.maxLevelWidth[level] = 0;
        if(this.maxLevelWidth[level] < this.nodeWidth)
            this.maxLevelWidth[level] =  this.nodeWidth;		
    },
    _setNeighbors: function(node, level) {
        node.leftNeighbor = this.previousLevelNode[level];
        if(node.leftNeighbor != null)
            node.leftNeighbor.rightNeighbor = node;
        this.previousLevelNode[level] = node;	
    },

    _getLeftSibling : function (node) {
        if(node.leftNeighbor != null && node.leftNeighbor.nodeParent == node.nodeParent)
            return node.leftNeighbor;
        else
            return null;	
    },

    _getRightSibling: function (node) {
        if(node.rightNeighbor != null && node.rightNeighbor.nodeParent == node.nodeParent)
            return node.rightNeighbor;
        else
            return null;	
    },
    _getChildrenCenter: function (graph,node) {
        ////////////console.log("getChildrenCenter",node.id);
        var children = graph.getChildren(node.id);
        ////////////console.log("children are ",children,graph);
      
        var firstchild = graph.getNode(children[0]);
        var lastchild = graph.getNode(children[children.length-1]);
        ////////////console.log("kids are",firstchild,lastchild);
        return firstchild.prelim + ((lastchild.prelim - firstchild.prelim) + this.nodeWidth) / 2;	
    },
    

    _firstWalk: function (graph, node, level) {
    		////console.log("walking",node);
    		var leftSibling = null;
		    node._depth = level;
            node.XPosition = 0;
            node.YPosition = 0;
            
            node.prelim = 0;
            node.modifier = 0;
            node.leftNeighbor = null;
            node.rightNeighbor = null;
            this._setLevelHeight(node, level);
            this._setLevelWidth(node, level);
            this._setNeighbors(node, level);
            var children= graph.getChildren(node.id);
            var parents = graph.getParents(node.id);
            var parents_children=graph.getChildren(parents);
            var siblingid = parents_children.indexOf(node.id);
            //////////console.log("has children",children);
            if(children.length == 0 || level == this._MaxDepth)
            {
     
                leftSibling = this._getLeftSibling(node);
                if(leftSibling != null){
                     ////////console.log("left sibling prelim",leftSibling.prelim,"size",this.nodeWidth(leftSibling));
                    
                    node.prelim = leftSibling.prelim + this.nodeWidth + 40;
                }
                else
                    node.prelim = 0;
            } 
            else
            {
                
                var n = graph.getChildren(node.id);
                for(var i = 0; i < n.length; i++)
                {
                    var iChild = graph.getNode(n[i]);
                    iChild.nodeParent = node;
                    this._firstWalk(graph, iChild, level + 1);
                }
                var midPoint = this._getChildrenCenter(graph,node);
                midPoint -= this.nodeWidth / 2;
                leftSibling = this._getLeftSibling(node);
                ////////////console.log("have leftSibling",leftSibling,"of ",node);
                if(leftSibling != null)
                {
                    ////////console.log("prelim",leftSibling.prelim,"size",this.nodeWidth(leftSibling));
                    node.prelim = leftSibling.prelim + this.nodeWidth + 40;
                    node.modifier = node.prelim - midPoint;
                    //////console.log("y",node.YPosition);
                    if(node.YPosition.toString() =='NaN') throw "bad modifier";
                    this._apportion(graph, node, level);
                } 
                else
                {            	
                    node.prelim = midPoint;
                }
            }	
            //////////console.log("finished first walk");
    },
    _apportion: function (graph, node, level) {
        //////////console.log("in apportion");
        var children = graph.getChildren(node.id);
            var firstChild = graph.getNode(children[0]);
            var firstChildLeftNeighbor = firstChild.leftNeighbor;
            var j = 1;
            for(var k = this._MaxDepth - level; firstChild != null && firstChildLeftNeighbor != null && j <= k;)
            {
              
                var modifierSumRight = 0;
                var modifierSumLeft = 0;
                var rightAncestor = firstChild;
                var leftAncestor = firstChildLeftNeighbor;
                for(var l = 0; l < j; l++)
                {
                    
                    rightAncestor = rightAncestor.nodeParent;
                    leftAncestor = leftAncestor.nodeParent;
                    modifierSumRight += rightAncestor.modifier;
                    modifierSumLeft += leftAncestor.modifier;
  
                }
                ////console.log("the node is",node,"left ancestor is",leftAncestor,"right is ",rightAncestor);
                var totalGap = (firstChildLeftNeighbor.prelim + modifierSumLeft + this.nodeWidth + 30) - (firstChild.prelim + modifierSumRight);
                if(totalGap > 0)
                {
                    var subtreeAux = node;
                    var numSubtrees = 0;
                    for(; subtreeAux != null && subtreeAux != leftAncestor; subtreeAux = this._getLeftSibling(subtreeAux))
                        numSubtrees++;

                    if(subtreeAux != null)
                    {
                        
                        var subtreeMoveAux = node;
                        ////console.log("subtree is",subtreeMoveAux);
                        var singleGap = totalGap / numSubtrees;
                        for(; subtreeMoveAux != leftAncestor; subtreeMoveAux = this._getLeftSibling(subtreeMoveAux))
                        {
                            ////console.log("left sibling is ",subtreeMoveAux,"looking for ",leftAncestor," to stop");
                            subtreeMoveAux.prelim += totalGap;
                            subtreeMoveAux.modifier += totalGap;
                            totalGap -= singleGap;
                        }

                    }
                }
                j++;
                var firstChildChildren = graph.getChildren(firstChild.id);
                if(firstChildChildren.length == 0){
            
                    firstChild = this._getLeftmost(graph,node, 0, j);
                    }
                else
                    firstChild = graph.getNode(firstChildChildren[0]);
                if(firstChild != null)
                    firstChildLeftNeighbor = firstChild.leftNeighbor;
            }
    },
    _getLeftmost:function (graph,node, level, maxlevel) {
       
        if(level >= maxlevel) return node;
        var children = graph.getChildren(node.id);
        
     
        if(children.length == 0) return null;

    
        for(var i = 0; i < children.length; i++)
        {
            var iChild = graph.getNode(children[i]);
            var leftmostDescendant = this._getLeftmost(graph,iChild, level + 1, maxlevel);
            if(leftmostDescendant != null)
                return leftmostDescendant;
        }

        return null;	
    },
    _secondWalk: function (graph, node, level, X, Y) {
        ////console.log("doing _secondWalk",level,node,node.id,node.leftNeighbor,node.rightNeighbor);
            if(level <= this._MaxDepth)
            {
                var xTmp = 0 + node.prelim + X;
                var yTmp = 0 + Y;
                var maxsizeTmp = 0;
                var nodesizeTmp = 0;
                var flag = false;
            
                 	            	    	
    	                maxsizeTmp = this.maxLevelHeight[level];
    	                nodesizeTmp = this.nodeHeight;	                
    	                node.XPosition = xTmp;
    	                node.YPosition = yTmp;
    	         
                if(flag)
                {
                    var swapTmp = node.XPosition;
                    node.XPosition = node.YPosition;
                    node.YPosition = swapTmp;
                    //////console.log("swapTmp",swapTmp,node.XPosition);
                    
                }
         
    	    node.YPosition = -node.YPosition - nodesizeTmp;
    	       //////console.log("nodesizeTmp",nodesizeTmp);
            
    	    ////////////console.log("getting Children",node);
    	     var Children = graph.getChildren(node.id);
    	     ////////////console.log(Children);
                if(Children.length != 0)
                    this._secondWalk(graph, graph.getNode(Children[0]), level + 1, X + node.modifier, Y + maxsizeTmp + 40);
                var rightSibling = this._getRightSibling(node);
                if(rightSibling != null)
                    this._secondWalk(graph, rightSibling, level, X, Y);
            }	
    ////////console.log("now",node.XPosition,node.YPosition);
    }
};/*
Taken from The JIT RGraph Library (BSD License) by Nicolas Garcia Belmonte
http://thejit.org/

***/
/*
 * File: RGraph.js
 * 
 * Author: Nicolas Garcia Belmonte
 * 

 * 
 * License: BSD License
 * 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the organization 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 Nicolas Garcia Belmonte ``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 Nicolas Garcia Belmonte 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.
 * 
 */

VismoGraphAlgorithms._utils ={   

    labelContainer: 'label_container'

    //Property: drawConcentricCircles
    //show/hide concentricCircles
    ,drawConcentricCircles: 4,

    //Property: concentricCirclesColor
    //The color of the concentric circles
    concentricCirclesColor: '#444',

    //Property: levelDistance
    //The actual distance between levels
    levelDistance: 100,

    //Property: nodeRadius
    //The radius of the nodes displayed
    nodeRadius: 4,

    //Property: allowVariableNodeDiameters
    //Set this to true if you want your node diameters to be proportional to you first dataset object value property (i.e _data[0].value_).
    //This will allow you to represent weighted tree/graph nodes.
    allowVariableNodeDiameters: false,

    //Property: nodeRangeDiameters
    //Diameters range. For variable node weights.
    nodeRangeDiameters: {
    min: 10,
    max: 35
    },

    //Property: nodeRangeValues
    // The interval of the values of the first object of your dataSet.
    // A superset of the values can also be specified.
    nodeRangeValues: {
    min: 1,
    max: 35
    },

    //Property: fps
    //animation frames per second
    fps:40,

    //Property: animationTime
    animationTime: 2500,

    //Property: interpolation
    interpolation: 'linear'   
    ,eachBFS: function(graph, id, action, flags) {
        
 		var filter = this.filter(flags);
 		graph.eachNode(function(elem) { elem._flag = false; });
 		
 		var queue = [graph.getNode(id)];
 		while(queue.length != 0) {
 			var node = queue.pop();
 			node._flag = true;
 			action(node, node._depth);
 			
 			graph.eachEdge(node, function(adj) {
 				var n = adj[1];
 				if(n._flag == false && filter(n)) {
 					n._flag = true;
 					queue.unshift(n);
 				}
 			});
 		}
 	}
    ,setAngularWidthForNodes: function(graph) {
 		var rVal = this.nodeRangeValues, rDiam = this.nodeRangeDiameters, nr = this.nodeRadius, allow = this.allowVariableNodeDiameters; 
 		var diam = function(value) { 

 		    var r= (((rDiam.max - rDiam.min)/(rVal.max - rVal.min)) * (value - rVal.min) + rDiam.min);
 		    return r;};
 		var that = this;
 		this.eachBFS(graph, this.root, function(elem, i) {
 			var dataValue = (allow && elem.data && elem.data.length > 0)? elem.data[0].value : nr;
 			var diamValue = diam(dataValue);
 			var rho = that.levelDistance * i;

 			elem._angularWidth = diamValue / rho;
 			elem._radius = allow? diamValue / 2 : nr;
 		}, "ignore");
 	}
 	,setSubtreeAngularWidth: function(graph,elem) {
 		var that = this, nodeAW = elem._angularWidth, sumAW = 0;
 		this.eachSubnode(graph, elem, function(child) {
 			that.setSubtreeAngularWidth(graph,child);
 			sumAW += child._treeAngularWidth;
 		}, "ignore");
 		elem._treeAngularWidth = Math.max(nodeAW, sumAW);
 	}
 	,eachSubnode: function(graph, node, action, flags) {
 		var d = node._depth, filter = this.filter(flags);
 		graph.eachEdge(node, function(adj) {
 			var n = adj[1];
 			if(n._depth > d && filter(n)) action(n);
 		});
 	}
 	,setSubtreesAngularWidth: function(graph) {
 		var that = this;
 		graph.eachNode(function(elem) {
 			that.setSubtreeAngularWidth(graph,elem);
 		});
 	}	
 	,computeAngularWidths: function (graph) {
 		this.setAngularWidthForNodes(graph);
 		this.setSubtreesAngularWidth(graph);
 	}
     /*
   	 Method: flagRoot

   	 Flags a node specified by _id_ as root.
   	*/
   	,flagRoot: function(graph,id) {
   		this.unflagRoot(graph);
   		var node = graph.getNode(id);
   		node._root = true;
   	}

 	,filter: function(param) {
 		if(!param || !param.constructor.toString().match(/string/i)) return function() { return true; };
 		var props = param.split(" ");
 		return function(elem) {
 			for(var i=0; i<props.length; i++) if(elem[props[i]]) return false;
 			return true;
 		};
 	}
 	,getMaximumDepth: function(){
 	    return this.maxDepth;
 	}
    ,computeLevels: function(graph,id, flags) {
        this.maxDepth = 0;
        var that = this;
 		var filterer = this.filter(flags);
 		graph.eachNode(function(elem) {
 			if(filterer(elem)){
 			    elem._flag = false;
 			    elem._depth = -1;
 			}
 		});
 		var root = graph.getNode(id);
 		root._depth = 0;
 		var queue = [root];
 		while(queue.length != 0) {
 			var node = queue.pop();
 			node._flag = true;
 			graph.eachEdge(node, function(adj) {
 				if(filterer(node)){
 				    var n = adj[1];
 				    if(n._flag == false && filterer(n)) {
 					    if(n._depth < 0) n._depth = node._depth + 1;
 					    if(n._depth > that.maxDepth) that.maxDepth = n._depth;
 					    queue.unshift(n);
 				    }
 				}
 			});
 		}
 	}

   	/*
   	 Method: unflagRoot

   	 Unflags all nodes.
   	*/
   	,unflagRoot: function(graph) {
   		graph.eachNode(function(elem) {elem._root = false;});
   	}
 	,computePositions: function(graph,property) {
 		var propArray = (typeof property == 'array' || typeof property == 'object')? property : [property];
 		var aGraph = graph;
 		var root = graph.getNode(this.root);

 		for(var i=0; i<propArray.length; i++)
 			root[propArray[i]] = new Polar(0, 0);

 		root.angleSpan = {
 			begin: 0,
 			end: 2 * Math.PI
 		};
 		root._rel = 1;
 		var that = this;
 		this.eachBFS(graph, this.root, function (elem) {
 			var angleSpan = elem.angleSpan.end - elem.angleSpan.begin;
 			var rho = (elem._depth + 1) * that.levelDistance;
 			var angleInit = elem.angleSpan.begin;
 			var totalAngularWidths = (function (element){
 				var total = 0;
 				that.eachSubnode(aGraph, element, function(sib) {
 					total += sib._treeAngularWidth;
 				}, "ignore");
 				return total;
 			})(elem);

 			that.eachSubnode(aGraph, elem, function(child) {
 				if(!child._flag) {
 					child._rel = child._treeAngularWidth / totalAngularWidths;
 					var angleProportion = child._rel * angleSpan;
 					var theta = angleInit + angleProportion / 2;


 					for(var i=0; i<propArray.length; i++){
 						child[propArray[i]] = new Polar(theta, rho);

                     }
 					child.angleSpan = {
 						begin: angleInit,
 						end: angleInit + angleProportion
 					};
 					angleInit += angleProportion;
 				}
 			}, "ignore");
 		}, "ignore");
 	}



 };
 
VismoGraphAlgorithms.radial = {
        name: "Radial"
    ,reset: function(graph){
        var nodes = graph.getNodes();
        for(var i=0; i < nodes.length; i++){
            var node = nodes[i];
            node.XPosition = false;
            node.YPosition = false;
        }
    }
    ,compute: function (graph,options,property) {	
       
        var root = options.root;


        var prop = property || ['pos', 'startPos', 'endPos'];
        var node = graph.getNode(root);
        node._depth = 0;
        var utils = VismoGraphAlgorithms._utils;
        utils.root = root;

        utils.flagRoot(graph,root);

        utils.computeLevels(graph,root, "ignore");
        utils.computeAngularWidths(graph);
        utils.computePositions(graph,prop);

        var nodes = graph.getNodes();

        for(var i=0; i < nodes.length;i++){
         var node = nodes[i];

         if(node.pos){
             var pos = node.pos.toComplex();
             node.XPosition =  pos.x;
             node.YPosition = pos.y
         }
        }
    }

 };
 
 var Complex= function() {
 	if (arguments.length > 1) {
 		this.x= arguments[0];
 		this.y= arguments[1];

 	} else {
 		this.x= null;
 		this.y= null;
 	}

 };

 Complex.prototype= {
 	/*
 	   Method: clone

 	   Returns a copy of the current object.

 	   Returns:

 	      A copy of the real object.
 	*/
 	clone: function() {
 		return new Complex(this.x, this.y);
 	},

 	/*
 	   Method: toPolar

 	   Transforms cartesian to polar coordinates.

 	   Returns:

 	      A new <Polar> instance.
 	*/

 	toPolar: function() {
 		var rho = this.norm();
 		var atan = Math.atan2(this.y, this.x);
 		if(atan < 0) atan += Math.PI * 2;
 		return new Polar(atan, rho);
 	},
 	/*
 	   Method: norm

 	   Calculates the complex norm.

 	   Returns:

 	      A real number representing the complex norm.
 	*/
 	norm: function () {
 		return Math.sqrt(this.squaredNorm());
 	},

 	/*
 	   Method: squaredNorm

 	   Calculates the complex squared norm.

 	   Returns:

 	      A real number representing the complex squared norm.
 	*/
 	squaredNorm: function () {
 		return this.x*this.x + this.y*this.y;
 	},

 	/*
 	   Method: add

 	   Returns the result of adding two complex numbers.
 	   Does not alter the original object.

 	   Parameters:

 	      pos - A Complex initialized instance.

 	   Returns:

 	     The result of adding two complex numbers.
 	*/
 	add: function(pos) {
 		return new Complex(this.x + pos.x, this.y + pos.y);
 	},

 	/*
 	   Method: prod

 	   Returns the result of multiplying two complex numbers.
 	   Does not alter the original object.

 	   Parameters:

 	      pos - A Complex initialized instance.

 	   Returns:

 	     The result of multiplying two complex numbers.
 	*/
 	prod: function(pos) {
 		return new Complex(this.x*pos.x - this.y*pos.y, this.y*pos.x + this.x*pos.y);
 	},

 	/*
 	   Method: conjugate

 	   Returns the conjugate por this complex.

 	   Returns:

 	     The conjugate por this complex.
 	*/
 	conjugate: function() {
 		return new Complex(this.x, -this.y);
 	},


 	/*
 	   Method: scale

 	   Returns the result of scaling a Complex instance.
 	   Does not alter the original object.

 	   Parameters:

 	      factor - A scale factor.

 	   Returns:

 	     The result of scaling this complex to a factor.
 	*/
 	scale: function(factor) {
 		return new Complex(this.x * factor, this.y * factor);
 	},

 	/*
 	   Method: equals

 	   Comparison method.
 	*/
 	equals: function(c) {
 		return this.x == c.x && this.y == c.y;
 	},

 	/*
 	   Method: $add

 	   Returns the result of adding two complex numbers.
 	   Alters the original object.

 	   Parameters:

 	      pos - A Complex initialized instance.

 	   Returns:

 	     The result of adding two complex numbers.
 	*/
 	$add: function(pos) {
 		this.x += pos.x; this.y += pos.y;
 		return this;	
 	},

 	/*
 	   Method: $prod

 	   Returns the result of multiplying two complex numbers.
 	   Alters the original object.

 	   Parameters:

 	      pos - A Complex initialized instance.

 	   Returns:

 	     The result of multiplying two complex numbers.
 	*/
 	$prod:function(pos) {
 		var x = this.x, y = this.y
 		this.x = x*pos.x - y*pos.y;
 		this.y = y*pos.x + x*pos.y;
 		return this;
 	},

 	/*
 	   Method: $conjugate

 	   Returns the conjugate for this complex.
 	   Alters the original object.

 	   Returns:

 	     The conjugate for this complex.
 	*/
 	$conjugate: function() {
 		this.y = -this.y;
 		return this;
 	},

 	/*
 	   Method: $scale

 	   Returns the result of scaling a Complex instance.
 	   Alters the original object.

 	   Parameters:

 	      factor - A scale factor.

 	   Returns:

 	     The result of scaling this complex to a factor.
 	*/
 	$scale: function(factor) {
 		this.x *= factor; this.y *= factor;
 		return this;
 	},

 	/*
 	   Method: $div

 	   Returns the division of two complex numbers.
 	   Alters the original object.

 	   Parameters:

 	      pos - A Complex number.

 	   Returns:

 	     The result of scaling this complex to a factor.
 	*/
 	$div: function(pos) {
 		var x = this.x, y = this.y;
 		var sq = pos.squaredNorm();
 		this.x = x * pos.x + y * pos.y; this.y = y * pos.x - x * pos.y;
 		return this.$scale(1 / sq);
 	}
 };

 Complex.KER = new Complex(0, 0);
 
 var Polar = function(theta, rho) {

 	this.theta = theta;
 	this.rho = rho;
 };

 Polar.prototype = {
 	/*
 	   Method: clone

 	   Returns a copy of the current object.

 	   Returns:

 	      A copy of the real object.
 	*/
 	clone: function() {
 		return new Polar(this.theta, this.rho);
 	},

 	/*
 	   Method: toComplex

 	    Translates from polar to cartesian coordinates and returns a new <Complex> instance.

 	   Returns:

 	      A new Complex instance.
 	*/
 	toComplex: function() {
 		return new Complex(Math.cos(this.theta), Math.sin(this.theta)).$scale(this.rho);
 	},

 	/*
 	   Method: add

 	    Adds two <Polar> instances.

 	   Returns:

 	      A new Polar instance.
 	*/
 	add: function(polar) {
 		return new Polar(this.theta + polar.theta, this.rho + polar.rho);
 	},

 	/*
 	   Method: scale

 	    Scales a polar norm.

 	   Returns:

 	      A new Polar instance.
 	*/
 	scale: function(number) {
 		return new Polar(this.theta, this.rho * number);
 	},

 	/*
 	   Method: equals

 	   Comparison method.
 	*/
 	equals: function(c) {
 		return this.theta == c.theta && this.rho == c.rho;
 	},

 	/*
 	   Method: $add

 	    Adds two <Polar> instances affecting the current object.

 	   Returns:

 	      The changed object.
 	*/
 	$add: function(polar) {
 		this.theta = this.theta + polar.theta; this.rho += polar.rho;
 		return this;
 	},

 	/*
 	   Method: $madd

 	    Adds two <Polar> instances affecting the current object. The resulting theta angle is modulo 2pi.

 	   Returns:

 	      The changed object.
 	*/
 	$madd: function(polar) {
 		this.theta = (this.theta + polar.theta) % (Math.PI * 2); this.rho += polar.rho;
 		return this;
 	},


 	/*
 	   Method: $scale

 	    Scales a polar instance affecting the object.

 	   Returns:

 	      The changed object.
 	*/
 	$scale: function(number) {
 		this.rho *= number;
 		return this;
 	},

 	/*
 	   Method: interpolate

 	    Calculates a polar interpolation between two points at a given delta moment.

 	   Returns:

 	      A new Polar instance representing an interpolation between _this_ and _elem_
 	*/
 	interpolate: function(elem, delta) {
 		var pi2 = Math.PI * 2;
 		var ch = function(t) {
 			return (t < 0)? (t % pi2) + pi2 : t % pi2;
 		};
 		var tt = ch(this.theta) , et = ch(elem.theta);
 		var sum;
 		if(Math.abs(tt - et) > Math.PI) {
 			if(tt - et > 0) {
 				sum =ch((et + ((tt - pi2) - et)* delta)) ;
 			} else {
 				sum =ch((et - pi2 + (tt - (et - pi2))* delta));
 			}

 		} else {
 				sum =ch((et + (tt - et)* delta)) ;
 		}
 		var  t = (sum);
 		var r = (this.rho - elem.rho) * delta + elem.rho;
 		return new Polar(t, r);
 	}
 };

 Polar.KER = new Polar(0, 0);
 
VismoGraphAlgorithms.hyperbolic ={   
    size: {width:400,height:400}
    ,name: "Hyperbolic"
    ,reset: function(graph){
       var nodes = graph.getNodes();
       for(var i=0; i < nodes.length; i++){
           var node = nodes[i];
           node.XPosition = false;
           node.YPosition = false;
       }
    }
    ,computeLevels: function(graph,id, flags) {

		var filterer = VismoGraphAlgorithms._utils.filter(flags);
		graph.eachNode(function(elem) {
			if(filterer(elem)){
			    elem._flag = false;
			    elem._depth = -1;
			}
		});
		var root = graph.getNode(id);
		root._depth = 0;
		var queue = [root];
		while(queue.length != 0) {
			var node = queue.pop();
			node._flag = true;
			graph.eachEdge(node, function(adj) {
				if(filterer(node)){
				    var n = adj[1];
				    if(n._flag == false && filterer(n)) {
					    if(n._depth < 0) n._depth = node._depth + 1;
					    queue.unshift(n);
				    }
				}
			});
		}
	}
    ,compute: function (graph,options) {	
        
        var root = options.root;
        var nodes = graph.getNodes();
        var utils = VismoGraphAlgorithms._utils;
        utils.root = root;
        
        var prop = ['pos', 'startPos']; 
        var node = graph.getNode(root); 
        node._depth = 0; 
        utils.computeLevels(graph, utils.root, 0, "ignore"); 
        var md = utils.getMaximumDepth();
        this.size.width = options.canvas_width *  (md);
        this.size.height = options.canvas_height * (md);
        //console.log(utils,md,this.size.width,this.size.height);
        
        utils.computeAngularWidths(graph); 
        

        this.computePositions(graph,prop);
   
        for(var i=0; i < nodes.length;i++){
            var node = nodes[i];
     
             var scale = Math.min(this.size.width, this.size.height)/2; 
            if(node.pos){
                var pos = node.pos.toComplex();
                node.XPosition =  pos.x * scale;
                node.YPosition = pos.y * scale; 
            }
           
        }
    }
    ,computePositions: function(graph,property) {
        var utils = VismoGraphAlgorithms._utils;
        var get_type = function(elem) {
          return Object.prototype.toString.call(elem).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
        };
        
        var type = get_type(property);
        var propArray = (type) ? ((type != 'array') ? [property] : property) : [];
        var aGraph = graph;
        var root = graph.getNode(utils.root), that = this, config = this.config; 
        var scale = Math.min(this.size.width, this.size.height)/ 2; 
 
 
        //Set default values for the root node 
        for(var i=0; i<propArray.length; i++)  
            root[propArray[i]] =  new Polar(0, 0); 
        root.angleSpan = { 
            begin: 0, 
            end: 2 * Math.PI 
        }; 
    root._rel = 1; 
   
        //Estimate better edge length. 
        var edgeLength = (function() { 
            var depth = 0; 
            graph.eachNode(function(node) { 
                depth = (node._depth > depth)? node._depth : depth; 
        node._scale = scale; 
            }, "ignore"); 
            for(var i=0.51; i<=1; i+=0.01) { 
                var valSeries = (function(a, n) { 
                    return (1 - Math.pow(a, n)) / (1 - a); 
                })(i, depth + 1); 
                if(valSeries >= 2) return i - 0.01; 
            } 
            return 0.5; 
        })(); 
       
        utils.eachBFS(graph, utils.root, function (elem) { 
            var angleSpan = elem.angleSpan.end - elem.angleSpan.begin; 
            var angleInit = elem.angleSpan.begin;
             
            var totalAngularWidths = (function (element){ 
                var total = 0; 
                utils.eachSubnode(graph,element, function(sib) { 
                    total += sib._treeAngularWidth; 
                }, "ignore"); 
                return total; 
            })(elem); 
 
            for(var i=1, rho = 0, lenAcum = edgeLength, depth = elem._depth; i<=depth+1; i++) { 
                rho += lenAcum; 
                lenAcum *= edgeLength; 
            } 
              
            utils.eachSubnode(graph,elem, function(child) { 
                if(!child._flag) { 
                    child._rel = child._treeAngularWidth / totalAngularWidths; 
                    var angleProportion = child._rel * angleSpan; 
                    var theta = angleInit + angleProportion / 2; 
                 
                    for(var i=0; i<propArray.length; i++) 
                        child[propArray[i]] = new Polar(theta, rho); 
                 
                    child.angleSpan = { 
                        begin: angleInit, 
                        end: angleInit + angleProportion 
                    }; 
                    angleInit += angleProportion; 
                } 
            }, "ignore"); 
 
        }, "ignore"); 
    } 
    
};

/***
|''Name:''|Jon Robson's VismoLibrary|
|''Description:''|An opensource library of javascript code designed to create clickable graphics in canvas with VML alternative for Internet Explorer browsers. The purpose of this is to provide hackable, extendable graphics based plugins without being locked in to consumer products such as Flash.|
|''Author:''|JonRobson (http://www.jonrobson.me.uk/Vismo)|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonRobson/Library/Vismo/|
|''Version:''|0.9 |
|''Dependencies:''| Requires jQuery|
|''Comments:''|Please raise questions and make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''Contributors:''"|
Graph algorithms for VismoGraphs come from uses code from ECO Tree http://www.codeproject.com/KB/scripting/graphic_javascript_tree.aspx#quick|
and Nicolas Belmonte's JIT library (http://thejit.org/)
|
"|''Usage:''|
Not much good on it's own - it provides some nice functions to create graphicsy plugins.
Currently provides horsepower to the following plugins amongst others:
GeoTiddlyWiki (http://www.jonrobson.me.uk/workspaces/tiddlers/GeoTiddlyWiki/), ImageTaggingPlugin, TiddlyTagMindMap (http://tiddlytagmindmap.tiddlyspot.com)
!Wouldn't have been possible without..
http://spatialreference.org/ref/sr-org/google-projection/ for help with google projection hack
***/
var VismoOptimisations = {
    minradius:5,
	packCoordinates: function(coordlist){
		var res = [];
		for(var i=0; i < coordlist.length-1; i+=2){
			res.push([coordlist[i],coordlist[i+1]]);
		}
		
		return res;
	}
	,unpackCoordinates: function(coordlist){
		var res = [];
		for(var i=0; i < coordlist.length; i+=1){
			res.push(coordlist[i][0]);
			res.push(coordlist[i][1]);
		}
		return res;	
	}
	//coords in form [[x1,y1],[x2,y2]]
	,douglasPeucker: function(coords,tolerance, start,end){
		var results = [];

		if(!start) start = 0;
		if(!end) end = coords.length - 1;
		if(start >= coords.length || end >= coords.length || start == end -1){
			return [];
		}	
		var midpoint = {};
	
	
		midpoint.x = (coords[end][0] + coords[start][0]) /2;
		midpoint.y = (coords[end][1] + coords[start][1]) /2;
		
		var bestPoint = {distance:-1, index:-1};
		for(var i=start+1; i < end; i++){
			var x = coords[i][0];
			var y = coords[i][1];
			var deltax = midpoint.x - x;
			var deltay= midpoint.y - y;
			
			var perpendicular_d = Math.sqrt((deltax * deltax ) + (deltay *deltay)); //this is not perpendicular distancd.. i think!
			if(perpendicular_d > bestPoint.distance){
				bestPoint.index = i;
				bestPoint.distance = perpendicular_d;
			}
		}
	
		if(bestPoint.index ==-1 || bestPoint.distance<tolerance){
			var res = [];
			res.push(coords[start]);
			//res.push(coords[end])
			return res; //none of these points are interesting except last
		}
		else{
			results.push(coords[start]);
			var ref = bestPoint.index;
			var splice1 = VismoOptimisations.douglasPeucker(coords,tolerance,start+1,ref);
			var splice2 = VismoOptimisations.douglasPeucker(coords,tolerance,ref,end);
			results = results.concat(splice1);
			results = results.concat(splice2);
			results.push(coords[end]);
			return results;
		}
		
	}
    ,inVisibleArea: function(el,x,y,transformation){
        	var left = 0,top = 0;
        	
        	var right =  jQuery(el).width(); 
    		var bottom = jQuery(el).height();
    	
    		var topleft =  VismoClickingUtils.undotransformation(left,top,transformation);
    		var bottomright =  VismoClickingUtils.undotransformation(right,bottom,transformation);				
            if(x < bottomright.x && x > topleft.x && y < bottomright.y && y > topleft.y){
                
                return true;
            }
            else{
                console.log("bad",el,x,y,transformation,topleft,bottomright);
                return false;
            }
    }
	,vismoShapeIsInVisibleArea: function(vismoShape,canvas,transformation,projection){
		var left = 0,top = 0;
		var right =  parseInt(canvas.width) + left; 
		var bottom = parseInt(canvas.height) + top;
		var topleft =  VismoClickingUtils.undotransformation(left,top,transformation);
		var bottomright =  VismoClickingUtils.undotransformation(right,bottom,transformation);		
		if(projection){
		    topleft = projection.xy(topleft);	
		    bottomright = projection.xy(bottomright);	
		}
		var frame = {};
		frame.top = topleft.y;
		frame.bottom = bottomright.y;
		frame.right = bottomright.x;
		frame.left = topleft.x;

		var g = vismoShape.getBoundingBox();
           
		if(g.x2 < frame.left) {
			return false;}
		if(g.y2 < frame.top) {
			return false;}
		if(g.x1 > frame.right){
			return false;
		}
		if(g.y1 > frame.bottom){
			return false;	
		}
		
		return true;
	}
	
	,vismoShapeIsTooSmall: function(vismoShape,transformation){
	    
	    VismoTimer.start("VismoOptimisations.vismoShapeIsTooSmall");

		if(!transformation ||!transformation.scale) {
		    VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
		    return false;
		}
		var g = vismoShape.getBoundingBox();
		var s = transformation.scale;
		var t1 = (g.width) * s.x;
		var t2 =(g.height) * s.y;

       
		if(t2 < this.minradius&& t1 < this.minradius) 
			{
			  VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
                    return true;}//too small
		else{
		   VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
			return false;
		}
		VismoTimer.end("VismoOptimisations.vismoShapeIsTooSmall");
	}

};window.onbeforeunload =function(){
    try{
        VismoUtils.scrubNodes(window.documentElement);
        
        if (window.CollectGarbage) {
    	    window.CollectGarbage();
        }
    }
    catch(e){
        //get over it
    }
};

Array.prototype.contains = function(item)
{
	return this.indexOf(item) != -1;
};
Array.prototype.clone = function () {var a = new Array(); for (var property in this) {a[property] = typeof (this[property]) == 'object' ? this[property].clone() : this[property]} return a};

if(!Array.indexOf) {
	Array.prototype.indexOf = function(item,from)
	{
		if(!from)
			from = 0;
		for(var i=from; i<this.length; i++) {
			if(this[i] === item)
				return i; 
		}
		return -1;
	};
}

var VismoShapeUtils ={
    randomColor: function(alpha){
       var r = parseInt(Math.random() * 255);
       var g = parseInt(Math.random() * 255);
       var b = parseInt(Math.random() * 255);
       var a;
       if(alpha) var a = parseInt(Math.random() * 255);
       else a = 1;
       return "rgba("+r+","+g+","+b+","+a+")";
    }
    ,_isCoordinate: function(c){
        if(c == "M" || c == "q" || c== 'c') return false;
        else {
            if(typeof(c)== 'number') return true;
        }
    }
    
    ,toHex: function(rgba){
        if(rgba.indexOf("rgba") == 0){
            rgba = rgba.replace("rgba(","");
            rgba = rgba.replace(")","");
        }
        else if(rgba.indexOf("rgb")==0){
             rgba = rgba.replace("rgb(","");
        }
        
        rgba = rgba.replace(")","");
        rgba = rgba.split(",");
        return "#"+this._tohexadecimal(rgba[0])+this._tohexadecimal(rgba[1]) +this._tohexadecimal(rgba[2]);
    }
    ,_tohexadecimal: function(N){
        if (N==null) return "00";
        N=parseInt(N); if (N==0 || isNaN(N)) return "00";
        N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
        return "0123456789ABCDEF".charAt((N-N%16)/16)
             + "0123456789ABCDEF".charAt(N%16);
        
    }
    ,opacityFrom: function(rgba){
 
        var rgbcode = rgba.replace("rgba(","");
	    rgbcode = rgbcode.replace(")","");
	    rgbcode = rgbcode.split(",");
	    var opvalue = 0;
	    if(rgbcode.length < 4) opvalue = 1;
	    else opvalue =rgbcode[3];
	    
	    return opvalue;
    }
    ,toRgb: function(hex_rgba,opacity){
        var rgb = {};
        if(hex_rgba.indexOf("#") == 0 && hex_rgba.indexOf(",") == -1){ //hex code argument
            var hex = hex_rgba;
			var hexcode = hex.substring(1);
			rgb.red = this._hexToR(hexcode);
			rgb.blue = this._hexToB(hexcode);
			rgb.green = this._hexToG(hexcode);
		}
		else if(hex_rgba.indexOf("rgba") != -1){
		    var rgbcode = hex_rgba.replace("rgba(","");
		    rgbcode = rgbcode.replace(")","");
		    rgbcode = rgbcode.split(",");
		    rgb.red =rgbcode[0];
		    rgb.green =rgbcode[1];
		    rgb.blue =rgbcode[2];
		    opacity = rgbcode[3];
		}
		return {rgb:"rgb("+rgb.red+","+ rgb.green +","+ rgb.blue+")",opacity:opacity};
	}    
    ,toRgba: function(hex,opacity){
        var rgb = {};
        if(hex.indexOf("#") == 0 && hex.indexOf(",") == -1){ //hex code argument
			var hexcode = hex.substring(1);
			rgb.red = this._hexToR(hexcode);
			rgb.blue = this._hexToB(hexcode);
			rgb.green = this._hexToG(hexcode);
		}
		if(!opacity) opacity = "1.0";
		return "rgba("+rgb.red+","+ rgb.green +","+ rgb.blue+"," + opacity+")";
    }
	/* thank you http://www.javascripter.net/faq/hextorgb.htm*/
	,_cutHex: function(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}
	,_hexToR:function(h){return parseInt((this._cutHex(h)).substring(0,2),16)}
	,_hexToG: function (h) {return parseInt((this._cutHex(h)).substring(2,4),16)}
	,_hexToB:function(h) {return parseInt((this._cutHex(h)).substring(4,6),16)}

};
var VismoUtils = {
	userAgent: navigator.userAgent.toLowerCase(),
	clone: function(obj){

        if(!obj) return obj;
        if(obj.appendChild) return obj;
	    if(obj == null || typeof(obj) != 'object')return obj;

	    var temp = new obj.constructor(); // changed (twice)

	    for(var key in obj){
	        //console.log(key);
	        temp[key] = VismoUtils.clone(obj[key]);
	        //console.log(temp[key])
	    }

	    return temp;

	}
	,invertYCoordinates: function(coords){
		var res = [];
		for(var i=0; i < coords.length; i++){
			var x = coords[i][0];
			var y = coords[i][1];
			res.push([x,-y]);
		}
		return res;
	},
	scrubNode: function(e)
    {
    	if(!VismoUtils.browser.isIE)
    		return;
    	var att = e.attributes;
    	if(att) {
    		for(var t=0; t<att.length; t++) {
    			var n = att[t].name;
    			if(n !== "style" && (typeof e[n] === "function" || (typeof e[n] === "object" && e[n] != null))) {
    				try {
    					e[n] = null;
    				} catch(ex) {
    				}
    			}
    		}
    	}
    	var c = e.firstChild;
    	while(c) {
    		 VismoUtils.scrubNode(c);
    		c = c.nextSibling;
    	}
    }
    
    ,mergejsons: function(prop1,prop2){
	    
	    var res = {};
	    var i;
	    for(i in prop1){
	        res[i] = prop1[i];
	    }
	    for(i in prop2){
	        res[i] = prop1[i];
	    }
	    return res;
	    
	}
};

VismoUtils.browser= {
		isIE: VismoUtils.userAgent.indexOf("msie") != -1 && VismoUtils.userAgent.indexOf("opera") == -1,
		isGecko: VismoUtils.userAgent.indexOf("gecko") != -1,
		ieVersion: /MSIE (\d.\d)/i.exec(VismoUtils.userAgent), // config.browser.ieVersion[1], if it exists, will be the IE version string, eg "6.0"
		isSafari: VismoUtils.userAgent.indexOf("applewebkit") != -1,
		isBadSafari: !((new RegExp("[\u0150\u0170]","g")).test("\u0150")),
		firefoxDate: /gecko\/(\d{8})/i.exec(VismoUtils.userAgent), // config.browser.firefoxDate[1], if it exists, will be Firefox release date as "YYYYMMDD"
		isOpera: VismoUtils.userAgent.indexOf("opera") != -1,
		isLinux: VismoUtils.userAgent.indexOf("linux") != -1,
		isUnix: VismoUtils.userAgent.indexOf("x11") != -1,
		isMac: VismoUtils.userAgent.indexOf("mac") != -1,
		isWindows: VismoUtils.userAgent.indexOf("win") != -1
	};

if(VismoUtils.browser.isIE && VismoUtils.browser.ieVersion[1] == "6.0"){
VismoUtils.browser.isIE6 = true;

}

if(VismoUtils.browser.isIE){
	if (!document.namespaces['vismoShapeVml_']) {
	        document.namespaces.add('vismoShapeVml_', 'urn:schemas-microsoft-com:vml'/*,"#default#VML"*/);
	        
	}
	document.namespaces.add('xmlns', 'http://www.w3.org/1999/xhtml');
	document.namespaces.add('svg', 'http://www.w3.org/2000/svg');
	document.namespaces.add('xlink', 'http://www.w3.org/1999/xlink');

	  // Setup default CSS.  Only add one style sheet per document
	 if (!document.styleSheets['vismoShape']) {
	        var ss = document.createStyleSheet();
	        ss.owningElement.id = 'vismoShape';
	        ss.cssText = 'canvas{display:inline;overflow:hidden;' +
	            'text-align:left;}' +
	            'vismoShapeVml_\\: * {behavior:url(#default#VML);}';
	}
}
VismoUtils.svgSupport = function(){
        if(VismoUtils.browser.isIE){
                try {
                 var asv = new ActiveXObject("Adobe.SVGCtl");
                 return true;
                }
                catch(e){ }
        }
        else if(document.implementation) {
                if(VismoUtils.browser.isSafari) return true;
                return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Shape", "1.0");
        }



        return true;
};
/* 
Creates primitive shapes that can be rendered across most browsers
I am not very happy with the code that follows. It is not of the best standard and needs much improvement
coordinates are a string consisting of floats and move commands (M)
*/

var VismoShape = function(properties,coordinates){
    this._isVismoShape = true;
    this.options = {};
    if(!coordinates) {
        coordinates = properties.coordinates;
        delete properties["coordinates"];
    }
    this._optimise_cache = {};
    
	this.coordinates = {
		projected: false,
		normal: [],
		optimised: {},
		optimisedandprojected:{}
	};
	this.grid = {};
	this.width = 0;
	this.height =0;
	this.properties = {};
	this.setProperties(properties);
	//if(!this.properties.lineWidth)this.properties.lineWidth = "0.2";
	if(coordinates[0] && coordinates[0].length == 2){
		coordinates = VismoOptimisations.unpackCoordinates(coordinates);	
	}
	
	this._construct(properties,coordinates);
	this.browser =false;
	this.currentResolution = false;
	this.vml = false;
	this.unique_id = Math.random() + "_" + this.properties.id;
    this._scale = {x:1,y:1};
};



VismoShape.prototype={
    isCommand: function(i){
        if(i == 'M' || i =='c' || i =='q'){
            return true;
        }
        else{
            return false;
        }
    }
    ,clone: function(){
                var coords = this.getCoordinates("normal");
                var props = this.getProperties();
                var p = VismoUtils.clone(props);
                p.coordinates = coords;
                try{
                    //console.log(p);
                    return new VismoShape(p);
                }
                catch(e){
                    throw e;
                }
    }
    ,translate: function(x,y){
  	    var c = this.getCoordinates("normal");

  	    var newc = [];
  	    for(var i=0; i < c.length; i+=2){
  	         if(this.isCommand(c[i])) i+=1;
  	         var newx,newy;

  	        newx = c[i] + x;
  	        newy = c[i+1] + y;
  	        newc.push(newx);
  	        newc.push(newy);
  	    }

  	    this.setCoordinates(newc);
      }

  	,scale: function(x,y){
  	    this._scale.x = x;
  	    this._scale.y = y;
  	    var c = this.getCoordinates("normal");

  	    var newc = [];
  	    for(var i=0; i < c.length; i+=2){
  	        if(this.isCommand(c[i])) i+=1;
  	        var newx,newy;

  	        newx = c[i] * x;
  	        newy = c[i+1] * y;
  	        newc.push(newx);
  	        newc.push(newy);
  	    }

  	    this.setCoordinates(newc);
  	    return true;
  	}
	,resize: function(x,y){
	    var bb = this.getBoundingBox();
	    var newWidth = x *bb.width;
	    var newHeight = y * bb.height;
	    var offsetx = (bb.center.x * x) - bb.center.x;
	    var offsety = (bb.center.y * y)- bb.center.y;
	    this._scale.x = x;
	    this._scale.y = y;
	    var c = this.getCoordinates("normal");

	    var newc = [];
	    for(var i=0; i < c.length; i+=2){
	        var newx,newy;
	        
	        newx = c[i] * x;
	        newy = c[i+1] * y;
	        newx -= offsetx;
	        newy -= offsety;
	        newc.push(newx);
	        newc.push(newy);
	    }
	  
	    this.setCoordinates(newc);
	    return true;
	}
	,moveTo: function(x,y){
	    var st = this.properties.shape;
	    var dim = this.getDimensions();
	 
	    if(st == "point" || st == 'circle'){
	        this.setCoordinates([x,y,dim.width/2, dim.height/2]);
	    }
	    else if(st == 'polygon' ||st == 'path'){
	        var bb = this.getBoundingBox();
	        var movex = x - bb.center.x;
	        var movey = y - bb.center.y;
	        
	        var c = this.getCoordinates("normal");
	        var newc = [];
	        for(var i=0; i < c.length; i+=2){
	            if(this.isCommand(c[i])) i +=1;
	            newc.push(c[i]+movex);
	            newc.push(c[i+1]+movey);
	        }
	        this.setCoordinates(newc);
	    }
	}
	,getShape: function(){
		return this.getProperty("shape");
    }
	,setProperties: function(properties){
	    var newprops = VismoUtils.clone(properties);
		var i;
		for(i in newprops){
		        this.setProperty(i,newprops[i]);
		}
		if(!newprops["z-index"]){
		    this.setProperty("z-index","0");
		}
		if(!newprops.stroke){
			this.setProperty("stroke",'#000000');		
		}
		
	}
	,getBoundingBox: function(){ /* returns untransformed bounding box */
	    return this.grid;
	}

	,render: function(canvas,transformation,projection,optimisations, browser){
	    VismoTimer.start("VismoShape.render");
        var lw = this.properties.lineWidth;
        if(projection) {this._applyProjection(projection,transformation);}
        if(lw && transformation && transformation.scale && transformation.scale.x){
            //this.properties.lineWidth = lw / transformation.scale.x;
        }
		var mode = this.getRenderMode(canvas);
		if(mode == 'ie'){
		     this.render_ie(canvas,transformation,projection,optimisations, browser);    
		}
		else{	
	        this.render_canvas(canvas,transformation,projection,optimisations, browser);
	        //this.render = this.render_canvas;
		}
		this.properties.lineWidth = lw;
		VismoTimer.end("VismoShape.render");	
	}
	,render_ie: function(canvas,transformation,projection,optimisations, browser){
	    
	    VismoTimer.start("VismoShape.render_ie");
	    if(this.properties.hidden){
		        if(this.vml)this.vml.clear();
		        return;
		}
	    if(this.vml===false){ //not created
            this.vml = new VismoVector(this,canvas);
            this.donevml = true;
            
        }
        
           

		this.vml.render(canvas,transformation,projection);
        VismoTimer.end("VismoShape.render_ie");
        return;
	}
	,render_canvas: function(canvas,transformation,projection,optimisations, browser){
		VismoTimer.start("VismoShape.render_canvas");
		var c;
		if(this.properties.hidden) {
		    return;
    	}
    	var vismoShape = this;
    	var ctx = canvas.getContext('2d');
		if(!ctx) return;
		ctx.save();
		if(transformation){
			var o = transformation.origin;
			var tr = transformation.translate;
			var s = transformation.scale;
			var r = transformation.rotate;
	
				if(o)ctx.translate(o.x,o.y);
				if(s)ctx.scale(s.x,s.y);
				if(tr)ctx.translate(tr.x,tr.y);
			
			if(r && r.x)ctx.rotate(r.x);
		}

		VismoCanvasRenderer.renderShape(canvas,vismoShape);
		ctx.restore();
		VismoTimer.end("VismoShape.render_canvas");
	}
	,getTransformation: function(){
	    var transform= this.getProperty("transformation");
	   
	    if(!transform) transform = {translate:false,scale:false};
   		if(!transform.translate)transform.translate = {x:0,y:0};
   		if(!transform.translate.x)transform.translate.x = 0;
   		if(!transform.translate.y)transform.translate.y = 0;
   		if(!transform.scale)transform.scale= {x:1,y:1};
   		if(!transform.scale.x)transform.scale.x = 1;
   		if(!transform.scale.y)transform.scale.y = 1;
	       
	       return transform;
	}
	
    ,setTransformation: function(transformation){
	    this.setProperty("transformation",transformation);
	    this._calculateBounds();
	}
	,setCoordinates: function(coordinates,type){
	    if(this.properties.shape == 'circle' || this.properties.shape == 'point'){
	        if(coordinates.length == 2 && this.coordinates.normal){
	            coordinates.push(this.coordinates.normal[2]);
	            coordinates.push(this.coordinates.normal[3]);
	        }
	    }	        
        var good = [];
        for(var i=0; i < coordinates.length; i++){
            if(coordinates[i] +"" !='NaN')
            {good.push(coordinates[i]);}
        }
     
        if(good.length < 2) {
                throw "cannot set coordinates for VismoShape not enough good coordinates given (coordinates may contain non-number elements)" + coordinates.toString();
        }
        coordinates = good;
                
                
		if(type == 'projected'){this.coordinates.projected = coordinates;this._calculateBounds(coordinates);return;}
		
		this.coordinates.normal = coordinates;
	
		if(this.vml)this.vml.coordinatesHaveChanged();
		this.coordinates.projected= false;
		var i;
		for(i in this.coordinates_optimised){
			delete this.coordinates_optimised[i];
		}
		var j;
		for(j in this.coordinates.optimisedandprojected){
			delete this.coordinates.optimisedandprojected[j];
		}		
		this.grid = {}; //an enclosing grid
		
		if(this.vml) this.vml.path = false; //reset path so recalculation will occur
		var st = this.getShape();
		if(st== 'circle' || st == 'point'){
		    this.setRadius(coordinates[2],coordinates[3]);
		    //else this.setDimensions(this.options.pointsize,this.options.pointsize);
		}
		this._calculateBounds();

	}
	,getCoordinates: function(type){
	    if(!type){
	        if(this.coordinates.projected){
	            return this.coordinates.projected;
	        }
	        else return this.coordinates.normal;
	    }
		if(type == 'normal') return this.coordinates.normal;
	    if(type == 'projected') return this.coordinates.projected;
		
		var resolution = this.currentResolution;
		if(this.coordinates.projected) {
			if(this.browser != 'ie' && resolution){
				return this._simplifyCoordinates(resolution,this.coordinates.projected);
				var opt=this.coordinates.optimisedandprojected;
				if(!opt[resolution]) opt[resolution] =  this._simplifyCoordinates(resolution,this.coordinates.projected);
				
				return opt[resolution];
			}		
			return this.coordinates.projected;
		}
		else{
			if(this.browser != 'ie' && resolution){
				var opt=this.coordinates.optimised;
				if(!opt[resolution]) opt[resolution] =  this._simplifyCoordinates(resolution,this.coordinates.normal);
				
				return opt[resolution];
			}	
			return this.coordinates.normal;
		}
	}
	,getProperties: function(){
	    return this.properties;
	}
	,getRenderMode: function(canvas){
	    VismoTimer.start("VismoShape.getRenderMode");
	    if(!this.browser){
		    if(!canvas.getContext) {				
		                this.browser = "ie";
			}
				
			else 	this.browser = "good";
		}
		VismoTimer.end("VismoShape.getRenderMode");
		return this.browser;
	}
	
	,setProperty: function(name,value){
		this.properties[name] = value;
		 //console.log("Reset",name,this);
		 if(this.vml) {
		    this.vml.nochange = false;
	       
	    }
	    if(name == 'z-index'){ //organise a re-sort for the z-index property to kick in
	      if(Vismo.store.Canvas[this._canvasref]){
	        Vismo.store.Canvas[this._canvasref].needsSort = true;
	      }
	    }
	}
	,getProperty: function(name){
		return this.properties[name];
	}

	,_calculateBounds: function(coords){
	    VismoTimer.start("VismoShapes._calculateBounds");
	    var that = this;
		var st = this.getShape();
		var transform = this.getTransformation();

        
		if(st == 'path'){
			this.grid = {x1:0,x2:1,y1:0,y2:1,center:{x:0,y:0}};
			return;
		}
		else if(st == 'point' || st == 'circle' | st == 'image' | st == 'domElement'){
				var coords = this.getCoordinates("normal").clone();
				var x = coords[0]; var y = coords[1]; 
				var dim = this.getDimensions();
				this.grid.center = {};
				this.grid.center.x = x;
				this.grid.center.y = y;
				
				if(transform){
				        if(transform.translate){
				                var tran_x = transform.translate.x;
				                var tran_y =  transform.translate.y;
				                
				                this.grid.center.x += tran_x;
				                this.grid.center.y += tran_y;
				        }
				        if(transform.scale){
				                dim.width *= transform.scale.x;
				                dim.height *= transform.scale.y;
				        }
				}
				var newx = this.grid.center.x;
				var newy = this.grid.center.y;
				var radiusw = dim.width / 2;
				var radiush = dim.height / 2;
				
				this.grid ={x1: newx -radiusw ,x2: newx + radiusw, y1: newy - radiush, y2: newy + radiush,center:{x:newx,y:newy},width: dim.width,height:dim.height};	

				
				//console.log(this.grid.center.x,this.coordinates.normal,this.properties.transformation);
				return;
		}
		
		if(!coords) coords = this.getCoordinates();
		if(coords.length < 2) return;
		this.grid.x1 = coords[0];
		this.grid.y1 = coords[1];
		this.grid.x2 = coords[0];
		this.grid.y2 = coords[1];
		
		this._deltas = []
		var d = this._deltas;

		var lastX, lastY;
		var index = 0;
	
		lastX = coords[0];
		lastY = coords[1];
		for(var i=0; i < coords.length-1; i+=2){
			var xPos = parseFloat(coords[i]); //long
			var yPos = parseFloat(coords[i+1]); //lat
			var deltax =xPos - lastX;
			var deltay= yPos - lastY;
			if(deltax < 0) deltax = - deltax;
			if(deltay < 0) deltay = -deltay;
			d.push(deltax);
			d.push(deltay);
			if(xPos < this.grid.x1) this.grid.x1 = xPos;
			if(yPos < this.grid.y1) this.grid.y1 = yPos;	
			if(xPos > this.grid.x2) this.grid.x2 = xPos;
			if(yPos > this.grid.y2) this.grid.y2 = yPos;
			
			lastX = xPos;
			lastY = yPos;
		}
		
		//this.grid.x2 *= transform.scale.x;
		//this.grid.y2 *= transform.scale.y;
		this.grid.width = (this.grid.x2 - this.grid.x1);
		this.grid.height = (this.grid.y2 - this.grid.y1);

		this.grid.center = {};
		this.grid.center.x = (this.grid.x2 - this.grid.x1) / 2 + this.grid.x1;
		this.grid.center.y = (this.grid.y2 - this.grid.y1) / 2 + this.grid.y1;
		
		//recalculate based on scaling
		this.grid.width *= transform.scale.x;
		this.grid.height *= transform.scale.y;
		this.grid.center.x += transform.translate.x;
		this.grid.center.y += transform.translate.y;
		
		var halfw = this.grid.width / 2;
		var halfh = this.grid.height /2;
		this.grid.x1 = this.grid.center.x - halfw;
		this.grid.x2 = this.grid.center.x + halfw;
		this.grid.y1 = this.grid.center.y - halfh;
		this.grid.y2 = this.grid.center.y + halfh;
		
/*		if(transform && transform.translate){
		        var trans = transform.translate;
		        this.grid.center.x += trans.x;
		        this.grid.center.y += trans.y;
		}
*/
		this.grid.x1 = this.grid.center.x - (this.grid.width / 2);
		this.grid.x2 = this.grid.center.x + (this.grid.width /2);
		this.grid.y1 = this.grid.center.y - (this.grid.height/2);
		this.grid.y2 = this.grid.center.y +(this.grid.height/2);
		
		VismoTimer.end("VismoShapes._calculateBounds");
		//if(st == 'path') console.log(this,this.grid);
	}

    ,getCanvas: function(){
        return this.vismoCanvas;
    }
	,setRadius: function(rx,ry){
	    if(!ry) ry = rx;
		this.setDimensions(rx*2,ry*2);
	}
	,getRadius: function(){
		if(this.width) return this.width /2;
	    else{
	        var bb = this.getBoundingBox();
		    return bb.width / 2;
		}
		
	}
	,setDimensions: function(width,height){
		this.width = width;
		this.height = height;
		if(this.properties.shape=='circle'){
		    for(var j in this.coordinates){
		        var c = this.coordinates[j];
		        if(c){
		            c[2] = width/2;
		        }
		    }
		    //console.log(this);
		}
		else{
		    
		}
		if(this.vml) this.vml.path = false;
		
		this._calculateBounds();
	    
	}
	,getDimensions: function(){
		return {width: this.width, height: this.height};
	}
	
	,_construct: function(properties, coordinates){
	    VismoTimer.start("VismoShapes._construct");
		var shapetype =properties.shape; 
		if(!shapetype) shapetype = 'polygon';
		if(shapetype == 'point' || shapetype == 'circle'){
			var radiusw,radiush;
			if(coordinates[2]) radiusw = coordinates[2];
			else radiusw = 2.5;
			
			if(coordinates[3]) radiush= coordinates[3];
			else radiush = radiusw;
			
			this.setDimensions(radiusw*2,radiush*2);
			this.setCoordinates([coordinates[0],coordinates[1],radiusw,radiush]);
			
		}
		else if(shapetype == 'polygon' || shapetype == 'path')
		{
			this.setCoordinates(coordinates);
		}
		else if(shapetype == 'domElement'){
					       
		        var w = jQuery(this.getProperty("element")).width(); 
		        var h = jQuery(this.getProperty("element")).height(); 
		        this.setDimensions(w,h);
		        this.setCoordinates(coordinates);

		}
		else if(shapetype == 'image'){
			var src = this.getProperty("src");
			if(!src) throw "all images must carry a property src at minimum";
			var image = new Image();
			image.src= src;
			this.image = image;
			var vismoShape = this;
			var w = vismoShape.getProperty("width"); h=  vismoShape.getProperty("height");
			if(coordinates.length > 2){
				w = coordinates[2]; h = coordinates[3];
			}
			image.onload = function(){
				if(!w && !h){
					vismoShape.setDimensions(w,h);
					vismoShape.setCoordinates([coordinates[0],coordinates[1]]);
				}
				vismoShape.ready = true;
			};
			if(image.complete)vismoShape.ready = true;
		
			vismoShape.setDimensions(w,h);
			vismoShape.setCoordinates([coordinates[0],coordinates[1]]);	
			
		}
		else{
			console.log("don't know how to construct basic shape " + properties.shape);
		}		
		VismoTimer.end("VismoShapes._construct");	
		
	}	

	,_applyProjection: function(projection,transformation){
        //console.log("apply projection to",this.properties.shape);
	    VismoTimer.start("VismoShapes._applyProjection");
		var c = this.getCoordinates('normal');
	
		if(!projection || !projection.xy) return c;
	
		if(projection.init) projection.init();
		var newc = [];
		for(var i=0; i < c.length-1; i+=2){
			var moved = false;
			if(!VismoShapeUtils._isCoordinate(c[i])){
				i+= 1;
			}
			var x = parseFloat(c[i]);
			var y = parseFloat(c[i+1]);
			var newx,newy;
			var projectedCoordinate = projection.xy(c[i],c[i+1],transformation);
			if(projectedCoordinate.x && projectedCoordinate.y){
				newx= projectedCoordinate.x;
				newy= projectedCoordinate.y;
			
				if(projectedCoordinate.move){
					moved  =true;
				}
			
				cok = true;
				//check we haven't wrapped around world (For flat projections sss)
				if(!projection.nowrap){
					var diff;
					if(newx > x) diff = newx - x;
					if(x > newx) diff = x - newx;
					if(diff > 100) cok = false; //too extreme change
				}
			
				if(cok){
					if(VismoShapeUtils._isCoordinate(x) && VismoShapeUtils._isCoordinate(y)){
						if(moved){
							newc.push("M");
						}
						newc.push(newx);
						newc.push(newy);
					}

				}
			}	
		}	
		if(newc.length < 2) return;
		this.setCoordinates(newc,"projected");
		this._calculateBounds(newc);
		
		VismoTimer.end("VismoShapes._applyProjection");
		return newc;
	}


	
	,optimise: function(canvas,transformation,projection,justcompute){
	    
	    VismoTimer.start("VismoShapes.optimise");
	    var ocache = this._optimise_cache;

	    
	    var cid = transformation["cache"]["id1"];
	    var cid2 =transformation["cache"]["id2"];
	    
	    if(this._scale.x > 1){
	        var newx,newy;
	        newx = this._scale.x  * transformation.scale.x;
	        newy = this._scale.y  * transformation.scale.y;
	        cid = newx + ","+newy;
	    }
	    if(!ocache[cid]) ocache[cid] = {};
	    
        if(typeof(ocache[cid][cid2]) != "undefined"){
	        return ocache[cid][cid2];
        }
	    
	    var shapetype = this.properties.shape;
	    if(shapetype == "path") {
	        ocache[cid][cid2] = true;
	        VismoTimer.end("VismoShapes.optimise");
	        return true;
		}
		if(transformation && transformation.scale) {
		    this.currentResolution = Math.min(transformation.scale.x, transformation.scale.y);
		}
		
		
		if(shapetype != 'point' && shapetype != 'path' && shapetype !="domElement"){ //check if worth drawing				
			if(VismoOptimisations.vismoShapeIsTooSmall(this,transformation)) {
				if(!justcompute && this.vml)this.vml.clear();
				ocache[cid][cid2] = false;
				VismoTimer.end("VismoShapes.optimise");
				return false;	
			}	
		}
		
		if(!VismoOptimisations.vismoShapeIsInVisibleArea(this,canvas,transformation,projection)){
			if(!justcompute && this.vml)this.vml.clear();
			ocache[cid][cid2] = false;
			VismoTimer.end("VismoShapes.optimise");
			return false;	
		}
		ocache[cid][cid2] = true;
		VismoTimer.end("VismoShapes.optimise");
		return true;
	}
	,optimise_ie: function(canvas,transformation,projection){	
	    VismoTimer.start("VismoShape.optimise_ie");
	    var ocache = this._optimise_cache;
	    var cid = transformation["cache"]["id1"];
        if(typeof(ocache[cid]) != "undefined"){
	        return ocache[cid];
        }
        VismoOptimisations.minradius = 6;
	    var sh = this.properties.shape;
		if(sh == 'path' || sh == 'point') {
		        ocache[cid] =true;
               return true;
        }
        
		if(VismoOptimisations.vismoShapeIsTooSmall(this,transformation)) {
				if(this.vml)this.vml.clear();
                VismoTimer.end("VismoShape.optimise_ie");
				ocache[cid] =false;
				return false;		
		}
        ocache[cid] =true;
        VismoTimer.end("VismoShape.optimise_ie");
		return true;
	}
	
	,_simplifyCoordinates: function(scaleFactor,coordinates){// **
		VismoTimer.start("VismoShapes._simplifyCoordinates");
		if(this.getProperty("shape") == 'path') return coordinates;
		/*will use http://www.jarno.demon.nl/polygon.htm#ref2 */
		if(!coordinates) throw "give me some coordinates!";
		var originals =coordinates;
		var tolerance;
		var bb = this.getBoundingBox();
		
		var d;
		if(bb.width < bb.height) d = bb.width;
		else d = bb.height;
		tolerance = (d/4) / scaleFactor;
		
		coordinates = VismoOptimisations.packCoordinates(coordinates);
		coordinates = VismoOptimisations.douglasPeucker(coordinates,tolerance);
		
		coordinates = VismoOptimisations.unpackCoordinates(coordinates);	
		
		var diff = originals.length - coordinates.length;
		
		VismoTimer.end("VismoShapes._simplifyCoordinates");
		if(diff < 10) return originals;
		else 
		return coordinates;	
	}


};/*
A package for rendering geojson polygon and point features easily to create maps
*/
var GeoTag = function(longitude,latitude,properties){
	var geo = {};
	geo.type = "feature";
	geo.geometry = {};
	geo.geometry.type = "point";
	geo.geometry.coordinates = [longitude,latitude];
	geo.properties = properties;
	return geo;	
};
var GeoPath = function(coords,properties){
    var geo = {geometry:{type:"LineString"},type:"feature",properties:properties};
    if(coords && coords[0].length > 1){
        geo.geometry.coordinates = coords;
    }
    else{
        var newcoords = [];
        for(var i=0; i < coords.length; i+=2){
            newcoords.push([coords[i],coords[i+1]]);
        }
        //console.log("built",newcoords,"from",coords);
        geo.geometry.coordinates = newcoords;
    }
    return geo;
}

var VismoMap = function(wrapper,options){  
    
    if(wrapper.length){ //for jquery
        var result = [];
        for(var i=0; i < wrapper.length; i++){
            var x = new VismoMap(wrapper[i],options);
            result.push(x);
        }
        return x;
    }
    
	if(typeof wrapper == 'string') wrapper = document.getElementById(wrapper);
	else wrapper = wrapper;
		
	this.wrapper = wrapper;
	wrapper.vismoMap = this;
	//wrapper.style.position = "relative";
	var that = this;
	this.settings = {};
	var w= jQuery(wrapper).width();
	var h= jQuery(wrapper).height();
	jQuery(wrapper).css({width:w,height:h});
	
	this.feature_reference = {};
	if(!options) options = {};


	var that = this;
	var handler = function(t){
	    that.transform(t);
	}
	//if(!options.vismoController) options.vismoController = {};
	if(options.vismoController)options.vismoController.handler = handler;

	this.vismoCanvas = new VismoCanvas(wrapper,options);
	this.controller = this.vismoCanvas.vismoController;
	
	//run stuff
	if(this.controller)this.transform(this.controller.transformation); //set initial transformation
	this._fittocanvas = true;
	this.geofeatures = {};
	this.features = [];
	this.clear();
	
	var proj = options.projection;
	var eMap = this;
	this._hijackMouseFunctions();
	if(options.tooltip){
	    this.vismoCanvas.addTooltip(function(el,s){
	        if(s){
	        el.innerHTML = s.getProperty("name");
            }
	    });
	    
	}
		this.mouse({down:options.mousedown,up:options.mouseup,move:options.move,dblclick:options.dblclick,keypress:options.keypress});
	
	var eMap = this;
	if(proj){
		if(proj == 'globe' || proj == 'spinnyglobe'){
			eMap = new VismoGlobe(this);
			if(proj == 'spinnyglobe'){
				eMap.toggleSpin();
			}
		}
		if(proj == 'google'){
			eMap.settings.projection = VismoSlippyMap.prototype.getGoogleMercatorProjection();
		}
		else if(proj == 'slippystaticmap'){
			eMap = new VismoSlippyMap(this);					
		}
		
	}
	
	if(options.geojson){
	    this.drawFromGeojson(options.geojson,options.fullscreen);
	}
	else if(options.georss){
	    this.drawFromGeojson(VismoConversion.geoRssToGeoJson(options.georss),options.fullscreen);
	}
	else if(options.kml){
	    this.drawFromGeojson(VismoConversion.kmlToGeoJson(options.kml),options.fullscreen);
	}
	return eMap;
};  
VismoMap.prototype = {
	setTransparency: function(args){
	    var alpha = arguments[0];
		this.vismoCanvas.setTransparency(alpha);
	}
	,getVismoShapes: function(args){
		return this.vismoCanvas.getMemory();
	}
	,resize: function(args){
	    var width = arguments[0];
	    var height = arguments[1];
		this.wrapper.style.width = width+"px";
		this.wrapper.style.height = height +"px";
		var  t=this.getTransformation();
		t.origin.x = width / 2;
		t.origin.y = height / 2;
		this.setTransformation(t);
		this.vismoCanvas.resize(width,height);

		this.clear();

	}
	,getProjection: function(args){
		return this.settings.projection;
	}
	,setProjection: function(args){
	    var projection = arguments[0];
		this.settings.projection = projection;

	}
	,clear: function(args){ /* does this work in IE? */
		var deleteMemory = arguments[0];
		this.vismoCanvas.clear(deleteMemory);
	},
	
	drawFromGeojson: function(args){
        var geojson = arguments[0];
        var autosize = arguments[1];
			if(typeof geojson == 'string'){
				geojson = eval('(' +geojson+ ')');
			}
							
			this._lastgeojson = geojson;
			if(autosize){
			 	var t = VismoMapUtils.fitgeojsontocanvas(geojson,this.wrapper);

				var p =this.getProjection();
				if(p && p.name == "GLOBE") {
					t.translate = {x:0,y:0};
				}
					
				this.controller.setTransformation(t);
			}
		
			var type =geojson.type.toLowerCase();		
	 
			if(type == "featurecollection"){
				var features = geojson.features;
				this.drawGeoJsonFeatures(features);
			}  else if(type =='feature') {
				this.drawGeoJsonFeature(geojson);
			} else {
				console.log("only feature collections currently supported");
			}

			this.render();
			
	},
	add: function(feature){
	    this.drawGeoJsonFeature(feature,feature.properties);
	    this.render();
	}
	,drawFromGeojsonFile: function(args){
	    var file = arguments[0];
		var that = this;
		var callback = function(status,params,responseText,url,xhr){
		
			that.drawFromGeojson(responseText);
		};
		VismoFileUtils.loadRemoteFile(file,callback);
	}

	,getTransformation: function(args){
		if(!this.transformation){
			return false;
		}
		else
			return this.transformation;
	}
	,setTransformation: function(args){
	    var transformation = arguments[0];
		if(typeof transformation.translate.x != 'number'||typeof transformation.translate.y != 'number') throw "bad transformation translate given ";
		if(typeof transformation.scale.x != 'number'||typeof transformation.scale.y != 'number') throw "bad transformation scale given ";
		
		this.controller.setTransformation(transformation);
	}
	,moveTo: function(args){
	    var longitude= arguments[0];
	    var latitude = arguments[1];
	    var zoom = arguments[2];
		var newt = {translate:{},scale:{}};
		var transformation =this.getTransformation();
		
		var newxy={};
		newxy.x = parseFloat(longitude);
		newxy.y = parseFloat(latitude);
		
		if(this.settings.projection){
		 	newxy = this.settings.projection.xy(newxy.x,newxy.y,transformation);
		}
		newt.translate.x = - newxy.x;
		newt.translate.y = newxy.y;
		
		if(!zoom){
			zoom =transformation.scale.x;
		}
		else{
			zoom = parseFloat(zoom);
		}
		newt.scale.x = zoom;
		newt.scale.y = zoom;
		this.controller.setTransformation(newt)
		
	}

	,redraw: function(args){
		this.render();	

	    //alert("average VML render"+ VismoVector.rstats);
	    //alert("total average VML render time"+ VismoVector.rstats * VismoVector.rnum);
	},
		
	transform: function(args){
	    var transformation = arguments[0];
		//console.log(arguments);
		var w =parseInt(this.wrapper.style.width);
		var h = parseInt(this.wrapper.style.height);
		var t =transformation.translate;
		var s = transformation.scale;
	
		this.transformation = transformation;
		/*if(!transformation.origin){
			this.transformation.origin = {};
			var origin = this.transformation.origin;
			origin.x =w / 2;
			origin.y =h / 2;
		}*/
		
		if(s.x < 0.5) s.x = 0.5;
		if(s.y < 0.5) s.y = 0.5;
		
		if(t.x > 180) t.x = 180; //t.x=Math.min(t.x, 180)
		if(t.x < -180) t.x = -180;
		
		if(t.y > 85.0511) t.y = 85.0511;
		if(t.y < -85.0511) t.y = -85.0511;
		
		if(!this.transformation.rotate){
				this.transformation.rotate = {x:0,y:0,z:0};
		}
			
		
		var that = this;
		var f = function(args){
		    that.vismoCanvas.setTransformation(that.transformation);
		    that.redraw();
		}
		window.setTimeout(f,0);

	},


	/*onmouseup and ove are functions with following parameters:
		e,shape,mouse,longitude_latitude,feature
		
	*/
	mouse: function(args){
 	    if(!args){
	        return {up: this.onmouseup, down: this.onmousedown, move: this.onmousemove, dblclick: this.ondblclick,keypress:this.onkeypress};
	    }
			if(args.move)this.onmousemove =args.move;
			if(args.up)this.onmouseup = args.up;
			if(args.down)this.onmouseup = args.down;
			if(args.keypress) this.onkeypress = args.keypress;
			if(args.dblclick) this.ondblClick = args.dblclick;
	}

	,_hijackMouseFunctions: function(args){
	        var eMap = this;
	        var getParameters = function(e){
			var result = {};
			var code;
			if (e.which) code =e.which;
			else if (e.keyCode) code = e.keyCode;
			var character;
			if(code) character = String.fromCharCode(code);	
			var t = VismoClickingUtils.resolveTargetWithVismo(e);
			if(t && t.getAttribute("class") == 'vismoControl') return false;
			var shape = eMap.vismoCanvas.getShapeAtClick(e);
			if(shape) {
				result.shape = shape;
				result.feature = eMap.geofeatures[eMap.vismoCanvas.getMemoryID(shape)];
			}
		
			
			var pos = VismoClickingUtils.getMouseFromEvent(e);
			var x =pos.x;
			var y = pos.y;
			result.mouse = pos;
			result.longitude_latitude = VismoMapUtils.getLongLatFromMouse(x,y,eMap);
			result.event = e;
			result.keypressed = character;
			return result;
			
		};
		
		 var md = function(e,s){
	                var r = getParameters(e);
	                if(eMap.onmousedown) eMap.onmousedown(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);
	        };
	        
	        var mu = function(e,s){
	                var r = getParameters(e);
	                if(eMap.onmouseup) eMap.onmouseup(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);
	        };
	        var mm = function(e,s){
	            
	                var r = getParameters(e);
	                if(eMap.onmousemove) eMap.onmousemove(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);	                
	        };
	        var dbl = function(e,s){
	                var r = getParameters(e);
        	        if(eMap.ondblClick) eMap.ondblClick(e,s,r.mouse,r.longitude_latitude,r.feature,r.key,eMap);
	        };
	        var key = function(e,s){
	                var r = getParameters(e);
                        if(eMap.onkeypress) eMap.onkeypress(e,s,r.mouse,r.longtitude_latitude,r.feature,r.key,eMap);
	        }
	        this.vismoCanvas.mouse({mousedown:md,mouseup:mu,mousemove:mm,dblclick:dbl,keypress:key});
	}

	,render: function(args){
	    var d1 = new Date();
	    var flag = arguments[0];
		var tran =this.transformation;

		var that = this;

		this.vismoCanvas.render(this.settings.projection);
		if(this.settings.afterRender) {
			this.settings.afterRender(tran);
			
		}
		var t = document.getElementById(that.wrapper.id + "_statustext");
		if(t) {
			t.parentNode.removeChild(t);	
		}
		var d2 = new Date();
		var id="mapRender";
		if(!VismoTimer[id]) VismoTimer[id] = 0;
		VismoTimer[id] += (d2 - d1);
		
		
		
	
	},
	
	getFeatures: function(args){
	       if(arguments[0] && this.features[arguments[0]]) return this.features[arguments[0]];
	       return this.features;
	}
	,drawGeoJsonFeature: function(args){
	    var featuredata = arguments[0];
	    var props = arguments[1];
		var feature = new VismoMap.Feature(featuredata,props);		
		var s = feature.getVismoShapes();		
		for(var i=0; i < s.length; i++){
			this.vismoCanvas.add(s[i]);
			//this.geofeatures[this.vismoCanvas.getMemoryID(s[i])] = feature;
		}	
         this.features.push(feature);
	},
	drawGeoJsonFeatures: function(args){
	    var features = arguments[0];
			var avg1 = 0;
				
			for(var i=0; i < features.length; i++){
			
				this.drawGeoJsonFeature(features[i],{featureid:i});
			}

	}
	,getVismoCanvas: function(args){
	        return this.vismoCanvas;
	}
};


VismoMap.Feature = function(feature,props){
	this.init(feature,props);
};

VismoMap.Feature.prototype = {
	init: function(args){
	    var feature = arguments[0];
	    if(arguments[1])extra_properties = arguments[1];
	    else extra_properties = {};
		this.properties = feature.properties;
		this.geometry = feature.geometry;
		this.outers = [];
		this.vismoShapes = [];
		var geometry = this.geometry;
		var type =geometry.type.toLowerCase();

		if(type == 'multipolygon'){
			this._drawGeoJsonMultiPolygonFeature(feature.geometry.coordinates,feature);
		}
		else if(type =='linestring'){
		    this._drawGeoJsonLineStringFeature(feature);
		}
		else if(type=='multilinestring' || type == 'multipoint' || type=='geometrycollection'){
			console.log(type + " not supported yet");
		}

		else if(type == 'polygon'){
			this._drawGeoJsonPolygonFeature(feature.geometry.coordinates,feature);
		}
		else if(type == 'point'){
			this._drawGeoJsonPointFeature(feature.geometry.coordinates,feature);				
		}
		else {	
			//console.log("unsupported geojson geometry type " + geometry.type);
		}		
        var x = this.getVismoShapes();
        var f;
  
        for(f in extra_properties){
    
             for(var i=0; i < x.length; i++){
                x[i].setProperty(f,extra_properties[f]);
            }
        }
	}
	,addOuterVismoShape: function(args){
		var shape = arguments[0];
		this.outers.push(shape);
	}
	,getOuterVismoShapes: function(args){
		return this.outers;
	}
	,addVismoShape: function(args){
	    var vismoShape = arguments[0];
		this.vismoShapes.push(vismoShape);
	}
	,getVismoShapes: function(args){
		return this.vismoShapes;
	}
	,_drawGeoJsonLineStringFeature: function(args){
	    var feature = arguments[0];
	    var coordinates = feature.geometry.coordinates;
	    var p = feature.properties;
	    if(!p) p = {};
	    p.shape = "path";
	    p.coordinates = [];
	    //console.log(feature,":)");
	    for(var i=0; i < coordinates.length;i++){
	        var xy =coordinates[i];
	        p.coordinates.push(xy[0]);
	        p.coordinates.push(-xy[1]);
	        
	    } 
	    var s = new VismoShape(p);
	    this.addVismoShape(s);
	    return s;
	    
	}
	,_drawGeoJsonMultiPolygonFeature: function(args){
	    var coordinates=  arguments[0];
	    var feature = arguments[1];
		var outer;
		
		for(var i=0; i < coordinates.length; i++){ //it's a list of polygons!
			var s = this._drawGeoJsonPolygonFeature(coordinates[i],feature,i);
			
		}
		
	},	
	_drawGeoJsonPolygonFeature: function(args){
        var coordinates=  arguments[0];
	    var feature = arguments[1];
	    var featureid = arguments[2];
		var p = feature.properties;
		p.shape = 'polygon';
		//console.log(coordinates[0]);
		
		var outer = false;
		for(var j=0; j< coordinates.length; j++){//identify and create each polygon
			var coords =coordinates[j];	
			coords = VismoUtils.invertYCoordinates(coords);
			var s = new VismoShape(p,coords);
			s.properties.geometryid = featureid;
			s.properties.geometryid2 = j;
			this.addVismoShape(s);
		}
		return outer;		
		
	},
	_drawGeoJsonPointFeature: function(args){
	    var coordinates=  arguments[0];
	    var feature = arguments[1];

		var p = feature.properties;
		p.shape = 'point';
		coordinates[1] = -coordinates[1];
		var s = new VismoShape(p,coordinates);
		this.addVismoShape(s);
	}
	,setProperty: function(args){
	    var id = arguments[0];
	    var val = arguments[1];
	    var shapes = this.getVismoShapes();
	    for(var i=0; i < shapes.length;i++){
	        shapes[i].setProperty(id,val);
	    }
	}
};
/*Extends VismoMaps to provide tiled background */
var VismoGlobe=  function(eMap){
	var i;
	for(i in VismoGlobe.prototype){
		eMap[i] = VismoGlobe.prototype[i];
	}	
	
	eMap.setGlobeProjection("GLOBE");
	return eMap;
	
};

VismoGlobe.prototype = {
	setGlobeProjection: function(){
		var vismomap = this;
		vismomap._fittocanvas = false;
		this.settings.beforeRender = function(t){
				vismomap._createGlobe(vismomap.getProjection().getRadius(t.scale));
		};
		
		this.settings.projection= {
				name: "GLOBE",
				nowrap:true,
				radius: 10,
				direction: 0
				,init: function(){
					this.direction = 0;
				}
				,getRadius: function(){
					return this.radius;
				}
				,inversexy: function(x,y,t){
						var radius =this.getRadius(t.scale);
						var res = VismoMapUtils._undospherify(x,y,t,radius);
						return res;
				}
				,xy: function(x,y,t){
					
					var radius =this.getRadius(t.scale);
					if(!radius || !x || !y || !t) return {x:x,y:y};
					var res = VismoMapUtils._spherifycoordinate(x,y,t,radius);
					/*
					if(res.movedNorth && this.direction >= 0){
						this.direction = -1;
						res.move= true;
					}
					else if(res.movedSouth && this.direction <= 0){
						this.direction = 1;
						res.move = true;
					}
					
					if(res.y > radius - 10 || res.y < 10-radius){
						
						res.y = false;
					}*/
					return res;
				}
		};
		
		var heightR = parseInt(vismomap.wrapper.style.height)  /2;
		var widthR= parseInt(vismomap.wrapper.style.width) /2;
		if(widthR > heightR){
			this.settings.projection.radius = heightR;
		}
		else{
			this.settings.projection.radius = widthR;
		}
		
	
		
	}
	,toggleSpin: function(){
		var eMap = this;
		var f = function(){
			var t = eMap.controller.transformation;
			if(!t.rotate) t.rotate = {};
			if(!t.rotate.z) t.rotate.z  = 0;
		
			t.rotate.z += 0.3;
			eMap.controller.setTransformation(t);
			window.setTimeout(f,600);
		};
		f();
	}
	,_createGlobe: function(radius){
		if(VismoUtils.browser.isIE) {return;}
		var ctx = this.vismoClicking.canvas.getContext('2d');
		if(!ctx) return;
		var t =this.controller.transformation;
		var tr =t.translate;
		var s = t.scale;
		var o = t.origin;
		ctx.save();	
		ctx.translate(o.x,o.y);
		ctx.scale(s.x,s.y);
		ctx.translate(tr.x,tr.y);
	
	
		var radgrad = ctx.createRadialGradient(0,0,10,0,0,radius);

		radgrad.addColorStop(0,"#AFDCEC");
		radgrad.addColorStop(0.5, '#00C9FF');
		radgrad.addColorStop(1, '#00B5E2');
		radgrad.addColorStop(1, 'rgba(0,201,255,0)');

		ctx.beginPath();
		ctx.arc(0, 0, radius, 0, Math.PI*2, true);
		ctx.closePath();
		ctx.fillStyle = radgrad;
		ctx.fill();
		ctx.restore();

	}
};



var VismoSlippyMap = function(vismoMap){	
	//vismoMap.resize(512,512);
	//console.log("in setup",vismoMap);
	this.loadedurls = {};
	this.tileserverurl = "http://tile.openstreetmap.org/";
	this.setupSlippyStaticMapLayer(vismoMap);

        vismoMap.oldDrawFromGeojson = vismoMap.drawFromGeojson
         vismoMap.drawFromGeojson = function(geojson,autosize){