<!--{{{-->
<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 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

----
Also see [[AdvancedOptions]]
<<importTiddlers>>
Trying to find out what twitter is all about
så er jeg vist kommet godt i gang..
<!--<<view title>>-->,"<!--<<view text>>-->",<!--<<view modified date>>-->
TweetID,Tweet,Date
<!--<<templateTiddlers CsvItemTemplate filter:"[tag[tweets]]">>-->
/***
|''Navn:''|DanishTranslationPlugin|
|''Beskrivelse:''|Translation of TiddlyWiki into Danish|
|''Forfatter:''|MartinBudden (mjbudden (at) gmail (dot) com)|
|''Kilde:''|www.example.com |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/association/locales/core/en/locale.en.js |
|''Version:''|0.3.7|
|''Dato:''|Jul 6, 2007|
|''Kommentarer:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''Licens:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]] |
|''~CoreVersion:''|2.4|
***/

//{{{
//--
//-- Translateable strings
//--

// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone

config.locale = "da"; // W3C language tag

if (config.options.txtUserName == 'YourName') // do not translate this line, but do translate the next line
	merge(config.options,{txtUserName: "DitNavn"});

merge(config.tasks,{
	save: {text: "gem", tooltip: "Gem dine ændringer til denne TiddlyWiki", action: saveChanges},
	sync: {text: "synk", tooltip: "Synkronisér ændringer med andre TiddlyWiki filer og servere", content: '<<sync>>'},
	importTask: {text: "importér", tooltip: "Importér tiddlers og plugins fra andre TiddlyWiki filer og servere", content: '<<importTiddlers>>'},
	tweak: {text: "Tilpas", tooltip: "Tilpas TiddlyWikis udseende og opførsel", content: '<<options>>'},
	upgrade: {text: "upgradér", tooltip: "Upgrader TiddlyWikis kerne kode", content: '<<upgrade>>'},
	plugins: {text: "udvidelser", tooltip: "Administrér installerede udvidelser", content: '<<plugins>>'}
});

// Options that can be set in the options panel and/or cookies
merge(config.optionsDesc,{
	txtUserName: "Brugernavn til signering af dine ændringer",
	chkRegExpSearch: "Avend almindelige udtryk til søgninger",
	chkCaseSensitiveSearch: "Forskel på store og små bogstaver",
	chkIncrementalSearch: "Bogstav for bogstav-søgning",
	chkAnimate: "Anvend animationer",
	chkSaveBackups: "Gem en backupfil når der gemmes ændringer",
	chkAutoSave: "Gem automatisk ændringer",
	chkGenerateAnRssFeed: "Lav et RSS feed når der gemmes ændringer",
	chkSaveEmptyTemplate: "Lav en tom skabelon når der gemmes ændringer",
	chkOpenInNewWindow: "Åben internet links i et nyt vindue",
	chkToggleLinks: "Når man klikker på et link i åbne tiddlers lukkes de",
	chkHttpReadOnly: "Skjul redigeringsværktøjer når den vises over HTTP",
	chkForceMinorUpdate: "Opdatér ikke brugernavn og dato når tiddlers bliver ændrede",
	chkConfirmDelete: "Bed om bekræftelse før tiddlers slettes",
	chkInsertTabs: "Brug tab tasten til at indsætte tab tegn istedet for at hoppe imellem felter",
	txtBackupFolder: "Navn på mappe til brug for backups",
	txtMaxEditRows: "Maximum antal af rækker i edit bokse",
	txtFileSystemCharSet: "Default tegnsæt til at gemme ændringer (Kun i Firefox/Mozilla)"});

merge(config.messages,{
	customConfigError: "Der opstod problemer ved loading af udvidelser. Se PluginManager for detaljer",
	pluginError: "Fejl: %0",
	pluginDisabled: "Ikke udført fordi det er slået fra via 'systemConfigDisable' tag",
	pluginForced: "Udført fordi det er tvunget via 'systemConfigForce' tag",
	pluginVersionError: "Ikke udført fordi denne udvidelse kræver en nyere udgave af TiddlyWiki",
	nothingSelected: "Intet er valgt. Du er nødt til at vælge en eller flere ting først",
	savedSnapshotError: "Det ser ud som om denne TiddlyWiki er blevet gemt forkert. Se venligst http://www.tiddlywiki.com/#DownloadSoftware for details",
	subtitleUnknown: "(ukendt)",
	undefinedTiddlerToolTip: "Tiddleren '%0' findes ikke endnu",
	shadowedTiddlerToolTip: "Tiddleren '%0' findes ikke endnu, men har en foruddefineret skygge værdi",
	tiddlerLinkTooltip: "%0 - %1, %2",
	externalLinkTooltip: "Internet link til %0",
	noTags: "Der er ingen taggede tiddlere",
	notFileUrlError: "Du er nødt til at gemme denne TiddlyWiki til en fil før du kan gemme ændringer",
	cantSaveError: "Det er ikke muligt at gemme ændringer. Mulige grunde indbefatter:\n- din browser understøtter det ikke (Firefox, Internet Explorer, Safari og Opera virker alle fint hvis de er konfigurerede korrekt)\n- stien til din TiddlyWiki fil indeholder ulovlige tegn\n- TiddlyWiki HTML filen er blevet flyttet eller omdøbt",
	invalidFileError: "Den originale fil '%0' lader ikke til at være en rigtig TiddlyWiki",
	backupSaved: "Backup gemt",
	backupFailed: "Det lykkedes IKKE at gemme en backup fil",
	rssSaved: "RSS feed gemt",
	rssFailed: "Det lykkedes IKKE at gemme et RSS feed",
	emptySaved: "Tom skabelon gemt",
	emptyFailed: "Det lykkedes IKKE at gemme en tom skabelon",
	mainSaved: "Hoved TiddlyWiki fil gemt",
	mainFailed: "Det lykkedes IKKE at gemme hoved TiddlyWiki filen. Dine ændringer er IKKE blevet gemt",
	macroError: "Fejl i makro <<\%0>>",
	macroErrorDetails: "Fejl ved udførsel af makro <<\%0>>:\n%1",
	missingMacro: "Ingen sådan makro",
	overwriteWarning: "En tiddler med navnet '%0' findes allerede. Vælg OK for at overskrive den",
	unsavedChangesWarning: "ADVARSEL! Der er ugemte æmdringer i TiddlyWikien\n\nVælg OK for at gemme\nVælg FORTRYD for at afvise",
	confirmExit: "--------------------------------\n\nDer er ugemte ændringer i TiddlyWikien. Hvis du fortsætter vil du miste disse ændringer\n\n--------------------------------",
	saveInstructions: "GemÆndringer",
	unsupportedTWFormat: "Ikke understøttet TiddlyWiki format '%0'",
	tiddlerSaveError: "Fejl ved forsøg på at gemme tiddler '%0'",
	tiddlerLoadError: "Fejl ved load af tiddler '%0'",
	wrongSaveFormat: "Kan ikke gemme med formatet '%0'. Bruger standard format til at gemme.",
	invalidFieldName: "Ikke tilladt feltnavn %0",
	fieldCannotBeChanged: "Felt '%0' kan ikke ændres",
	loadingMissingTiddler: "Forsøger at hente tiddleren '%0' fra '%1' serveren ved:\n\n'%2' i arbejdsområdet '%3'",
	upgradeDone: "Opgradering til version %0 er nu fuldført\n\nKlik 'OK' for at genopfriske den nyligt opgraderede TiddlyWiki"});

merge(config.messages.messageClose,{
	text: "luk",
	tooltip: "luk dette meddelelsesområde"});

config.messages.backstage = {
	open: {text: "bagscenen", tooltip: "Åben bagsceneområdet for at ændre på nogle grundlæggende indstillinger"},
	close: {text: "luk", tooltip: "Luk bagsceneområdet"},
	prompt: "bagscenen: ",
	decal: {
		edit: {text: "edit", tooltip: "Redigér tiddleren '%0'"}
	}
};

config.messages.listView = {
	tiddlerTooltip: "Klik for at se hele denne tiddlers tekst",
	previewUnavailable: "(forhåndsvisning er ikke tilgængelig)"
};

config.messages.dates.months = ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November","December"];
config.messages.dates.days = ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"];
config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"];
config.messages.dates.shortDays = ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"];
// suffixes for dates, eg "1ste","2den","3die"..."30te","31te"
config.messages.dates.daySuffixes = ["ste","den","die","te","te","te","te","te","te","te",
		"te","te","te","te","te","te","te","te","te","te",
		"ste","den","die","te","te","te","te","te","te","te",
		"te"];
config.messages.dates.am = "formiddag";
config.messages.dates.pm = "eftermiddag";

merge(config.messages.tiddlerPopup,{
	});

merge(config.views.wikified.tag,{
	labelNoTags: "ingen tags",
	labelTags: "tags: ",
	openTag: "Åben tag '%0'",
	tooltip: "Vis tiddlere der er taggede med '%0'",
	openAllText: "Åben alle",
	openAllTooltip: "Åben alle disse tiddlere",
	popupNone: "Ingen andre tiddlere er taggede med '%0'"});

merge(config.views.wikified,{
	defaultText: "Tiddleren '%0' findes ikke endnu. Dobbelt-klik for at lave den",
	defaultModifier: "(mangler)",
	shadowModifier: "(indbygget skygge tiddler)",
	dateFormat: "DD MMM YYYY", // use this to change the date format for your locale, eg "YYYY MMM DD", do not translate the Y, M or D
	createdPrompt: "lavet"});

merge(config.views.editor,{
	tagPrompt: "Skriv tags delt med mellemrum, [[brug 2 dobbelte firkantede klammer]] om nødvendigt, eller tilføj allerede eksisterende",
	defaultText: "Skriv teksten til '%0'"});

merge(config.views.editor.tagChooser,{
	text: "tags",
	tooltip: "Vælg eksisterende tags som tilføjelse til denne tiddler",
	popupNone: "Der er ikke defineret nogen tags",
	tagTooltip: "Tilføj tagget '%0'"});

merge(config.messages,{
	sizeTemplates:
		[
		{unit: 1024*1024*1024, template: "%0\u00a0GB"},
		{unit: 1024*1024, template: "%0\u00a0MB"},
		{unit: 1024, template: "%0\u00a0KB"},
		{unit: 1, template: "%0\u00a0B"}
		]});

merge(config.macros.search,{
	label: "søg",
	prompt: "Søg i denne TiddlyWiki",
	accessKey: "F",
	successMsg: "Der er fundet %0 tiddlere som matcher %1",
	failureMsg: "Der er ikke fundet nogen tiddlere som matcher %0"});

merge(config.macros.tagging,{
	label: "tagger: ",
	labelNotTag: "tagger ikke",
	tooltip: "Liste over tiddlere der er taggede med '%0'"});

merge(config.macros.timeline,{
	dateFormat: "DD MMM YYYY"});// use this to change the date format for your locale, eg "YYYY MMM DD", do not translate the Y, M or D

merge(config.macros.allTags,{
	tooltip: "Vis tiddlere der er taggede med '%0'",
	noTags: "Der er ingen taggede tiddlere"});

config.macros.list.all.prompt = "Alle tiddlere i alfabetisk orden";
config.macros.list.missing.prompt = "Tiddlere der linkes til men som ikke er definerede";
config.macros.list.orphans.prompt = "Tiddlere som der ikke linkes til fra nogen andre tiddlere";
config.macros.list.shadowed.prompt = "Tiddlere som er skyggede med grundlæggende indhold";
config.macros.list.touched.prompt = "Tiddlere som er blevet ændret lokalt ";

merge(config.macros.closeAll,{
	label: "luk alle",
	prompt: "Luk alle viste tiddlere (untaget dem som er ved at blive redigerede)"});

merge(config.macros.permaview,{
	label: "vis permalink",
	prompt: "Lav et link til en URL som henter alle de netop nu synlige tiddlere"});

merge(config.macros.saveChanges,{
	label: "gem ændringer",
	prompt: "Gem alle tiddlere for at lave en ny TiddlyWiki",
	accessKey: "S"});

merge(config.macros.newTiddler,{
	label: "ny tiddler",
	prompt: "Lav en ny tiddler",
	title: "Ny Tiddler",
	accessKey: "N"});

merge(config.macros.newJournal,{
	label: "ny journal",
	prompt: "Lav en ny tiddler ud fra nuværende dato og tid",
	accessKey: "J"});

merge(config.macros.options,{
	wizardTitle: "Tilpas avancerede muligheder",
	step1Title: "Disse muligheder gemmes i cookies i din browser",
	step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>Show unknown options</input>",
	unknownDescription: "//(ukendt)//",
	listViewTemplate: {
		columns: [
			{name: 'Option', field: 'option', title: "Option", type: 'String'},
			{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
			{name: 'Name', field: 'name', title: "Name", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'}
			]}
	});

merge(config.macros.plugins,{
	wizardTitle: "Administrer udvidelser",
	step1Title: "Aktive udvidelser",
	step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
	skippedText: "(Denne udvidelse er ikke blevet aktiveret fordi den først er blevet tilføjet efter start)",
	noPluginText: "Der er ikke installeret nogen udvidelser",
	confirmDeleteText: "Er du sikker på at du vil slette disse udvidelser:\n\n%0",
	removeLabel: "Fjern systemConfig tag",
	removePrompt: "Fjern systemConfig tag",
	deleteLabel: "slet",
	deletePrompt: "Slet disse tiddlere permanent",
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
			{name: 'Forced', field: 'forced', title: "Forced", tag: 'systemConfigForce', type: 'TagCheckbox'},
			{name: 'Disabled', field: 'disabled', title: "Disabled", tag: 'systemConfigDisable', type: 'TagCheckbox'},
			{name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"},
			{name: 'Startup Time', field: 'startupTime', title: "Startup Time", type: 'String'},
			{name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"},
			{name: 'Log', field: 'log', title: "Log", type: 'StringList'}
			],
		rowClasses: [
			{className: 'error', field: 'error'},
			{className: 'warning', field: 'warning'}
			]}
	});

merge(config.macros.toolbar,{
	moreLabel: "mere",
	morePrompt: "Vis flere muligheder"
	});

merge(config.macros.refreshDisplay,{
	label: "genopfrisk",
	prompt: "Genopfrisk hele TiddlyWikiens udseende"
	});

merge(config.macros.importTiddlers,{
	readOnlyWarning: "Du kan ikke importere til en låst TiddlyWiki fil. Prøv at åbne den fra en fil:// URL",
	wizardTitle: "Importer tiddlere fra en anden fil eller server",
	step1Title: "Trin 1: Find serveren eller TiddlyWiki filen",
	step1Html: "Vælg servertypen: <select name='selTypes'><option value=''>Choose...</option></select><br>Enter the URL or pathname here: <input type='text' size=50 name='txtPath'><br>...or browse for a file: <input type='file' size=50 name='txtBrowse'><br><hr>...or select a pre-defined feed: <select name='selFeeds'><option value=''>Choose...</option></select>",
	openLabel: "open",
	openPrompt: "Åben forbindelsen til denne fil eller server",
	openError: "Der var problemer med at hente tiddlywiki filen",
	statusOpenHost: "Forbinder til hosten",
	statusGetWorkspaceList: "Henter en liste over tilgængelige arbejdsområder",
	step2Title: "Trin 2: Vælg arbejdsområde",
	step2Html: "Indskriv et navn på arbejdsområdet: <input type='text' size=50 name='txtWorkspace'><br>...eller vælg et der allerede er der: <select name='selWorkspace'><option value=''>Choose...</option></select>",
	cancelLabel: "fortryd",
	cancelPrompt: "Fortryd denne import",
	statusOpenWorkspace: "Åben arbejdsområdet",
	statusGetTiddlerList: "Henter listen over tilgængelige tiddlere",
	errorGettingTiddlerList: "Fejl ved hentning af liste over tiddlere, klik Fortryd for at prøve igen",
	step3Title: "Trin 3: Vælg hvilke tiddlere der skal importeres",
	step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>Keep these tiddlers linked to this server so that you can synchronise subsequent changes</input><br><input type='checkbox' name='chkSave'>Save the details of this server in a 'systemServer' tiddler called:</input> <input type='text' size=25 name='txtSaveTiddler'>",
	importLabel: "importer",
	importPrompt: "Importer disse tiddlere",
	confirmOverwriteText: "Er du sikker på at du vil overskrive disse tiddlere:\n\n%0",
	step4Title: "Trin 4: Importerer %0 tiddler(e)",
	step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
	doneLabel: "udført",
	donePrompt: "Luk denne wizard",
	statusDoingImport: "Importerer tiddlere",
	statusDoneImport: "Alle tiddlere er importede",
	systemServerNamePattern: "%2 on %1",
	systemServerNamePatternNoWorkspace: "%1",
	confirmOverwriteSaveTiddler: "Tiddleren '%0' findes allerede. Klik 'OK' for at overskrive den med detaljerne fra denne server, eller 'Fortryd' for at efterlade uændret",
	serverSaveTemplate: "|''Type:''|%0|\n|''URL:''|%1|\n|''Workspace:''|%2|\n\nDenne tiddler blev lavet automatisk for at skrive denne servers detaljer",
	serverSaveModifier: "(System)",
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
			{name: 'Tags', field: 'tags', title: "Tags", type: 'Tags'}
			],
		rowClasses: [
			]}
	});

merge(config.macros.upgrade,{
	wizardTitle: "Opgrader TiddlyWikis kerne kode",
	step1Title: "Opdater eller reparer denne TiddlyWiki til sidste nye udgivelse",
	step1Html: "Du er ved at opgradere til sidste nye udgave af TiddlyWikis kerne kode (from <a href='%0' class='externalLink' target='_blank'>%1</a>). Dit indhold vil blive bibeholdt under opgraderinen.<br><br>Bemærk at opgraderinger kan konfikte med gamle udvidelser. Hvis du får problemer med den opgraderede fil se her <a href='http://www.tiddlywiki.org/wiki/CoreUpgrades' class='externalLink' target='_blank'>http://www.tiddlywiki.org/wiki/CoreUpgrades</a>",
	errorCantUpgrade: "Kan ikke opgradere denne TiddlyWiki. Du kan kun opgradere en TiddlyWiki fil som er gemt lokalt på en pc",
	errorNotSaved: "Du skal gemme ændringer før du kan gennemføre en opgradering",
	step2Title: "Bekræft opgraderingsdetaljer",
	step2Html_downgrade: "Du er ved at nedgradere til TiddlyWiki version %0 fra %1.<br><br>Nedgradering til en ældre udgave af kerne koden er IKKE tilrådeligt",
	step2Html_restore: "Denne tiddlyWike bruger allerede den sidste nye kerne kode (%0).<br><br>Du kan fortsætte med opgraderingen for at sikre dig at koden ikke er blevet ødelagt",
	step2Html_upgrade: "Du er ved at opgradere til TiddlyWiki version %0 fra %1",
	upgradeLabel: "opgrader",
	upgradePrompt: "Forbered opgraderingsprocessen",
	statusPreparingBackup: "Forbereder backup",
	statusSavingBackup: "Gemmer backup fil",
	errorSavingBackup: "Der var problemer med at gemme backup filen",
	statusLoadingCore: "Loader kernekoden",
	errorLoadingCore: "Fejl ved load af kernekoden",
	errorCoreFormat: "Fejl ved den nye kernekode",
	statusSavingCore: "Gemmer den nye kernekode",
	statusReloadingCore: "Genloader den nye kernekode",
	startLabel: "start",
	startPrompt: "Start opgraderingsprocessen",
	cancelLabel: "fortryd",
	cancelPrompt: "Fortryd opgraderingsprocessen",
	step3Title: "Opgradering afbrudt",
	step3Html: "Du har afbrudt opgraderingsprocessen"
	});

merge(config.macros.sync,{
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Server Type', field: 'serverType', title: "Server type", type: 'String'},
			{name: 'Server Host', field: 'serverHost', title: "Server host", type: 'String'},
			{name: 'Server Workspace', field: 'serverWorkspace', title: "Server workspace", type: 'String'},
			{name: 'Status', field: 'status', title: "Synchronisation status", type: 'String'},
			{name: 'Server URL', field: 'serverUrl', title: "Server URL", text: "View", type: 'Link'}
			],
		rowClasses: [
			],
		buttons: [
			{caption: "Synkronisér disse tiddlere", name: 'sync'}
			]},
	wizardTitle: "Synkroniser med internet servere og filer",
	step1Title: "Vælg hvilke tiddlere du vil synkronisere",
	step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
	syncLabel: "synk",
	syncPrompt: "Synkronisér disse tiddlere",
	hasChanged: "Ændret imens den var koblet fra",
	hasNotChanged: "Uændret imens den var koblet fra",
	syncStatusList: {
		none: {text: "...", color: "gennemsigtig", display:null},
		changedServer: {text: "Ændret på serveren", color: '#8080ff', display:null},
		changedLocally: {text: "Ændret imens den var koblet fra", color: '#80ff80', display:null},
		changedBoth: {text: "ændret imens den var koblet fra også på serveren", color: '#ff8080', display:null},
		notFound: {text: "Ikke fundet på serveren", color: '#ffff80', display:null},
		putToServer: {text: "Gemt update på serveren", color: '#ff80ff', display:null},
		gotFromServer: {text: "Hentet update fra serveren", color: '#80ffff', display:null}
		}
	});

merge(config.commands.closeTiddler,{
	text: "luk",
	tooltip: "Luk denne tiddler"});

merge(config.commands.closeOthers,{
	text: "luk andre",
	tooltip: "Luk alle andre tiddlere"});

merge(config.commands.editTiddler,{
	text: "redigér",
	tooltip: "Redigér denne tiddler",
	readOnlyText: "se",
	readOnlyTooltip: "Se denne tiddlers kilde"});

merge(config.commands.saveTiddler,{
	text: "færdig",
	tooltip: "Gem ændringer til denne tiddler"});

merge(config.commands.cancelTiddler,{
	text: "fortryd",
	tooltip: "Fortryd ændringer til denne tiddler",
	warning: "Er du sikker på at du vil fortryde dine ændringer til  '%0'?",
	readOnlyText: "færdig",
	readOnlyTooltip: "Se tiddlere normalt"});

merge(config.commands.deleteTiddler,{
	text: "slet",
	tooltip: "Slet denne tiddler",
	warning: "Er du sikker på at du vil slette '%0'?"});

merge(config.commands.permalink,{
	text: "permalink",
	tooltip: "Permalink til denne tiddler"});

merge(config.commands.references,{
	text: "referencer",
	tooltip: "Vis tiddlere som linker til denne tiddler",
	popupNone: "Ingen referencer"});

merge(config.commands.jump,{
	text: "spring",
	tooltip: "Spring til en anden tiddler"});

merge(config.commands.syncing,{
	text: "synkroniserer",
	tooltip: "Kontroller synkronisering af denne tiddler med en server eller en fil",
	currentlySyncing: "<div>Currently syncing via <span class='popupHighlight'>'%0'</span> to:</"+"div><div>host: <span class='popupHighlight'>%1</span></"+"div><div>workspace: <span class='popupHighlight'>%2</span></"+"div>", // Note escaping of closing <div> tag
	notCurrentlySyncing: "Sykroniserer ikke lige nu",
	captionUnSync: "Stop synkronisering af denne tiddler",
	chooseServer: "Synkronisér denne tiddler med en anden server:",
	currServerMarker: "\u25cf ",
	notCurrServerMarker: "  "});

merge(config.commands.fields,{
	text: "felter",
	tooltip: "Vis denne tiddlers udvidede felter",
	emptyText: "Der er ingen udvidede felter til rådighed for denne tiddler",
	listViewTemplate: {
		columns: [
			{name: 'Field', field: 'field', title: "Field", type: 'String'},
			{name: 'Value', field: 'value', title: "Value", type: 'String'}
			],
		rowClasses: [
			],
		buttons: [
			]}});

merge(config.shadowTiddlers,{
	DefaultTiddlers: "[[TranslatedGettingStarted]]",
	MainMenu: "[[TranslatedGettingStarted]]\n\n\n^^~TiddlyWiki version <<version>>\n© 2007 [[UnaMesa|http://www.unamesa.org/]]^^",
	TranslatedGettingStarted: "For at komme i gang med denne tomme tiddlywiki, skal du ændre på de følgende tiddlere:\n* SiteTitle & SiteSubtitle: Sidens titel og undertitel, som vist øverst (efter de er gemt, vil de også vise sig i browserens titelmenu)\n* MainMenu: er hovedmenuen (er oftest placeret til venstre)\n* DefaultTiddlers: Indeholder navnene på de tiddlere du vilhave skal starte op når du åbner TiddlyWiki\nDu skal også skrive dit brugernavn for at signere dine redigeringer: <<option txtUserName>>",
	SiteTitle: "Min TiddlyWiki",
	SiteSubtitle: "en genbrugelig ikke-liniær personlig web notesbog",
	SiteUrl: "http://www.tiddlywiki.com/",
	OptionsPanel: "Disse muligheder for at ændre på TiddlyWiki bliver gemt i din browser\n\nDit brugernavn til at signere dine ændringer. Skriv det som et WikiOrd (f.eks. PerPoulsen)\n<<option txtUserName>>\n\n<<option chkSaveBackups>> Save backups\n<<option chkAutoSave>> Auto save\n<<option chkRegExpSearch>> Regexp search\n<<option chkCaseSensitiveSearch>> Case sensitive search\n<<option chkAnimate>> Enable animations\n\n----\nAlso see [[TranslatedAdvancedOptions|AdvancedOptions]]",
	SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "muligheder \u00bb" "Ændre på TiddlyWikis avancerede muligheder">>',
	SideBarTabs: '<<tabs txtMainTab "Tidslinie" "Tidslinie" TabTimeline "Alle" "Alle tiddlere" TabAll "Tags" "Alle tags" TabTags "Flere" "Flere lister" TabMore>>',
	TabMore: '<<tabs txtMoreTab "Manglende" "Manglende tiddlere" TabMoreMissing "Uden tilknytning" "Tiddlere" TabMoreOrphans "Skyggede" "Skyggede tiddlere" TabMoreShadowed>>'
	});

merge(config.annotations,{
	AdvancedOptions: "Denne skygge tiddler giver adgang til flere avancerede muligheder",
	ColorPalette: "Disse værdier i denne skyggetiddler bestemmer hvilket farveskema, der bliver brugt til ~TiddlyWikis brugerflade",
	DefaultTiddlers: "Tiddlere som er listede i denne skyggetiddler vil automatisk blive vist når ~TiddlyWiki starter op",
	EditTemplate: "HTML skabelonen i denne skyggetiddler bestemmer hvordan tiddlere ser ud når de bliver redigerede",
	GettingStarted: "Denne skyggetiddler giver instruktioner om grundlæggende anvendelse",
	ImportTiddlers: "Denne skyggetiddler giver mulighed for at importere tiddlere",
	MainMenu: "Denne tiddler bliver brugt til at definere indholdet af hoved menuen i venstre side af skærmen",
	MarkupPreHead: "Denne tiddler bliver indsat i toppen af <head> sektionen på TiddlyWiki HTML filen",
	MarkupPostHead: "Denne tiddler bliver indsat i bunden af <head> sektionen på TiddlyWiki HTML filen",
	MarkupPreBody: "Denne tiddler bliver indsat i toppen af<body> sektionen på TiddlyWiki HTML filen",
	MarkupPostBody: "Denne tiddler bliver indsat i slutningen af  <body> sektionen på TiddlyWiki HTML filen umiddelbart efter script blokken",
	OptionsPanel: "Denne skyggetiddler bliver brugt til indholdet af muligheder skydepanelet i højre side",
	PageTemplate: "HTML skabelonen i denne skyggetiddler bestemmer det overordnede ~TiddlyWiki layout",
	PluginManager: "Denne skyggetiddler giver adgang til udvidelsesadministrationen",
	SideBarOptions: "Denne skyggetiddler bruges til indholdet af muligheder panelet i højre sidemenu",
	SideBarTabs: "Denne skyggetiddler bruges til indholdet af fanebladspanelet i højre sidemenu",
	SiteSubtitle: "Denne skyggetiddler bruges som anden del af sidens titel",
	SiteTitle: "Denne skyggetiddler bruges som første del af sidens titel",
	SiteUrl: "Denne skyggetiddler bør sættes til den fulde mål-URL til publikation",
	StyleSheetColors: "Denne skyggetiddler indeholder CSS definitionerne der bestemmer farverne på side elementerne. ''REDIGÉR IKKE DENNE TIDDLER'', lav i stedet dine ændringer i StyleSheet skyggetiddleren",
	StyleSheet: "Denne tiddler kan indeholde specialle CSS definitioner",
	StyleSheetLayout: "Denne skyggetiddler indeholder CSS definitioner der bestemmer layoutet på side elementer. ''REDIGÉR IKKE DENNE TIDDLER'', lav i stedet dine ændringer i StyleSheet skyggetiddleren",
	StyleSheetLocale: "Denne skyggetiddler indeholder CSS definitioner relateret til lokale oversættelser",
	StyleSheetPrint: "Denne skyggetiddler indeholder CSS definitioner til print",
	TabAll: "Denne skyggetiddler indeholder hvad der er i 'Alle' fanen i højre sidemenu",
	TabMore: "Denne skyggetiddler indeholder  hvad der er i 'Flere' fanen i højre sidemenu",
	TabMoreMissing: "Denne skyggetiddler indeholder  hvad der er i 'Mangler' fanen i højre sidemenu",
	TabMoreOrphans: "Denne skyggetiddler indeholder  hvad der er i  'Mangler tilknytning' fanen i højre sidemenu",
	TabMoreShadowed: "Denne skyggetiddler indeholder  hvad der er i 'Skyggede' fanen i højre sidemenu",
	TabTags: "Denne skyggetiddler indeholder  hvad der er i 'Tags' fanen i højre sidemenu",
	TabTimeline: "Denne skyggetiddler indeholder hvad der er i 'Tidslinie' fanen i højre sidemenu",
	ToolbarCommands: "Denne skyggetiddler bestemmer hvilke værktøjer der vises i tiddleres værktøjslinier",
	ViewTemplate: "HTML skabelonen i denne skyggetiddler bestemmer hvordan tiddlere ser ud"
	});

//}}}
[[TwitterBackupWizard]]
[[ThemeSwitcher]]
/***
|''Name:''|FadingMessagesPlugin|
|''Description:''|Automatically clear a displayed message after an interval |
|''Author:''|PaulDowney (psd (at) osmosoft (dot) com) |
|''Source:''|http://whatfettle.com/2008/07/FadingMessagesPlugin/ |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/PaulDowney/plugins/FadingMessagesPlugin/ |
|''Version:''|0.2|
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''~CoreVersion:''|2.4|
|''Overrides:''|displayMessage|
|''Requires:''|WikifiedMessagesPlugin|
!!Documentation
Displayed messages automatically fade away after a short interval. 
!!Options
|<<option txtFadingMessagesTimeout>>|<<message config.optionsDesc.txtFadingMessagesTimeout>>|
|<<option chkAnimate>>|<<message config.optionsDesc.chkAnimate>>|
!!Code
***/
//{{{
if(!version.extensions.FadingMessagesPlugin) {
version.extensions.FadingMessagesPlugin = {installed:true};

	config.options.txtFadingMessagesTimeout = 5;
	config.optionsDesc.txtFadingMessagesTimeout = "seconds before a displayed message clears itself";

	config.animDurationFade = 900;

	config.extensions.FadingMessages = {
		Fader: function(e,done)
		{
			e.style.overflow = 'hidden';
			e.style.display = 'block';
			var p = [];
			p.push({style: 'display', atEnd: 'none'});
			p.push({style: 'opacity', start: 1, end: 0, template: '%0'});
			p.push({style: 'filter', start: 100, end: 0, template: 'alpha(opacity:%0)'});
			return new Morpher(e,config.animDurationFade,p,done);
		},  
		clearMessageBox: function(e)
		{
			try { removeNode(e); } catch(ex) {}
			var msgArea = document.getElementById("messageArea");
			var n = msgArea.getElementsByTagName('div');
			if(!(n&&n.length)){
				msgArea.style.display = "none";
			}
		},
		fadeMessageBox: function(e)
		{
			var me = config.extensions.FadingMessages;
			if(config.options.chkAnimate && anim){
				anim.startAnimating(new me.Fader(e,me.clearMessageBox));
			}else{
				me.clearMessageBox(e);
			}
		},
		createClearAllButton: function(e)
		{
			return null;
		},
		createClearMessageButton: function(e)
		{
			var me = config.extensions.FadingMessages;
			return createTiddlyButton(createTiddlyElement(e,"span",null,"messageClear"),
				"×","",
				function(){me.clearMessageBox(e);});
		},
		_displayMessage: displayMessage,
		displayMessage: function(text,linkText)
		{
			var me = config.extensions.FadingMessages;
			var e = me._displayMessage(text,linkText);
			if(e){
				window.setTimeout(function(){me.fadeMessageBox(e);},config.options.txtFadingMessagesTimeout*1000);
			}
			return e;
		}
	};

	displayMessage = config.extensions.FadingMessages.displayMessage;
	config.extensions.WikifiedMessages.createClearMessageButton = config.extensions.FadingMessages.createClearMessageButton;
	config.extensions.WikifiedMessages.createClearAllButton = config.extensions.FadingMessages.createClearAllButton;
}
//}}}
/***
|''Name''|HTTPThrottlingPlugin|
|''Description''|limit the amount of simultaneous XMLHttpRequests|
|''Author''|FND|
|''Version''|0.1.1|
|''Status''|@@beta@@|
|''Source''|http://devpad.tiddlyspot.com/#HTTPThrottlingPlugin|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''CoreVersion''|2.4.1|
!Revision History
!!v0.1 (2008-11-05)
* initial release
!To Do
* use queuing instead of polling
!Code
***/
//{{{
if(!version.extensions.HTTPThrottlingPlugin) { //# ensure that the plugin is only installed once
version.extensions.HTTPThrottlingPlugin = { installed: true };

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

config.extensions.HTTPThrottlingPlugin = {
	XHRCount: 0,
	throttleAmount: 2, // browsers' max. number of concurrent HTTP connections
	throttleDelay: 1000,

	init: function() {
		// hijack httpReq to throttle simultaneous XHRs
		var httpReq_orig = httpReq;
		httpReq = function(type, url, callback, params, headers, data, contentType, username, password, allowCache) {
			var context = config.extensions.HTTPThrottlingPlugin;
			if(context.XHRCount >= context.throttleAmount) {
				var defer = function() {
					return httpReq(type, url, callback, params, headers, data, contentType, username, password, allowCache);
				};
				setTimeout(defer, context.throttleDelay);
			} else {
				context.XHRCount++;
				var callbackWrapper = function(status, params, responseText, url, x) {
					context.XHRCount--;
					return callback(status, params, responseText, url, x);
				};
				var args = [type, url, callbackWrapper, params, headers, data, contentType, username, password, allowCache];
				return httpReq_orig.apply(this, args);
			}
		};
	}
};

config.extensions.HTTPThrottlingPlugin.init();

} //# end of "install only once"
//}}}
Under the hood, TiddlyTweets is a plugin-extended ~TiddlyWiki (hence the name). ~TiddlyWiki is an open source project that Osmosoft has a lot of involvement with. Everything about TiddlyTweets is controlled by plugins written in JavaScript, a breakdown of which is below. If you want to get into exploring the guts, hit the "switch theme" button in the top-right to change into the ~TiddlyWiki theme, which makes it easier to navigate between tiddlers (did I mention those? A tiddler is a bit of content, or a plugin).

|Plugin |What's it for? |
|TwitterAdaptor |Handles communication with Twitter's API and converts returned tweets into tiddlers |
|TwitterWizardPlugin |Provides the user interface and uses the TwitterAdaptor |
|TemplatePlugin |Provides the mechanism for turning tiddlers into other data formats using templates |
|TemplatingMacrosPlugin |Adds some macros you can use inside templates to get at tiddler data |
|TemplateFormatterPlugin |Parses templates and calls macros inside them |
|TiddlyTemplatingMacro |Uses the above three plugins to generate the output XML and either save it to a file (if offline) or pop up a window with it in |
|ToggleThemePlugin |Adds the "switch theme" button |

|Tiddler |What's it for? |
|[[How to hack this]] |What you're reading. |
|RssTemplate |Template for creating an RSS feed from tiddlers |
|RssItemTemplate |Sub-template for each item in the RSS feed |
|RssItemCategoryTemplate |Sub-template for the tags on an RSS item |
|ThemeSwitcher |Contains a call to the toggleTheme macro to generate the "switch theme" button |
|TiddlyTweets |Information about TiddlyTweets |
|TiddlyTweetsTheme |The stylesheet, page template and tiddler view template for the default web app look |
|TiddlyWikiTheme |The stylesheet, page template and tiddler view template for the standard ~TiddlyWiki theme (plus the "switch theme" button) |
|TwitterBackupWizard |Contains a call to the TwitterBackupWizard macro to generate the Tweet Archiver interface |
/***
|Name|ImageSizePlugin|
|Source|http://www.TiddlyTools.com/#ImageSizePlugin|
|Version|1.2.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,formatter|
|Requires||
|Overrides|'image' formatter|
|Description|adds support for resizing images|
This plugin adds optional syntax to scale an image to a specified width and height and/or interactively resize the image with the mouse.
!!!!!Usage
<<<
The extended image syntax is:
{{{
[img(w+,h+)[...][...]]
}}}
where ''(w,h)'' indicates the desired width and height (in CSS units, e.g., px, em, cm, in, or %). Use ''auto'' (or a blank value) for either dimension to scale that dimension proportionally (i.e., maintain the aspect ratio). You can also calculate a CSS value 'on-the-fly' by using a //javascript expression// enclosed between """{{""" and """}}""". Appending a plus sign (+) to a dimension enables interactive resizing in that dimension (by dragging the mouse inside the image). Use ~SHIFT-click to show the full-sized (un-scaled) image. Use ~CTRL-click to restore the starting size (either scaled or full-sized).
<<<
!!!!!Examples
<<<
{{{
[img(100px+,75px+)[images/meow2.jpg]]
}}}
[img(100px+,75px+)[images/meow2.jpg]]
{{{
[<img(34%+,+)[images/meow.gif]]
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img(  1%+,+)[images/meow.gif]]
}}}
[<img(34%+,+)[images/meow.gif]]
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img(  1%+,+)[images/meow.gif]]
{{tagClear{
}}}
<<<
!!!!!Revisions
<<<
2009.02.24 [1.2.1] cleanup width/height regexp, use '+' suffix for resizing
2009.02.22 [1.2.0] added stretchable images
2008.01.19 [1.1.0] added evaluated width/height values
2008.01.18 [1.0.1] regexp for "(width,height)" now passes all CSS values to browser for validation
2008.01.17 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImageSizePlugin= {major: 1, minor: 2, revision: 1, date: new Date(2009,2,24)};
//}}}
//{{{
var f=config.formatters[config.formatters.findByField("name","image")];
f.match="\\[[<>]?[Ii][Mm][Gg](?:\\([^,]*,[^\\)]*\\))?\\[";
f.lookaheadRegExp=/\[([<]?)(>?)[Ii][Mm][Gg](?:\(([^,]*),([^\)]*)\))?\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg;
f.handler=function(w) {
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var floatLeft=lookaheadMatch[1];
		var floatRight=lookaheadMatch[2];
		var width=lookaheadMatch[3];
		var height=lookaheadMatch[4];
		var tooltip=lookaheadMatch[5];
		var src=lookaheadMatch[6];
		var link=lookaheadMatch[7];

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

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

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

config.formatterHelpers.addStretchHandlers=function(e,stretchW,stretchH) {
	e.title=((stretchW||stretchH)?'DRAG=stretch/shrink, ':'')
		+'SHIFT-CLICK=show full size, CTRL-CLICK=restore initial size';
	e.statusMsg='width=%0, height=%1';
	e.style.cursor='move';
	e.originalW=e.style.width;
	e.originalH=e.style.height;
	e.minW=Math.max(e.offsetWidth/20,10);
	e.minH=Math.max(e.offsetHeight/20,10);
	e.stretchW=stretchW;
	e.stretchH=stretchH;
	e.onmousedown=function(ev) { var ev=ev||window.event;
		this.sizing=true;
		this.startX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
		this.startY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
		this.startW=this.offsetWidth;
		this.startH=this.offsetHeight;
		return false;
	};
	e.onmousemove=function(ev) { var ev=ev||window.event;
		if (this.sizing) {
			var s=this.style;
			var currX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
			var currY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
			var newW=(currX-this.offsetLeft)/(this.startX-this.offsetLeft)*this.startW;
			var newH=(currY-this.offsetTop )/(this.startY-this.offsetTop )*this.startH;
			if (this.stretchW) s.width =Math.floor(Math.max(newW,this.minW))+'px';
			if (this.stretchH) s.height=Math.floor(Math.max(newH,this.minH))+'px';
			clearMessage(); displayMessage(this.statusMsg.format([s.width,s.height]));
		}
		return false;
	};
	e.onmouseup=function(ev) { var ev=ev||window.event;
		if (ev.shiftKey) { this.style.width=this.style.height=''; }
		if (ev.ctrlKey)  { this.style.width=this.originalW; this.style.height=this.originalH; }
		this.sizing=false;
		clearMessage();
		return false;
	};
	e.onmouseout=function(ev) { var ev=ev||window.event;
		this.sizing=false;
		clearMessage();
		return false;
	};
}
//}}}
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.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|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2009.04.11 [1.9.5] pass current tiddler object into wrapper code so it can be referenced from within 'onclick' scripts
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 5, date: new Date(2009,4,11)};

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

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

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

// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
twitter: [[@jayfresh|http://twitter.com/jayfresh]
blog: http://jaybyjayfresh.com
<<lifeStream tweets>>
/*
 * Javascript Humane Dates
 * Copyright (c) 2008 Dean Landolt (deanlandolt.com)
 * Re-write by Zach Leatherman (zachleat.com)
 * 
 * Adopted from the John Resig's pretty.js
 * at http://ejohn.org/blog/javascript-pretty-date
 * and henrah's proposed modification 
 * at http://ejohn.org/blog/javascript-pretty-date/#comment-297458
 * 
 * Licensed under the MIT license.
 */

function humane_date(date_str){
	var time_formats = [
		[60, 'Just Now'],
		[90, '1 Minute'], // 60*1.5
		[3600, 'Minutes', 60], // 60*60, 60
		[5400, '1 Hour'], // 60*60*1.5
		[86400, 'Hours', 3600], // 60*60*24, 60*60
		[129600, '1 Day'], // 60*60*24*1.5
		[604800, 'Days', 86400], // 60*60*24*7, 60*60*24
		[907200, '1 Week'], // 60*60*24*7*1.5
		[2628000, 'Weeks', 604800], // 60*60*24*(365/12), 60*60*24*7
		[3942000, '1 Month'], // 60*60*24*(365/12)*1.5
		[31536000, 'Months', 2628000], // 60*60*24*365, 60*60*24*(365/12)
		[47304000, '1 Year'], // 60*60*24*365*1.5
		[3153600000, 'Years', 31536000], // 60*60*24*365*100, 60*60*24*365
		[4730400000, '1 Century'], // 60*60*24*365*100*1.5
	];

	var time = ('' + date_str).replace(/-/g,"/").replace(/[TZ]/g," "),
		dt = new Date,
		seconds = ((dt - new Date(time) + (dt.getTimezoneOffset() * 60000)) / 1000),
		token = ' Ago',
		i = 0,
		format;

	if (seconds < 0) {
		seconds = Math.abs(seconds);
		token = '';
	}

	while (format = time_formats[i++]) {
		if (seconds < format[0]) {
			if (format.length == 2) {
				return format[1] + (i > 1 ? token : ''); // Conditional so we don't return Just Now Ago
			} else {
				return Math.round(seconds / format[2]) + ' ' + format[1] + (i > 1 ? token : '');
			}
		}
	}

	// overflow for centuries
	if(seconds > 4730400000)
		return Math.round(seconds / 4730400000) + ' Centuries' + token;

	return date_str;
};

if(typeof jQuery != 'undefined') {
	jQuery.fn.humane_dates = function(){
		return this.each(function(){
			var date = humane_date(this.title);
			if(date && jQuery(this).text() != date) // don't modify the dom if we don't have to
				jQuery(this).text(date);
		});
	};
}


config.macros.lifeStream = {};
config.macros.lifeStream.handler = function(place,macroName,params)
{
	config.macros.lifeStream.display(place, params);
};

config.macros.lifeStream.display = function (place, params)
{
	var tag = params[0];
	if(!tag) {
		throw "Provide a tag as a parameter to include tiddlers with that tag";
	}
	removeChildren(place);
	setStylesheet(".tiddler .button, .tiddler .button:hover {background-repeat:no-repeat;  margin:1px; float:none}"+
	".tiddler .button:hover,.tiddler .button	 {background-repeat:no-repeat; float:none;  }"+
	".textSpace {padding-top:1px}"+
	".tiddler .button, .tiddler .button:hover {padding:5px; margin:5px}"+
	".noFloat {float:none; background-color:red;}"+
	".stream { display: block; padding:1px; margin:1px ; max-width:500px;  min-height:20px; }"+
	".imgClass {float:left; display:block;padding-right:10px}");
	var tiddlers = store.reverseLookup("tags","excludeLists",false,"modified");
	var last = params[1] ? tiddlers.length-Math.min(tiddlers.length,parseInt(params[1])) : 0;
	var div = createTiddlyElement(place, "div");
	var lastDay ="";
	var today = new Date;
	var yesterday = new Date();
	yesterday.setDate(yesterday.getDate()-1);
	for(var t=tiddlers.length-1; t>=last; t--) {
		if(tiddlers[t].isTagged("tweets")) {
			if(typeof(tiddlers[t]['modified'])!='undefined'){
				var theDay = tiddlers[t]['modified'].convertToLocalYYYYMMDDHHMM().substr(0,8);
				if(theDay != lastDay) {
					if(tiddlers[t]['modified'].formatString("DD/MM/YYYY")==today.formatString("DD/MM/YYYY"))
						createTiddlyElement(place, "h3", null, null,  "Today");
					else if(tiddlers[t]['modified'].formatString("DD/MM/YYYY")==yesterday.formatString("DD/MM/YYYY"))
						createTiddlyElement(place, "h3", null, null,  "Yesterday");
					else
						createTiddlyElement(place, "h3", null, null, tiddlers[t]['modified'].formatString("DD/MM/YYYY"));
					lastDay = theDay;
				}		
			}
			var img = createTiddlyElement(null, "img", null, "imgClass");
			//img.src = tiddlers[t].fields['user_img'];
			img.src= "http://www.bioneural.net/wp-content/themes/k2bn/styles/bioneural/twitter.png";
			img.width = "16";
			img.height = "16";
			var slider = config.macros.slider.createSlider(place, "", "");
			addClass(slider,"slider");
			var sliderButton = findRelated(slider,"button","className","previousSibling");
			sliderButton.appendChild(img);
		
			var div = createTiddlyElement(sliderButton, "div", null, "textSpace");
			div.innerHTML =  tiddlers[t].text;
			addClass(sliderButton,"stream twitterStream");
			createTiddlyElement(sliderButton, "div", null, "noFloat");
			// this should choose some relevant fields - these are undefined for the tweets
			wikify(tiddlers[t].fields['url']+"\n\r"+tiddlers[t].fields.prettyDate,slider);
		}
	}
};
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

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

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 }
 return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
GettingStarted
LifeStream
/***
|Name|NestedSlidersPlugin|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.4.9|
|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|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
!!!!!Documentation
>see [[NestedSlidersPluginInfo]]
!!!!!Configuration
<<<
<<option chkFloatingSlidersAnimate>> allow floating sliders to animate when opening/closing
>Note: This setting can cause 'clipping' problems in some versions of InternetExplorer.
>In addition, for floating slider animation to occur you must also allow animation in general (see [[AdvancedOptions]]).
<<<
!!!!!Revisions
<<<
2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class).  In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
|please see [[NestedSlidersPluginInfo]] for additional revision details|
2005.11.03 - 1.0.0 initial public release.  Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
<<<
!!!!!Code
***/
//{{{
version.extensions.NestedSlidersPlugin= {major: 2, minor: 4, revision: 9, date: new Date(2008,11,15)};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// TW2.2+
// hijack Morpher stop handler so sliderPanel/floatingPanel overflow is visible after animation has completed
if (version.major+.1*version.minor+.01*version.revision>=2.2) {
	Morpher.prototype.coreStop = Morpher.prototype.stop;
	Morpher.prototype.stop = function() {
		this.coreStop.apply(this,arguments);
		var e=this.element;
		if (hasClass(e,"sliderPanel")||hasClass(e,"floatingPanel")) {
			// adjust panel overflow and position after animation
			e.style.overflow = "visible";
			if (window.adjustSliderPos) window.adjustSliderPos(e.parentNode,e.button,e);
		}
	};
}
//}}}
/***
|''Name:''|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"
	});
*/
//}}}
<category><!--<<view tags>>--></category>
<item>
	<title><!--<<view title>>--></title>
	<description><![CDATA[<!--<<view text>>-->]]></description>
	<!--<<templateTags RssItemCategoryTemplate>>-->
	<link><!--<<permalink>>--></link>
	<pubDate><!--<<view modified date>>--></pubDate>
</item>
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title><!--<<tiddler SiteTitle>>--></title>
<link><!--<<tiddler SiteURL>>--></link>
<description><!--<<tiddler SiteSubtitle>>--></description>
<language>en-us</language>
<copyright>Copyright <!--<<today "ddd, DD MMM YYYY 0hh:0hh:0ss TZD">>--> <!--<<message config.options.txtUserName>>--></copyright>
<pubDate><!--<<today "ddd, DD MMM YYYY 0hh:0hh:0ss TZD">>--></pubDate>
<lastBuildDate><!--<<today "ddd, DD MMM YYYY 0hh:0hh:0ss TZD">>--></lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>TiddlyWiki <!--<<message version.major>>-->.<!--<<message version.minor>>-->.<!--<<message version.revision>>--></generator>
<!--<<templateTiddlers RssItemTemplate filter:"[tag[tweets]]">>-->
</channel>
</rss>
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<tiddler TspotSidebar>><<slider chkSliderOptionsPanel OptionsPanel "muligheder »" "Ændre på TiddlyWikis avancerede muligheder">>

— fordi de er dine tweets!
Twitter Arkivering
<script label="SkiftTema">
   var theme1="TiddlyWikiTheme";
   var theme2="TiddlyTweetsTheme";
   var currTheme=config.options.txtTheme;
   config.options.txtTheme=(currTheme==theme1?theme2:theme1);
   story.switchTheme(config.options.txtTheme);
</script>
{{textcenter{
@@padding-left:45%;+++[Søg Tweets]...<br><<tiddler TwitterTabs>>
/***
|''Name:''|TemplateFormatterPlugin|
|''Author:''|Martin Budden ( mjbudden [at] gmail [dot] com)|
|''Description:''|Plug to demonstrate template formatter|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/experimental/TemplateFormatterPlugin.js |
|''Version:''|0.0.3|
|''Date:''|Mar 19, 2008|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]] |
|''~CoreVersion:''|2.3.0|

!!Description
Provides a formatter that can be used to expand templates

!!Usage
Then include this plugin and tag it systemConfig in the normal way. Templates can include:
{{{
<!--<<macroname macroparameters>>--> : macro that is expanded into the template
<!--comment--> : comment that is included in the output
<!--@@comment@@-->> : comment that is not included in the output (can be used to document the template itself)
}}}

***/

//{{{
if(!version.extensions.TemplateFormatterPlugin) {
version.extensions.TemplateFormatterPlugin = {installed:true};

config.templateFormatters = [
{
	name: 'templateElement',
	match: '<!--(?:<<|@@)',
	lookaheadRegExp: /<!--<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>-->|<!--@@([^@]*)@@-->/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			w.nextMatch = this.lookaheadRegExp.lastIndex;
			if(lookaheadMatch[1]) {
				invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
			}
		}
	}
}
];

config.parsers.templateFormatter = new Formatter(config.templateFormatters);
config.parsers.templateFormatter.format = 'template';
config.parsers.templateFormatter.formatTag = 'TemplateFormat';
} //# end of 'install only once'
//}}}
/***
|''Name:''|TemplatePlugin |
|''Description:''|Collection of functions to support rendering of tiddlers through HTML templates |
|''Author:''|JonathanLister |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/plugins/TemplatePlugin.js |
|''Version:''|0.0.5 |
|''Date:''|3/3/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.3|

The templateTiddlers macro finds a set of tiddlers and renders them once each through a template. The template can contain additional
calls to the macro to allow for e.g. looping inside a template (think RSS items). It needs to be able to support recursion, so that sub-templates make sense.

Usage:
{{{
<<templateTiddlers template:RssTemplate filter:"[tag[!excludeLists]]" [wikitext:true]>>
<<templateTiddlers RssTemplate filter:"[tag[!excludeLists]]">> // template qualification is optional
}}}

Parameters can be:
template - the name of the template
filter - a tiddler filter
wikitext - if true, renders the target tiddler's text as wikitext instead of using the special template formatter
raw - if true, adds the HTML to place without encoding it as text

If a parameter does not have a qualifier, it is assumed to be the template name

|''Name:''|templateTagsMacro |
|''Description:''|Renders a tiddler's tags through a template |

Usage:
{{{
<<templateTags template:RssItemCategoryTemplate>>
<<templateTiddlers RssTemplate>> // template qualification is optional
}}}

Parameters can be:
template - the name of the template

The templateTags macro renders a tiddler's tags through a template in an analagous way to how templateTiddlers renders a set of tiddlers. Future development might offer support for other data items other than tags, but this is what is needed for RSS, the use-case driving the development.

|''Name:''|PermalinkMacro |
|''Description:''|Creates a permalink to the tiddler |

Usage:
{{{
<<permalink>>
}}}
***/

//{{{
if(!version.extensions.templatePlugin) {
version.extensions.templatePlugin = {installed:true};

expandTemplate = function(template,tiddlers,wikitext)
{
	var defaultTemplate = "<<view text>>";
	var t = template;
	template = template ? store.getTiddlerText(template,template) : defaultTemplate;
	if(!tiddlers) {
		// no tiddlers provided, so create a temporary tiddler
		tiddlers = [];
		tiddlers.push(new Tiddler("temp"));
	}
	var output = "";
	// decide whether to parse as wikitext or simple template
	var format = wikitext ? null : 'template';
	for(var i=0; i<tiddlers.length; i++) {
		output += wikifyStatic(template,null,tiddlers[i],format).htmlDecode();
	}
	return output;
};

config.macros.templateTiddlers = {};
config.macros.templateTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	p = paramString.parseParams("anon",null,true,false,false);
	var template = getParam(p,"template",null);
	if(!template)
		template = getParam(p,"anon",null);
	var filter = getParam(p,"filter",null);
	var wikitext = getParam(p,"wikitext",null);
	var raw = getParam(p,"raw",false);
	var tiddlers = [];
	if(filter) {
		tiddlers = store.filterTiddlers(filter);
	} else {
		// no filter provided, so inherit or create temp tiddler
		tiddlers.push(tiddler ? tiddler : new Tiddler("temp"));
	}
	var output = expandTemplate(template,tiddlers,wikitext);
	/* I'm not sure this 'raw' thing is actually useful... if you don't do the htmlEncode before adding the output to the innerHTML, nested template content could be broken by the htmlDecode in expandTemplate. I think I've used the 'raw' control before to style a tiddler, but maybe this can still be done without using this method. It's probably safe if used right at the top-level of templating... */
	place.innerHTML += raw ? output : output.htmlEncode();
	if(raw) {
		/* Gotta refresh the tiddlerlinks! The wikifyStatic just plops a line of HTML in - the onclick is attached to different element */
	}
};

config.macros.templateTags = {};
config.macros.templateTags.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	p = paramString.parseParams("anon",null,true,false,false);
	var template = getParam(p,"template",null);
	var tiddlers = [];
	if(!template)
		template = getParam(p,"anon",null);
	for(var i=0;i<tiddler.tags.length;i++) {
		var t = new Tiddler(tiddler.title);
		t.tags = [tiddler.tags[i]];
		tiddlers.push(t);
	}
	var output = expandTemplate(template,tiddlers);
	place.innerHTML += output;
};

} //# end of 'install only once'
//}}}
/***
|''Name:''|TemplatingMacrosPlugin |
|''Description:''|Some macros used in TiddlyTemplating templates |
|''Author:''|JonathanLister |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/plugins/TemplatingMacrosPlugin.js |
|''Version:''|0.0.1 |
|''Date:''|25/3/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.3|

!permalink macro

Creates a link to a view of the TiddlyWiki with only the enclosing tiddler opened

Usage:
{{{
<<permalink>>
}}}

!view macro - slice view

Allows access to a slice contained within a tiddler

Usage:
{{{
<<view text slice MySlice>>

will extract this slice:

|mySlice | slice content |
}}}

!view macro - section view

Provides access to a section contained within a tiddler

Usage:
{{{
<<view text section mySection>>

will extract this section:

!mySection
blah blah
!end of mySection

}}}

***/

//{{{
if(!version.extensions.templatingMacrosPlugin) {
version.extensions.templatingMacrosPlugin = {installed:true};

config.macros.permalink = {};
config.macros.permalink.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	var t = encodeURIComponent(String.encodeTiddlyLink(tiddler.title));
	createTiddlyText(place,window.location+"#"+t);
};

config.macros.view.views.slice = function(value,place,params,wikifier,paramString,tiddler) {
	var slice = "";
	if(params && params[2]) {
		slice = store.getTiddlerSlice(tiddler.title,params[2]);
		if(slice) {
			createTiddlyText(place,slice);
		}
	}
};

config.macros.view.views.section = function(value,place,params,wikifier,paramString,tiddler) {
	var section = "";
	if(params && params[2]) {
		section = store.getTiddlerText(tiddler.title+"##"+params[2]);
		if(section) {
			createTiddlyText(place,section);
		}
	}
};

} //# end of 'install only once'
//}}}
<<toggleTheme TiddlyWikiTheme TiddlyTweetsTheme>>
/***

|''Name:''|TiddlyTemplatingMacro |
|''Description:''|Renders a template and saves the output to a local file |
|''Author:''|JonathanLister|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/plugins/TiddlyTemplatingMacro.js |
|''Version:''|3 |
|''Date:''|25/3/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.3 |

Usage:
{{{
<<TiddlyTemplating template|template:tiddlerName [filter:filterString] [wikitext:true] [filename:filename]>>
}}}

Description:
Provides a button labelled "Publish" that triggers the templating and saving processes

***/

//{{{
if(!version.extensions.TiddlyTemplating) {
version.extensions.TiddlyTemplating = {installed:true};

var TiddlyTemplating = {
	defaultFileName:"output.txt"
};

config.macros.TiddlyTemplating = {};

config.macros.TiddlyTemplating.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	var button = createTiddlyButton(place,"Publish","Publish",config.macros.TiddlyTemplating.onclick);
	button.params = params;
	button.paramString = paramString;
};

config.macros.TiddlyTemplating.onclick = function(e)
{
	console.log(TiddlyTemplating);
	var p = this.paramString.parseParams("anon",null,true,false,false);
	var filename = TiddlyTemplating.getFileName(p);
	var template = TiddlyTemplating.getTemplate(p);
	var tiddlers = TiddlyTemplating.getTiddlers(p);
	var wikitext = getParam(p,"wikitext",null);
	displayMessage("generating...");
	TiddlyTemplating.templateAndPublish(filename,template,tiddlers,wikitext);
};

TiddlyTemplating.getFileName = function(p)
{
	console.log(p);
	var filename = getParam(p,"fileName");
	if(!filename) {
		filename = this.defaultFileName;
	}
	return filename;
};

TiddlyTemplating.getTemplate = function(p)
{
	var template = getParam(p,"template",null);
	if(!template) {
		template = getParam(p,"anon",null);
	}
	return template;
};

TiddlyTemplating.getTiddlers = function(p)
{
	var filter = getParam(p,"filter",null);
	var tiddlers = [];
	if(filter) {
		tiddlers = store.filterTiddlers(filter);
	} else {
		// no filter provided, so inherit or create temp tiddler
		tiddlers.push(tiddler ? tiddler : new Tiddler("temp"));
	}
	return tiddlers;
};

TiddlyTemplating.templateAndPublish = function(filename,template,tiddlers,isWikitext)
{
	var content = expandTemplate(template,tiddlers,isWikitext);
	if(window.location.protocol === 'file:') {
		this.saveToFile(filename,content);
	} else {
		this.saveToWindow(filename,content);
	}
};

TiddlyTemplating.saveToFile = function(filename,content)
{
	config.messages.fileSaved = "file successfully saved";
	config.messages.fileFailed = "file save failed";
	var localPath = getLocalPath(document.location.toString());
	var savePath;
	if((p = localPath.lastIndexOf("/")) != -1) {
		savePath = localPath.substr(0,p) + "/" + filename;
	} else {
		if((p = localPath.lastIndexOf("\\")) != -1) {
			savePath = localPath.substr(0,p) + "\\" + filename;
		} else {
			savePath = localPath + "." + filename;
		}
	}
	displayMessage("saving...");
	var fileSave = saveFile(savePath,convertUnicodeToUTF8(content));
	if(fileSave) {
		displayMessage("saved... click here to load","file://"+savePath);
	} else {
		alert(config.messages.fileFailed,"file://"+savePath);
	}
};

TiddlyTemplating.saveToWindow = function(name,content)
{
	var newwindow = window.open(null,name);
	var doc = newwindow.document;
	if(doc.contentDocument) { // NS6
		doc = newwindow.contentDocument;
	} else if(newwindow.contentWindow) { // IE
		doc = newwindow.contentWindow.document;
	}
	doc.open();
	doc.write("<html><head></head><body><textarea id='source' rows='20' cols='80'>(source code goes here)</textarea></body></html>");
	doc.close();
	var theTextBox = doc.getElementById("source");
	theTextBox.value = content;
	theTextBox.focus();
	theTextBox.select();
};

} //# end of 'install only once'
//}}}
You might be wondering what this is all about.

TiddlyTweets is the work of [[Fred|http://osmosoft.com/#%5B%5BFrederik%20Dohr%5D%5D]] and [[Jonathan|http://osmosoft.com/#%5B%5BJon%20Lister%5D%5D]] from [[Osmosoft|http://osmosoft.com]]. It serves as an example of a client-side mashup, creating a useful application in a web-friendly way, using only HTML, CSS and ~JavaScript.

If you're interested, you might like to know how this application is put together. It's really a [[TiddlyWiki|http://www.tiddlywiki.com]] loaded up with plugins. Read on for [[how to hack this|How to hack this]].
|''Name:''|TiddlyTweetsTheme|
|''Description:''|Simple theme for TiddlyTweets|
|''Author:''|Jonathan Lister (jnthnlstr (at) googlemail (dot) com)|
|''~CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/verticals/FNDTiddlyTweets/content/TiddlyTweetsTheme.tiddler |
|''Version:''|0.5|
|''Date:''|Mar 4, 2009|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]] |
|''~CoreVersion:''|2.4.0|

|''~StyleSheet:''|##StyleSheet|
|''~PageTemplate:''|##PageTemplate|
|''~ViewTemplate:''|##ViewTemplate|


!StyleSheet
/*{{{*/
div.header {
	margin:0em 17em 0 14em;
}

div.headerShadow { 
	color: #DF4141;
}

#displayArea,
div.header {
	margin-left: 17em;
}

div.logo {
	padding: 12px;
	padding-left: 15px;
	float: left;
	position: absolute;
	top: 20px;
	left: 800px;
	z-index: 2;
}

div.header,
div.headerShadow {
	background-color: #DF4141;
        -moz-border-radius-bottomleft: 5px;
        -moz-border-radius-bottomright: 5px;
        -webkit-border-bottom-left-radius: 5px;
        -webkit-border-bottom-right-radius: 5px;
}

.headerForeground {
	padding-top: 2em;
}

.siteTitle {
	padding-left: 1em;
	line-height: 1.6em;
}

.siteSubtitle {
	padding-left: 2em;
	font-style: italic;
}


div.viewer {
	font-size: 1.2em;
	line-height: 1.6em;
}

#tiddlerThemeSwitcher {
	position:absolute;
	top:0px;
	right:0px;
}

#backstageButton {
	display:none;
}

.wizard {
	background-color:#eeeeee;
        border:2px solid #888;
        -moz-border-radius:5px;
        -webkit-border-radius:5px;
	padding: 2em;
}

.wizard > h1 {
	display: none;
}

.wizardBody h2 {
	line-height: 2em;
}
.wizardBody h2:after {
	content: ":";
}

.wizardFooter {
	background-color:#eeeeee;
        border:none;
}

.wizardFooter .button,
.button {
	background-color: #DF4141;
	color: #fff;
	padding: 5px;
        -moz-border-radius:5px;
        -webkit-border-radius:5px;
	border:none;
        border-bottom: 1px solid #000;
        border-right: 1px solid #000;
}

#tiddlerTwitterBackupWizard {
	padding: 0em;
}

#tiddlerThemeSwitcher div.viewer .button {
	font-size: 1.2em;
	line-height: 1.6em;
	padding: 5px;
	border:none;
        border-bottom: 1px solid #000;
        border-right: 1px solid #000;
}

#tiddlerThemeSwitcher div.viewer .button:hover,
div.wizardFooter .button:hover {
	background-color: #3875D7;
	color: #fff;
	border:none;
        border-bottom: 1px solid #000;
        border-right: 1px solid #000;
}

.wizardStep {
	border-color:#4D294D;
	padding: 1em;
	margin-bottom: 1em;
}

.progress {
	background-color: #8A2BE2;
	display: block;
	height: 2em;
	margin-bottom: -2em;
	width: 0%;
}

/* GrowlStyle Message Area */
#messageArea {
        border:none;
        background: transparent;
}

#messageArea .messageBox {
        border:2px solid #888;
        color: #000;
	background-color:#eeeeee;
        width:20em;
        padding:10px;
        margin-top:5px;
        margin-bottom:5px;
        -moz-border-radius:5px;
        -webkit-border-radius:5px;
        filter:alpha(opacity=80);
}

#messageArea .messageText {
        display:block;
        width:15em;
        margin:0;
        padding:0;
}

#messageArea .messageClear {
        display:block;
        float:right;
        width:1em;
}

#messageArea .messageClear a {
        text-decoration:none;
        background-color: transparent;
        color:[[ColorPalette::Foreground]];
}


/*}}}*/

!ViewTemplate
<!--{{{--->
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->

!PageTemplate
<!--{{{-->
<div class='logo'><img src="http://xn--mns-ula.dk/Billeder/images/TwitterArchiverLogo.png"/></div>
<div class='header'>
<div class='headerShadow'>
<span class='siteTitle'></span>&nbsp;
<span class='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='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<div id='footer' refresh='content' tiddler='SiteFooter'></div>
<!--}}}-->
|''Name:''|DefaultTheme|
|''Description:''|Empty theme which resets to the defaults, leaving the ThemeSwitcher tiddler styled|

|''StyleSheet:''|##StyleSheet|

!StyleSheet
#tiddlerThemeSwitcher {
	position:absolute;
	top:0.6em;
	right:0;
}

#tiddlerThemeSwitcher div {
	display:none;
}

#tiddlerThemeSwitcher div.viewer {
	display:block;
}

#tiddlerThemeSwitcher div.viewer .button {
	background-color:#ffffff;
	border:#ffffff
}

#tiddlerThemeSwitcher div.viewer .button:hover {
	background-color:orange;
}
/***
|''Name:''|ToggleThemePlugin|
|''Description:''|Switches between two themes|
|''Author:''|Jonathan Lister (jnthnlstr (at) googlemail (dot) com)|
|''~CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/verticals/FNDTiddlyTweets/plugins/ToggleThemePlugin.js |
|''Version:''|0.1|
|''Date:''|Mar 4, 2009|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]] |
|''~CoreVersion:''|2.4|

!!Description
This plugin defines a theme selector button that allows you to select a theme from a list of tiddlers tagged with "systemTheme".

!!Usage
Include
{{{<<selectTheme>>}}}
in any tiddler to create a select theme button.

***/

//{{{
if(!version.extensions.ToggleThemePlugin) {
version.extensions.ToggleThemePlugin = {installed:true};

config.macros.toggleTheme = {

	label: "Skift tema",
	prompt: "Switch the theme from %0 to %1",

	getNewTheme: function(theme1,theme2) {
		var currentTheme = config.options.txtTheme;
		var newTheme = currentTheme === theme1 ? theme2 : theme1;
		return newTheme;
	},
	
	handler: function(place,macroName,params,wikfier,paramString,tiddler) {
		var theme1 = params[0];
		var theme2 = params[1];
		if(!(theme1 && theme2)) {
			throw "Error in toggleTheme: please provide two themes as parameters";
		}
		var newTheme  = this.getNewTheme(theme1,theme2);
		var plugin = this;
		var onClick = function() {
			var newTheme = plugin.getNewTheme(theme1,theme2);
			// switchTheme triggers this handler before changing config.options.txtTheme
			config.options.txtTheme = newTheme;
			story.switchTheme(newTheme);
		};
		var btn = createTiddlyButton(place,this.label,this.prompt.format([config.options.txtTheme,newTheme]),onClick);
	}
};

} //# end of 'install only once'
//}}}
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{

// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'tweetdk';

// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too

// disable autosave in d3
if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false;

// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}

// create some shadow tiddler content
merge(config.shadowTiddlers,{

'WelcomeToTiddlyspot':[
 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),

'TspotControls':[
 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),

'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")

});
//}}}
<<search>>
/***
|''Name''|TwitterAdaptor|
|''Description''|adaptor for retrieving data from Twitter|
|''Author''|FND|
|''Contributors''|[[Simon McManus|http://simonmcmanus.com]], MartinBudden|
|''Version''|0.3.6|
|''Status''|@@beta@@|
|''Source''|http://devpad.tiddlyspot.com/#TwitterAdaptor|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''CoreVersion''|2.5.0|
!Revision History
!!v0.2 (2008-10-23)
* initial release
!!v0.3 (2008-11-03)
* major refactoring
!To Do
* parsing of replies, DMs etc.
* document custom/optional context attributes (userID, userName, page, suppressUsers)
!Code
***/
//{{{
if(!version.extensions.TiddlyWebAdaptorPlugin) { //# ensure that the plugin is only installed once
version.extensions.TiddlyWebAdaptorPlugin = { installed: true };

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

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

adaptor.prototype = new AdaptorBase();
adaptor.serverType = "twitter";
adaptor.serverLabel = "Twitter";
adaptor.mimeType = "application/json";
adaptor.tweetTags = ["tweets"];
adaptor.userTags = ["users"];

adaptor.errorFunc = function(XMLHttpRequest, textStatus, errorThrown) {
	var message = this.errorMessage;
	displayMessage("There has been a wee problem..."+message+". Status: "+textStatus);
};

adaptor.prototype.getWorkspaceList = function(context, userParams, callback) {
	context = this.setContext(context, userParams, callback);
	context.workspaces = [
		{ title: "public" },
		{ title: "with_friends" }, // TODO: rename?
		{ title: "replies" },
		{ title: "direct_messages_in" },
		{ title: "direct_messages_out" },
		{ title: "friends" },
		{ title: "followers" },
		{ title: "users" },
		{ title: context.userName } // user timeline
	];
	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);
	var page = context.page || 0;
	var count = context.count || 20;
	switch(context.workspace) {
		case "public":
			var uriTemplate = "%0/statuses/public_timeline.json";
			var uri = uriTemplate.format([context.host]);
			break;
		case "with_friends":
			uriTemplate = "%0/statuses/friends_timeline.json?page=%1";
			uri = uriTemplate.format([context.host, page]);
			break;
		case "replies": // TODO: require special parsing
			uriTemplate = "%0/statuses/replies.json?page=%1";
			uri = uriTemplate.format([context.host, page]);
			break;
		case "direct_messages_in":
			uriTemplate = "%0/direct_messages.json?page=%1";
			uri = uriTemplate.format([context.host, page]);
			break;
		case "direct_messages_out":
			uriTemplate = "%0/direct_messages/sent.json?page=%1";
			uri = uriTemplate.format([context.host, page]);
			break;
		case "friends":
			if(context.userID) {
				uriTemplate = "%0/statuses/friends/%1.json?page=%2";
				uri = uriTemplate.format([context.host, context.userID, page]);
			} else {
				uriTemplate = "%0/statuses/friends.json?page=%2";
				uri = uriTemplate.format([context.host, page]);
			}
			break;
		case "followers":
			uriTemplate = "%0/statuses/followers.json?page=%1";
			uri = uriTemplate.format([context.host, page]);
			break;
		case "users":
			uriTemplate = "%0/users/show/%1.format";
			uri = uriTemplate.format([context.host, context.userID]);
			break;
		case "user_timeline":
		default: // user timeline
			if (context.userID) {
				uriTemplate = "%0/statuses/user_timeline/%1.json?page=%2&count=%3";
				uri = uriTemplate.format([context.host, context.userID, page, count]);
			} else {
				uriTemplate = "%0/statuses/user_timline.json?page=%1&count=%2";
				uri = uriTemplate.format([context.host, page, count]);
			}
			break;
	}
	/*var req = httpReq("GET", uri, adaptor.getTiddlerListCallback,
		context, null, null, { accept: adaptor.mimeType });*/
	jQuery.getJSONP = function(s) {
		console.log('getJSONP has been called in the Twitter adaptor');
	    s.dataType = 'jsonp';
	    jQuery.ajax(s);
	
	    var t = 0, cb = s.url.match(/callback=(\w+)/)[1], cbFn = window
	[cb];
	    var $script = jQuery('head script[src*='+cb+']');
	    if (!$script.length)
	        return; // same domain request
	
	    $script[0].onerror = function(e) {
	    	var text = $script;
	        //$script.remove();
	        jQuery.handleError(s, {}, "error", e);
	        clearTimeout(t);
	    };
	
	    if (!s.timeout)
	        return;
	
	    window[cb] = function(json) {
	        clearTimeout(t);
	        cbFn(json);
	        cbFn = null;
	    };
	
	    t = setTimeout(function() {
	        $script.remove();
	        jQuery.handleError(s, {}, "timeout");
	        if (cbFn)
	            window[cb] = function(){};
	    }, s.timeout);
	};
	var opt = {
		url: uri,
		dataType: 'jsonp',
		success: adaptor.getTiddlerListCallback,
		error: adaptor.errorFunc,
		context: context
	};
	jQuery.getJSONP(opt);
	/*
	var req = jQuery.ajax({
		url: uri,
		dataType: 'jsonp',
		success: adaptor.getTiddlerListCallback,
		error: adaptor.errorFunc,
		errorMessage: "Problem getting data from Twitter",
		context: context
	});
	return typeof req == "string" ? req : true;
	*/
};

adaptor.getTiddlerListCallback = function(data, textStatus) {
	var context = this.context;
	var tweets = data;
	context.tiddlers = [];
	var users = {};
	for(var i = 0; i < tweets.length; i++) {
		var tiddler = adaptor.parseTweet(tweets[i]);
		context.tiddlers.push(tiddler);
		if(!context.suppressUsers) { // retain user info
			var user = tweets[i].user;
			user.updated = adaptor.convertTimestamp(tweets[i].created_at);
			if(!(users[user.id] && user.updated > users[user.id].modified)) {
				users[user.id] = adaptor.parseUser(user);
				users[user.id].fields = {
					"server.type": adaptor.serverType,
					"server.host": AdaptorBase.minHostName(context.host),
					"server.workspace": "users"
				};
			}
		}
	}
	context.tweets = context.tiddlers.length;
	for(user in users) { // XXX: should be for each, but JSLint doesn't recognize that
		context.tiddlers.push(users[user]);
	}
	if(context.callback) {
		context.callback(context, context.userParams);
	}
};

adaptor.prototype.getTiddler = function(title, context, userParams, callback) {
	context = this.setContext(context, userParams, callback);
	context.title = title;
	var fields = {
		"server.type": adaptor.serverType,
		"server.host": AdaptorBase.minHostName(context.host),
		"server.workspace": context.workspace
	};
	// reuse previously-requested tiddlers
	if(context.tiddler) {
		context.tiddler.fields = merge(context.tiddler.fields, fields, true);
	}
	// do not re-request non-truncated tweets
	if(context.tiddler && (context.tiddler.fields.truncated === false || context.tiddler.fields["server.workspace"] == "users")) {
		context.status = true;
		var subcontext = merge({}, context);
		window.setTimeout(function() { callback(subcontext, context.userParams); }, 0);
		return true;
	}
	// request individual tweet
	if(!context.tiddler || context.tiddler.fields.truncated === undefined) { // truncated flag as indicator of actual tweet
		context.tiddler = new Tiddler(title);
		context.tiddler.modifier = context.workspace;
		context.tiddler.fields = fields;
	}
	var uriTemplate = "%0/statuses/show/%1.json";
	var uri = uriTemplate.format([context.host, title]);
	/*var req = httpReq("GET", uri, adaptor.getTiddlerCallback,
		context, null, null, { accept: adaptor.mimeType });*/
	var req = jQuery.ajax({
		url: uri,
		dataType: 'jsonp',
		success: adaptor.getTiddlerCallback,
		error: adaptor.errorFunc,
		errorMessage: "Problem getting data from Twitter",
		context: context
	});
	return typeof req == "string" ? req : true;
};

adaptor.getTiddlerCallback = function(data, textStatus) {
	var context = this.context;
	var tweet = data;
	var tiddler = adaptor.parseTweet(tweet);
	tiddler.fields = merge(context.tiddler.fields, tiddler.fields, true);
	context.tiddler = tiddler;
	if(context.callback) {
		if(context.tiddler.fields.truncated) {
			var subContext = merge({},context);
			subContext.tiddler = context.tiddler;
			if(window.location.protocol!=='file') {
				// do pass on truncated tweet to callback even though we can't request full tweet
				context.callback(context, context.userParams);
			} else {
				context.callback(context, context.userParams);
				context.adaptor.getFullTweet(subContext, context.userParams, context.callback);
			}
		} else {
			context.callback(context, context.userParams);
		}
	}
};

// re-request truncated tweet - need to be offline for this
adaptor.prototype.getFullTweet = function(context, userParams, callback) {
	context = this.setContext(context, userParams, callback);
	var uriTemplate = "%0/%1/status/%2";
	var uri = uriTemplate.format([context.host, context.userID, context.tiddler.title]);
	var req = httpReq("GET", uri, adaptor.getFullTweetCallback, context);
	return typeof req == "string" ? req : true;
};

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

// convert tweet to tiddler object
adaptor.parseTweet = function(tweet) {
	var tiddler = new Tiddler(tweet.id.toString());
	tiddler.created = adaptor.convertTimestamp(tweet.created_at);
	tiddler.modified = tiddler.created;
	tiddler.modifier = tweet.user.id.toString();
	tiddler.tags = adaptor.tweetTags;
	tiddler.fields = {
		source: tweet.source, // TODO: split into appName and appURI
		truncated: tweet.truncated,
		favorited: tweet.favorited,
		context: tweet.in_reply_to_status_id,
		user: tweet.user.id,
		username: tweet.user.name, // XXX: obsolete due to separate user info?
		usernick: tweet.user.screen_name // TODO: rename --  XXX: obsolete due to separate user info?
	};
	tiddler.text = adaptor.decodeHTMLEntities(tweet.text);
	return tiddler;
};

// convert user to tiddler object
adaptor.parseUser = function(user) {
	var tiddler = new Tiddler(user.id.toString());
	tiddler.created = user.updated; // XXX: not quite correct (updated vs. created)
	tiddler.modified = tiddler.created;
	tiddler.modifier = user.id.toString();
	tiddler.tags = adaptor.userTags;
	var slice = "|''%0''|%1|\n";
	tiddler.text = slice.format(["ID", user.id]) +
		slice.format(["ScreenName", user.screen_name]) +
		slice.format(["FullName", user.name]) +
		slice.format(["URL", user.url]) +
		slice.format(["Icon", user.profile_image_url]) +
		slice.format(["Bio", user.description]) +
		slice.format(["Location", user.location]) +
		slice.format(["Followers", user.followers_count]) +
		slice.format(["Protected", user.protected]);
	return tiddler;
};

// retrieve untruncated tweet (cf. http://code.google.com/p/twitter-api/issues/detail?id=133)
adaptor.scrapeTweet = function(html) {
	// load HTML page
	var ifrm = document.createElement("iframe");
	ifrm.style.display = "none";
	document.body.appendChild(ifrm);
	var doc = ifrm.document;
	if(ifrm.contentDocument) { // NS6
		doc = ifrm.contentDocument;
	} else if(ifrm.contentWindow) { // IE
		doc = ifrm.contentWindow.document;
	}
	doc.open();
	doc.writeln(html);
	doc.close();
	// retrieve status message
	var container = doc.getElementById("permalink");
	var spans = container.getElementsByTagName("span");
	for(i = 0; i < spans.length; i++) {
		if(spans[i].className == "entry-content") {
			var tweet = spans[i];
			var text = tweet.text || tweet.textContent; // strip descendants' markup -- XXX: cross-browser compatible?
			break;
		}
	}
	removeNode(ifrm);
	return adaptor.decodeHTMLEntities(text.trim());
};

// convert timestamp ("mmm 0DD 0hh:0mm:0ss +0000 YYYY") to Date instance
adaptor.convertTimestamp = function(str) {
	var c = str.match(/(\w+) (\d+) (\d+):(\d+):(\d+) \+\d+ (\d+)/);
	return new Date(c[6], adaptor.convertShortMonth(c[1]),
		c[2], c[3], c[4], c[5]);
};

// convert short-month string (mmm) to month number (zero-based)
adaptor.convertShortMonth = function(text) {
	for(var i = 0; i < config.messages.dates.shortMonths.length; i++) { // XXX: inefficient!?
		if(text == config.messages.dates.shortMonths[i]) {
			return i;
		}
	}
};

// convert HTML entities to the respective characters
adaptor.decodeHTMLEntities = function(str) {
	var el = document.createElement("textarea");
	el.innerHTML = str;
	return el.value;
};

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

} //# end of "install only once"
//}}}
<<tiddler SøgTweets>>
<<TwitterBackupWizard>>
{{textcenter{
@@padding-left:45%;+++[Hvad er dette?]...<br>[<<tiddler TiddlyTweets>>

[[Link:|http://twitter.com]]
<html><div align="center"><iframe src="http://twitter.com" frameborder="2" width="100%" height="400"></iframe></div></html>
|''Type''|twitter|
|''URL''|http://www.twitter.com|
<<tiddler HideTiddlerBackground>><<tiddler HideTiddlerTags>>/%

- - - - - TAB DEFINITIONS - - - - -

%/<<tabs twitterTabs
	'søg'		'søg efter tweets'		[[TwitterTabs##searchForm]]
	'TiddlyWiki'		'tweets fra TiddlyWiki'	[[TwitterTabs##TiddlyWiki]]
	'tiddlytools'		'tweets fra tiddlytools'	[[TwitterTabs##tiddlytools]]
	'jermolene'		'tweets fra jermolene'		[[TwitterTabs##jermolene]]
>>/%
!searchForm
<<tiddler [[TwitterTabs##searchForTweets]]
	with: {{config.options.txtTweetSearch=config.options.txtTweetSearch||'TiddlyWiki'}}>>
!TiddlyWiki
<<tiddler [[TwitterTabs##showUserTweets]] with: TiddlyWiki>>
!jermolene
<<tiddler [[TwitterTabs##showUserTweets]] with: jermolene>>
!tiddlytools
<<tiddler [[TwitterTabs##showUserTweets]] with: tiddlytools>>
!end

- - - - - TAB CONTENT FORMATTING - - - - -

!searchForTweets
Søg efter tweets som indeholder: <<option txtTweetSearch>> {{fine{//(indskriv tekst, klik derefter på 'søg' fanen igen for at opdatere resultater)//}}}
''__[[Aktuelle tweets om: "$1"|http://search.twitter.com/search?q=$1]]__''
<hr>@@display:block;height:20em;overflow:auto;
<script src="http://search.twitter.com/search.json?q=$1&rpp=25&callback=twitterCallback">
	window.twitterPlace=place;
</script>@@@@display:block;text-align:right;^^rul ned for at se flere...^^@@
!end

!showUserTweets
''__[[Recent tweets from $1|http://twitter.com/$1]]__''
<hr>@@display:block;height:20em;overflow:auto;
<script src="http://twitter.com/statuses/user_timeline/$1.json?callback=twitterCallback">
	window.twitterPlace=place;
</script>@@@@display:block;text-align:right;^^scroll for more...^^@@
!end

- - - - - CALLBACK RENDERING FUNCTION - - - - -

%/<script>
window.twitterCallback=function(data){ // render data items returned from twitter.com
	var fmt=store.getTiddlerText('TwitterTabs##itemFormat');
	if (data.results) data=data.results; // for SEARCH results
	for (var i=0; i<data.length; i++) { var item=data[i];
		var img=item.user? item.user.profile_image_url : item.profile_image_url;
		var who=item.user? item.user.screen_name : item.from_user;
		wikify(fmt.format([img,who,item.text,item.created_at]),window.twitterPlace);
	}
}
</script>/%

- - - - - TWEET ITEM FORMAT - - - - -

!itemFormat
[<img(48px+,48px+)[%0]][[%1|http://twitter.com/%1]]: %2
{{fine{
%3}}} {{clear{
}}}<br>
!end

NOTE:  (48px+,48px+) syntax requires [[ImageSizePlugin]]

%/
/***
|''Name''|TwitterWizardPlugin|
|''Description''|interface for retrieving tweets and user data from Twitter|
|''Author''|FND, JonathanLister|
|''Version''|0.2.0|
|''Status''|@@experimental@@|
|''Requires''|TwitterAdaptorPlugin|
|''Source''|http://devpad.tiddlyspot.com/#TwitterArchivePlugin|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''CoreVersion''|2.5.0|
!Usage
{{{
<<TiddlyTweets [workspace] [pages]>>
}}}
{{{
<<TwitterWizard>>
}}}
!Revision History
!!v0.2 (2009-03-04)
* jsonp
* made it work
!!v0.1 (2008-11-14)
* initial release
!To Do
* documentation
* abort conditions: empty response or tweet already archived
* report when retrieval has been completed
* disable wiki markup for tweets
!Code
***/
//{{{
if(!version.extensions.TwitterWizardPlugin) { //# ensure that the plugin is only installed once
version.extensions.TwitterWizardPlugin = { installed: true };

if(!config.adaptors.twitter) {
	throw "Missing dependency: TwitterAdaptor";
}

config.macros.TiddlyTweets = {
	btnLabel: "TiddlyTweets",
	btnTooltip: "hent tweets",
	usernamePrompt: "skriv Twitter brugernavn",

	host: "http://www.twitter.com",
	requestDelay: 1000, // delay between page requests
	adaptor: new config.adaptors.twitter(),

	handler: function(place, macroName, params, wikifier, paramString, tiddler) {
		this.pageCount = 0; // XXX: means there can only be a single instance!!
		createTiddlyButton(place, this.btnLabel, this.btnTooltip,
			function() { config.macros.TiddlyTweets.dispatcher(params); });
	},

	dispatcher: function(params) { // TODO: rename
		var self = config.macros.TiddlyTweets;
		var maxPages = params[1] || 1;
		self.maxPages = maxPages;
		var count = params[2];
		if(self.pageCount <= maxPages) {
			var username = params[0] || prompt(self.usernamePrompt);
			setTimeout(function() { self.dispatcher(params); },
				self.requestDelay);
			self.launcher(username, self.pageCount, count);
			self.pageCount++;
		} else {
			self.pageCount = 1;
		}
	},

	launcher: function(username, page, count) { // TODO: rename
		var self = config.macros.TiddlyTweets;
		var context = {
			host: self.host,
			workspace: "user_timeline",
			userID: username,
			page: page,
			count: count
		};
		self.adaptor.getTiddlerList(context, null, self.processor);
		/*
		var status = self.adaptor.getTiddlerList(context, null, self.processor);
		if(status !== true) {
			displayMessage("error retrieving page " + context.page); // TODO: i18n
		}
		*/
	},

	processor: function(context, userParams) { // TODO: rename
		var self = config.macros.TiddlyTweets;
		self.doneRequestCount++;
		self.totalReturnedTiddlers += context.tweets;
		if(self.doneRequestCount === self.maxPages) {
			displayMessage('all the page requests have returned and been processed!');
			if(self.totalReturnedTiddlers!==self.tweetCount) {
				var difference = self.tweetCount - self.totalReturnedTiddlers;
				displayMessage('total tweets doesn\'t match predicted number, there are '+difference+' missing tweets');
			} else {
				displayMessage('all expected tweets returned');
			}
		}
		for(var i = 0; i < context.tweets; i++) {
			context.tiddler = context.tiddlers[i];
			self.adaptor.getTiddler(context.tiddler.title, context, null, self.saver);
		}
	},

	saver: function(context, userParams) { // TODO: rename
		var self = config.macros.TiddlyTweets;
		var tiddler = context.tiddler;
		store.saveTiddler(tiddler.title, tiddler.title, tiddler.text,
			tiddler.modifier, tiddler.modified, tiddler.tags,
			tiddler.fields, false, tiddler.created);
		self.savedTweets++;
		self.progressBar.style.width = (self.savedTweets / self.tweetCount)*100 +'%';
		console.log(self.progressBar.style.width);
		if(self.savedTweets === self.tweetCount) {
			displayMessage('saved all tweets! finished!');
		}
	},

	// this function could probably move out to the TwitterBackWizard macro
	// then TiddlyTweets macro should have some instantiation with params like pageCount and launchCount
	handleWizard: function(w) {
		var self = config.macros.TiddlyTweets;
		self.pageCount = 1;
		self.doneRequestCount = 0;
		self.totalReturnedTiddlers = 0;
		self.savedTweets = 0;
		self.tweetCount = w.tweetCount;
		var params = [
			w.username,
			w.maxPages,
			200
		];
		w.addStep("Downloading","<span class='progress'></span>");
		var stepElem = w.bodyElem.getElementsByTagName('div')[1];
		stepElem.style.padding = 0;
		stepElem.style.paddingBottom = "2em";
		w.setButtons([{
			caption: "Search these tweets",
			tooltip: "Search these tweets",
			onClick: function() {
				story.displayTiddler("bottom","TweetTrawler");
				return false;
			}
		},
		{
			caption: "Gem til CSV",
			tooltip: "Gem til CSV",
			onClick: function() {
				TiddlyTemplating.templateAndPublish(w.username+'.csv','CsvTemplate');
				return false;
			}
		},
		{
			caption: "Gør det igen!",
			tooltip: "Start forfra",
			onClick: function() {
				var w = new Wizard(this);
				var place = w.clear();
				config.macros.TwitterBackupWizard.restart(w);
				return false;
			}
		}]);
		self.progressBar = w.bodyElem.getElementsByTagName('span')[0];
		self.dispatcher(params);
	}
};

jQuery.getJSONP = function(s) {
	console.log('getJSONP has been called in the Twitter Archiver wizard');
    s.dataType = 'jsonp';
    jQuery.ajax(s);

    var t = 0, cb = s.url.match(/callback=(\w+)/)[1], cbFn = window
[cb];
    var $script = jQuery('head script[src*='+cb+']');
    if (!$script.length)
        return; // same domain request

    $script[0].onerror = function(e) {
    	var text = $script;
        //$script.remove();
        jQuery.handleError(s, {}, "error", e);
        clearTimeout(t);
    };

    if (!s.timeout)
        return;

    window[cb] = function(json) {
        clearTimeout(t);
        cbFn(json);
        cbFn = null;
    };

    t = setTimeout(function() {
        $script.remove();
        jQuery.handleError(s, {}, "timeout");
        if (cbFn)
            window[cb] = function(){};
    }, s.timeout);
};

// like the more ambitious TwitterWizard below, but only for your tweets
// includes a step to check how many tweets you have and work out maxPages from that
config.macros.TwitterBackupWizard = {
	handler: function(place, macroName, params, wikifier, paramString, tiddler, errorMsg) {
		var w = new Wizard();
		w.createWizard(place, "Twitter Backup Wizard");
		this.restart(w);
	},
	
	restart: function(w) {
		var self = config.macros.TwitterBackupWizard;
		var onClick = function() {
			w.username = w.getValue('username').value;
			self.step2(w);
			return false;
		};
		w.addStep("Skriv venligst dit Twitter brugernavn", "<input name='username'>");
		w.formElem.onsubmit = onClick;
		w.setButtons([{
			caption: "Lad os komme i gang",
			tooltip: "For det første, klik for at tælle dine tweets",
			onClick: onClick
		}]);
	},

	handleProfilePageToCountUpdates: function(person, textStatus) {
		var tweetCount = person.statuses_count;
		var w = this.wizard;
		config.macros.TwitterBackupWizard.step3(w, tweetCount);
	},

	step2: function(w) {
		w.addStep("Hello " + w.username + ", counting your tweets", "<span>hold your horses!</span>");
		w.setButtons([]);
		var self = config.macros.TwitterBackupWizard;
		var host = "http://www.twitter.com";
		var url = host + "/users/show/" + w.username + ".json";
		var context = {
			wizard: w
		};
		//var req = httpReq("GET", url, self.handleProfilePageToCountUpdates, context);
		try {
		var opt = {
			url: url,
			//url: 'http://jquery.com/Test.php',
			dataType: 'jsonp',
			success: self.handleProfilePageToCountUpdates,
			error: self.errorFunc,
			wizard: w
		};
		jQuery.getJSONP(opt);
		} catch(e) {
			console.log(e,e.message);
		}
	},

	step3: function(w, tweetCount) {
		var step3html = "";
		if(tweetCount > 3200) {
			step3html += "we need the Power of Greyskull to get back further than that! Let's do what we can...<p /><img src='http://www.dvdplaza.fi/reviews/images/heman46_000.jpg' title='image from http://www.dvdplaza.fi/' />";
			w.addStep("oh noes "+w.username+"!, you've got "+tweetCount+" tweets and I can only get the first 3200 tweets", step3html);
			tweetCount = 3200;
		} else {
			step3html = "This might take a moment...";
			w.addStep(w.username+", you've got " + tweetCount + " tweets!", step3html);
		}
		w.tweetCount = tweetCount;
		w.maxPages = Math.ceil(parseInt(tweetCount, 10) / 200);
		w.setButtons([{
			caption: "Download tweets",
			tooltip: "Download " + tweetCount + " tweets",
			onClick: function() { config.macros.TiddlyTweets.handleWizard(w); }
		},
		{
			caption: "Go back",
			tooltip: "Oops! Wrong username, take me back",
			onClick: function() {
				var w = new Wizard(this);
				var place = w.clear();
				config.macros.TwitterBackupWizard.restart(w);
				return false;
			}
		}]);
	},
	
	errorFunc: function(XMLHttpRequest, textStatus, errorThrown) {
		var w = this.wizard;
		var addResetButton = function(wizard) {
			wizard.setButtons([{
				caption: "Start again!",
				tooltip: "Start again!",
				onClick: function() {
					var w = new Wizard(wizard.formElem);
					var place = w.clear();
					config.macros.TwitterBackupWizard.restart(w);
					return false;
				}
			}]);
		};
		if(!self.apiLimitChecked) {
			w.addStep("Ah. There has been a wee problem... maybe we're hammering Twitter too much", "checking your API rate limit...");
			var twitterAPICheckerCallback = function(limitObj) {
				self.apiLimitChecked = false; // ensure future errors trigger limit check again
				var limit = limitObj.hourly_limit;
				var remaining = limitObj.remaining_hits;
				var w = this.wizard;
				var errorHTML = "";
				if(remaining > 0) {
					errorHTML = "you have "+remaining+" calls left from an hourly limit of "+limit+"<p/>best check the twitter account exists: <a href='http://twitter.com/"+w.username+"' target='_blank'>"+w.username+"</a>";
				} else {
					var resetTime = limitObj.reset_time_in_seconds*1000 - new Date().getTime();
					resetTime = new Date().getTime() + resetTime;
					resetTime = new Date(resetTime);
					errorHTML = "you've run out of calls to the API; wait a while and try again<p/>your limit will reset in less than "+resetTime.getMinutes()+" minutes";
				}
				w.addStep("Checked your rate limit",errorHTML);
				addResetButton(w);
			};
			var opt = {
				url: "http://twitter.com/account/rate_limit_status.json",
				dataType: 'jsonp',
				success: twitterAPICheckerCallback,
				error: arguments.callee,
				wizard: w
			};
			self.apiLimitChecked = true;
			jQuery.getJSONP(opt);
		} else {
			self.apiLimitChecked = false; // ensure future errors trigger limit check again
						w.addStep("Error checking rate limit","maybe Twitter is down?<br/><a href='http://istwitterdown.com' target='_blank'>istwitterdown.com</a>");
			addResetButton(w);
		}
	}
};

/*** past here, code is not used in Twitter Archiver ***/

// Twitter archiving wizard -- XXX: experimental, incomplete -- TODO: i18n
config.macros.TwitterWizard = {
	handler: function(place, macroName, params, wikifier, paramString, tiddler, errorMsg) {
		var w = new Wizard();
		w.createWizard(place, "Twitter Wizard");
		w.addStep("Twitter username", "<input name='username'>");
		w.setButtons([{
			caption: "Import",
			tooltip: "click to import",
			onClick: function() { config.macros.twitter.step1(w); }
		}]);
	},

	step1: function(w) {
		var step1Html = "<input name='my_tweets' type='checkbox' /><label>My Tweets</label><br />" +
			"<input name='contacts' type='checkbox' /><label>My Contacts</label><br />" +
			"<input name='contacts_tweets' type='checkbox' /><label>My Contacts Tweets</label><br />";
		w.addStep("account :" + w.formElem.twitter_id.value, step1Html);
		w.setButtons([{
			caption: "Import 2",
			tooltip: "click to import",
			onClick: function() { config.macros.twitter.step2(w); }
		}]);
	},

	step2: function(w) {
		w.addStep("enter password for " + w.formElem.twitter_id.value,
			"<input name='twitter_password' type='password'/>");
		w.setButtons([{
			caption: "Import",
			tooltip: "click to import",
			onClick: function() { config.macros.TwitterWizard.step3(w); }
		}]);
	},

	step3: function(w) {
		var html = w.formElem.twitter_id.value + "<br />" +
			w.formElem.my_tweets + "<br />" +
			w.formElem.twitter_password.value + "<br />";
		w.addStep("All Done", html);
	}
};

} //# end of "install only once"
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 28/04/2009 23:07:58 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . |
| 28/04/2009 23:14:54 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . | ok |
| 28/04/2009 23:16:02 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . | ok |
| 28/04/2009 23:17:02 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . |
| 28/04/2009 23:26:48 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . |
| 28/04/2009 23:42:59 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . | ok |
| 28/04/2009 23:44:30 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . | ok |
| 28/04/2009 23:47:15 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . |
| 29/04/2009 09:23:10 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . | ok |
| 29/04/2009 09:26:15 | DitNavn | [[/|http://tweetdk.tiddlyspot.com/]] | [[store.cgi|http://tweetdk.tiddlyspot.com/store.cgi]] | . | [[index.html | http://tweetdk.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 3,
	date: new Date("Feb 24, 2008"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

//
// Environment
//

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

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

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

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

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

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

//
// uploadOptions Macro
//

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

//
// upload functions
//

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

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

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

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

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

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

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

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

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

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

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

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

//
// Utilities
// 

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

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

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

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

//
// Initializations
//

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

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

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

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


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


//}}}

/***
|''Name:''|WikifiedMessagesPlugin|
|''Description:''|Wikify displayMessage text  |
|''Author:''|PaulDowney (psd (at) osmosoft (dot) com) |
|''Source:''|http://whatfettle.com/2008/07/WikifiedMessagesPlugin/ |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/PaulDowney/plugins/WikifiedMessagesPlugin/ |
|''Version:''|0.4|
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''~CoreVersion:''|2.4|
!!Documentation
A plugin to replace the core displayMessage function with a version which wikifies the message text.
The construction of the [close] single message and [close all] buttons has been seperated to be overrideable and the created message div is returned by displayMessage, for extensibility by other plugins.
!!Code
***/
//{{{
if(!version.extensions.WikifiedMessagesPlugin) {
version.extensions.WikifiedMessagesPlugin = {installed:true};

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

	config.extensions.WikifiedMessages = {

		createClearAllButton: function(msgArea)
		{
			return (msgArea.hasChildNodes())? null :
				createTiddlyButton(createTiddlyElement(msgArea,"div",null,"messageToolbar"),
					config.messages.messageClose.text,
					config.messages.messageClose.tooltip,
					clearMessage);
		},
		createClearMessageButton: function(e)
		{
			return null;
		},
		getMessageDiv: function()
		{
			var msgArea = document.getElementById("messageArea");
			var me = config.extensions.WikifiedMessages;
			if(!msgArea){
				return null;
			}
			msgArea.style.display = "block";
			me.createClearAllButton(msgArea);
			e = createTiddlyElement(msgArea,"div",null,"messageBox");
			me.createClearMessageButton(e);
			return e;
		},
		displayMessage: function(text,linkText)
		{
			var e = getMessageDiv();
			if(!e) {
				alert(wikifyPlain(text));
				return null;
			}
			if(linkText) {
				text = "[["+text+"|"+linkText+"]]";
			}
			t = createTiddlyElement(e,"span",null,"messageText");
			t.innerHTML = wikifyStatic(text);
			return e;
		}
	};

	displayMessage = config.extensions.WikifiedMessages.displayMessage;
	getMessageDiv = config.extensions.WikifiedMessages.getMessageDiv;

        // macro, useful for testing
        config.macros.DisplayMessage = {
                handler: function(place,macroName,params,wikifier,paramString,tiddler){
                        displayMessage(paramString);
                }
        };
}
//}}}
/***
|''Name:''|YourSearchPlugin|
|''Version:''|2.1.0 (2006-10-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin ([[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23YourSearchPlugin]])|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2006 [[abego Software|http://www.abego-software.de]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; ~InternetExplorer 6.0|
!About YourSearch
YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!

For more information see [[Help|YourSearch Help]].
!Compatibility
This plugin requires TiddlyWiki 2.1. 
Check the [[archive|http://tiddlywiki.abego-software.de/archive]] for ~YourSearchPlugins supporting older versions of TiddlyWiki.
!Source Code
***/
/***
This plugin's source code is compressed (and hidden). Use this [[link|http://tiddlywiki.abego-software.de/archive/YourSearchPlugin/Plugin-YourSearch-src.2.1.0.js]] to get the readable source code.
***/
///%
if(!version.extensions.YourSearchPlugin){version.extensions.YourSearchPlugin={major:2,minor:1,revision:0,source:"http://tiddlywiki.abego-software.de/#YourSearchPlugin",licence:"[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",copyright:"Copyright (c) abego Software GmbH, 2005-2006 (www.abego-software.de)"};if(!window.abego){window.abego={};}if(!Array.forEach){Array.forEach=function(_1,_2,_3){for(var i=0,len=_1.length;i<len;i++){_2.call(_3,_1[i],i,_1);}};Array.prototype.forEach=function(_5,_6){for(var i=0,len=this.length;i<len;i++){_5.call(_6,this[i],i,this);}};}abego.toInt=function(s,_9){if(!s){return _9;}var n=parseInt(s);return (n==NaN)?_9:n;};abego.createEllipsis=function(_b){var e=createTiddlyElement(_b,"span");e.innerHTML="&hellip;";};abego.shallowCopy=function(_d){if(!_d){return _d;}var _e={};for(var n in _d){_e[n]=_d[n];}return _e;};abego.copyOptions=function(_10){return !_10?{}:abego.shallowCopy(_10);};abego.countStrings=function(_11,s){if(!s){return 0;}var len=s.length;var n=0;var _15=0;while(1){var i=_11.indexOf(s,_15);if(i<0){return n;}n++;_15=i+len;}return n;};abego.getBracedText=function(_17,_18,_19){if(!_18){_18=0;}var re=/\{([^\}]*)\}/gm;re.lastIndex=_18;var m=re.exec(_17);if(m){var s=m[1];var _1d=abego.countStrings(s,"{");if(!_1d){if(_19){_19.lastIndex=re.lastIndex;}return s;}var len=_17.length;for(var i=re.lastIndex;i<len&&_1d;i++){var c=_17.charAt(i);if(c=="{"){_1d++;}else{if(c=="}"){_1d--;}}}if(!_1d){if(_19){_19.lastIndex=i-1;}return _17.substring(m.index+1,i-1);}}};abego.select=function(_21,_22,_23,_24){if(!_24){_24=[];}_21.forEach(function(t){if(_22.call(_23,t)){_24.push(t);}});return _24;};abego.TiddlerFilterTerm=function(_26,_27){if(!_27){_27={};}var _28=_26;if(!_27.textIsRegExp){_28=_26.escapeRegExp();if(_27.fullWordMatch){_28="\\b"+_28+"\\b";}}var _29=new RegExp(_28,"m"+(_27.caseSensitive?"":"i"));this.tester=new abego.MultiFieldRegExpTester(_29,_27.fields,_27.withExtendedFields);};abego.TiddlerFilterTerm.prototype.test=function(_2a){return this.tester.test(_2a);};abego.parseNewTiddlerCommandLine=function(s){var m=/(.*?)\.(?:\s+|$)([^#]*)(#.*)?/.exec(s);if(!m){m=/([^#]*)()(#.*)?/.exec(s);}if(m){var r;if(m[3]){var s2=m[3].replace(/#/g,"");r=s2.parseParams("tag");}else{r=[[]];}var _2f=m[2]?m[2].trim():"";r.push({name:"text",value:_2f});r[0].text=[_2f];return {title:m[1].trim(),params:r};}else{return {title:s.trim(),params:[[]]};}};abego.parseTiddlerFilterTerm=function(_30,_31,_32){var re=/\s*(?:(?:\{([^\}]*)\})|(?:(=)|([#%!])|(?:(\w+)\s*\:(?!\/\/))|(?:(?:("(?:(?:\\")|[^"])+")|(?:\/((?:(?:\\\/)|[^\/])+)\/)|(\w+\:\/\/[^\s]+)|([^\s\)\-\"]+)))))/mg;var _34={"!":"title","%":"text","#":"tags"};var _35={};var _36;re.lastIndex=_31;while(1){var i=re.lastIndex;var m=re.exec(_30);if(!m||m.index!=i){throw "Word or String literal expected";}if(m[1]){var _39={};var _3a=abego.getBracedText(_30,0,_39);if(!_3a){throw "Invalid {...} syntax";}var f=Function("tiddler","return ("+_3a+");");return {func:f,lastIndex:_39.lastIndex,markRE:null};}if(m[2]){_36=true;}else{if(m[3]){_35[_34[m[3]]]=1;}else{if(m[4]){_35[m[4]]=1;}else{var _3c=m[6];var _3d=m[5]?window.eval(m[5]):m[6]?m[6]:m[7]?m[7]:m[8];var _32=abego.copyOptions(_32);_32.fullWordMatch=_36;_32.textIsRegExp=_3c;var _3e=[];for(var n in _35){_3e.push(n);}if(_3e.length==0){_32.fields=_32.defaultFields;}else{_32.fields=_3e;_32.withExtendedFields=false;}var _40=new abego.TiddlerFilterTerm(_3d,_32);var _41=_3c?_3d:_3d.escapeRegExp();if(_41&&_36){_41="\\b"+_41+"\\b";}return {func:function(_42){return _40.test(_42);},lastIndex:re.lastIndex,markRE:_41?"(?:"+_41+")":null};}}}}};abego.BoolExp=function(s,_44,_45){this.s=s;var _46=_45&&_45.defaultOperationIs_OR;var _47=/\s*(?:(\-|not)|(\())/gi;var _48=/\s*\)/g;var _49=/\s*(?:(and|\&\&)|(or|\|\|))/gi;var _4a=/\s*[^\)\s]/g;var _4b=/\s*(\-|not)?(\s*\()?/gi;var _4c=function(_4d){_4b.lastIndex=_4d;var m=_4b.exec(s);var _4f;var _50;if(m&&m.index==_4d){_4d=_4b.lastIndex;_4f=m[1];if(m[2]){var e=parseBoolExpression(_4d);_48.lastIndex=e.lastIndex;if(!_48.exec(s)){throw "Missing ')'";}_50={func:e.func,lastIndex:_48.lastIndex};}}if(!_50){_50=_44(s,_4d,_45);}if(_4f){_50.func=(function(f){return function(_53){return !f(_53);};})(_50.func);_50.markRE=null;}return _50;};var _54=function(_55){var _56=_4c(_55);while(1){var l=_56.lastIndex;_49.lastIndex=l;var m=_49.exec(s);var _59;var _5a;if(m&&m.index==l){_59=!m[1];_5a=_4c(_49.lastIndex);}else{try{_5a=_4c(l);}catch(e){return _56;}_59=_46;}_56.func=(function(_5b,_5c,_5d){return _5d?function(_5e){return _5b(_5e)||_5c(_5e);}:function(_5f){return _5b(_5f)&&_5c(_5f);};})(_56.func,_5a.func,_59);_56.lastIndex=_5a.lastIndex;if(!_56.markRE){_56.markRE=_5a.markRE;}else{if(_5a.markRE){_56.markRE=_56.markRE+"|"+_5a.markRE;}}}};var _60=_54(0);this.evalFunc=_60.func;if(_60.markRE){this.markRegExp=new RegExp(_60.markRE,_45.caseSensitive?"mg":"img");}};abego.BoolExp.prototype.exec=function(){return this.evalFunc.apply(this,arguments);};abego.BoolExp.prototype.getMarkRegExp=function(){return this.markRegExp;};abego.BoolExp.prototype.toString=function(){return this.s;};abego.MultiFieldRegExpTester=function(re,_62,_63){this.re=re;this.fields=_62?_62:["title","text","tags"];this.withExtendedFields=_63;};abego.MultiFieldRegExpTester.prototype.test=function(_64){var re=this.re;for(var i=0;i<this.fields.length;i++){var s=store.getValue(_64,this.fields[i]);if(typeof s=="string"&&re.test(s)){return this.fields[i];}}if(this.withExtendedFields){return store.forEachField(_64,function(_68,_69,_6a){return typeof _6a=="string"&&re.test(_6a)?_69:null;},true);}return null;};abego.TiddlerQuery=function(_6b,_6c,_6d,_6e,_6f){if(_6d){this.regExp=new RegExp(_6b,_6c?"mg":"img");this.tester=new abego.MultiFieldRegExpTester(this.regExp,_6e,_6f);}else{this.expr=new abego.BoolExp(_6b,abego.parseTiddlerFilterTerm,{defaultFields:_6e,caseSensitive:_6c,withExtendedFields:_6f});}this.getQueryText=function(){return _6b;};this.getUseRegExp=function(){return _6d;};this.getCaseSensitive=function(){return _6c;};this.getDefaultFields=function(){return _6e;};this.getWithExtendedFields=function(){return _6f;};};abego.TiddlerQuery.prototype.test=function(_70){if(!_70){return false;}if(this.regExp){return this.tester.test(_70);}return this.expr.exec(_70);};abego.TiddlerQuery.prototype.filter=function(_71){return abego.select(_71,this.test,this);};abego.TiddlerQuery.prototype.getMarkRegExp=function(){if(this.regExp){return "".search(this.regExp)>=0?null:this.regExp;}return this.expr.getMarkRegExp();};abego.TiddlerQuery.prototype.toString=function(){return (this.regExp?this.regExp:this.expr).toString();};abego.PageWiseRenderer=function(){this.firstIndexOnPage=0;};merge(abego.PageWiseRenderer.prototype,{setItems:function(_72){this.items=_72;this.setFirstIndexOnPage(0);},getMaxPagesInNavigation:function(){return 10;},getItemsCount:function(_73){return this.items?this.items.length:0;},getCurrentPageIndex:function(){return Math.floor(this.firstIndexOnPage/this.getItemsPerPage());},getLastPageIndex:function(){return Math.floor((this.getItemsCount()-1)/this.getItemsPerPage());},setFirstIndexOnPage:function(_74){this.firstIndexOnPage=Math.min(Math.max(0,_74),this.getItemsCount()-1);},getFirstIndexOnPage:function(){this.firstIndexOnPage=Math.floor(this.firstIndexOnPage/this.getItemsPerPage())*this.getItemsPerPage();return this.firstIndexOnPage;},getLastIndexOnPage:function(){return Math.min(this.getFirstIndexOnPage()+this.getItemsPerPage()-1,this.getItemsCount()-1);},onPageChanged:function(_75,_76){},renderPage:function(_77){if(_77.beginRendering){_77.beginRendering(this);}try{if(this.getItemsCount()){var _78=this.getLastIndexOnPage();var _79=-1;for(var i=this.getFirstIndexOnPage();i<=_78;i++){_79++;_77.render(this,this.items[i],i,_79);}}}finally{if(_77.endRendering){_77.endRendering(this);}}},addPageNavigation:function(_7b){if(!this.getItemsCount()){return;}var _7c=this;var _7d=function(e){if(!e){var e=window.event;}var _7f=abego.toInt(this.getAttribute("page"),0);var _80=_7c.getCurrentPageIndex();if(_7f==_80){return;}var _81=_7f*_7c.getItemsPerPage();_7c.setFirstIndexOnPage(_81);_7c.onPageChanged(_7f,_80);};var _82;var _83=this.getCurrentPageIndex();var _84=this.getLastPageIndex();if(_83>0){_82=createTiddlyButton(_7b,"Previous","Go to previous page (Shortcut: Alt-'<')",_7d,"prev");_82.setAttribute("page",(_83-1).toString());_82.setAttribute("accessKey","<");}for(var i=-this.getMaxPagesInNavigation();i<this.getMaxPagesInNavigation();i++){var _86=_83+i;if(_86<0){continue;}if(_86>_84){break;}var _87=(i+_83+1).toString();var _88=_86==_83?"currentPage":"otherPage";_82=createTiddlyButton(_7b,_87,"Go to page %0".format([_87]),_7d,_88);_82.setAttribute("page",(_86).toString());}if(_83<_84){_82=createTiddlyButton(_7b,"Next","Go to next page (Shortcut: Alt-'>')",_7d,"next");_82.setAttribute("page",(_83+1).toString());_82.setAttribute("accessKey",">");}}});abego.LimitedTextRenderer=function(){var _89=40;var _8a=4;var _8b=function(_8c,_8d,_8e){var n=_8c.length;if(n==0){_8c.push({start:_8d,end:_8e});return;}var i=0;for(;i<n;i++){var _91=_8c[i];if(_91.start<=_8e&&_8d<=_91.end){var r;var _93=i+1;for(;_93<n;_93++){r=_8c[_93];if(r.start>_8e||_8d>_91.end){break;}}var _94=_8d;var _95=_8e;for(var j=i;j<_93;j++){r=_8c[j];_94=Math.min(_94,r.start);_95=Math.max(_95,r.end);}_8c.splice(i,_93-i,{start:_94,end:_95});return;}if(_91.start>_8e){break;}}_8c.splice(i,0,{start:_8d,end:_8e});};var _97=function(_98){var _99=0;for(var i=0;i<_98.length;i++){var _9b=_98[i];_99+=_9b.end-_9b.start;}return _99;};var _9c=function(c){return (c>="a"&&c<="z")||(c>="A"&&c<="Z")||c=="_";};var _9e=function(s,_a0){if(!_9c(s[_a0])){return null;}for(var i=_a0-1;i>=0&&_9c(s[i]);i--){}var _a2=i+1;var n=s.length;for(i=_a0+1;i<n&&_9c(s[i]);i++){}return {start:_a2,end:i};};var _a4=function(s,_a6,_a7){var _a8;if(_a7){_a8=_9e(s,_a6);}else{if(_a6<=0){return _a6;}_a8=_9e(s,_a6-1);}if(!_a8){return _a6;}if(_a7){if(_a8.start>=_a6-_8a){return _a8.start;}if(_a8.end<=_a6+_8a){return _a8.end;}}else{if(_a8.end<=_a6+_8a){return _a8.end;}if(_a8.start>=_a6-_8a){return _a8.start;}}return _a6;};var _a9=function(s,_ab){var _ac=[];if(_ab){var _ad=0;var n=s.length;var _af=0;do{_ab.lastIndex=_ad;var _b0=_ab.exec(s);if(_b0){if(_ad<_b0.index){var t=s.substring(_ad,_b0.index);_ac.push({text:t});}_ac.push({text:_b0[0],isMatch:true});_ad=_b0.index+_b0[0].length;}else{_ac.push({text:s.substr(_ad)});break;}}while(true);}else{_ac.push({text:s});}return _ac;};var _b2=function(_b3){var _b4=0;for(var i=0;i<_b3.length;i++){if(_b3[i].isMatch){_b4++;}}return _b4;};var _b6=function(s,_b8,_b9,_ba,_bb){var _bc=Math.max(Math.floor(_bb/(_ba+1)),_89);var _bd=Math.max(_bc-(_b9-_b8),0);var _be=Math.min(Math.floor(_b9+_bd/3),s.length);var _bf=Math.max(_be-_bc,0);_bf=_a4(s,_bf,true);_be=_a4(s,_be,false);return {start:_bf,end:_be};};var _c0=function(_c1,s,_c3){var _c4=[];var _c5=_b2(_c1);var pos=0;for(var i=0;i<_c1.length;i++){var t=_c1[i];var _c9=t.text;if(t.isMatch){var _ca=_b6(s,pos,pos+_c9.length,_c5,_c3);_8b(_c4,_ca.start,_ca.end);}pos+=_c9.length;}return _c4;};var _cb=function(s,_cd,_ce){var _cf=_ce-_97(_cd);while(_cf>0){if(_cd.length==0){_8b(_cd,0,_a4(s,_ce,false));return;}else{var _d0=_cd[0];var _d1;var _d2;if(_d0.start==0){_d1=_d0.end;if(_cd.length>1){_d2=_cd[1].start;}else{_8b(_cd,_d1,_a4(s,_d1+_cf,false));return;}}else{_d1=0;_d2=_d0.start;}var _d3=Math.min(_d2,_d1+_cf);_8b(_cd,_d1,_d3);_cf-=(_d3-_d1);}}};var _d4=function(_d5,s,_d7,_d8,_d9){if(_d8.length==0){return;}var _da=function(_db,s,_dd,_de,_df){var t;var _e1;var pos=0;var i=0;var _e4=0;for(;i<_dd.length;i++){t=_dd[i];_e1=t.text;if(_de<pos+_e1.length){_e4=_de-pos;break;}pos+=_e1.length;}var _e5=_df-_de;for(;i<_dd.length&&_e5>0;i++){t=_dd[i];_e1=t.text.substr(_e4);_e4=0;if(_e1.length>_e5){_e1=_e1.substr(0,_e5);}if(t.isMatch){createTiddlyElement(_db,"span",null,"marked",_e1);}else{createTiddlyText(_db,_e1);}_e5-=_e1.length;}if(_df<s.length){abego.createEllipsis(_db);}};if(_d8[0].start>0){abego.createEllipsis(_d5);}var _e6=_d9;for(var i=0;i<_d8.length&&_e6>0;i++){var _e8=_d8[i];var len=Math.min(_e8.end-_e8.start,_e6);_da(_d5,s,_d7,_e8.start,_e8.start+len);_e6-=len;}};this.render=function(_ea,s,_ec,_ed){if(s.length<_ec){_ec=s.length;}var _ee=_a9(s,_ed);var _ef=_c0(_ee,s,_ec);_cb(s,_ef,_ec);_d4(_ea,s,_ee,_ef,_ec);};};(function(){function alertAndThrow(msg){alert(msg);throw msg;}if(version.major<2||(version.major==2&&version.minor<1)){alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.1 or newer.\n\nCheck the archive for YourSearch plugins\nsupporting older versions of TiddlyWiki.\n\nArchive: http://tiddlywiki.abego-software.de/archive");}abego.YourSearch={};var _f1;var _f2;var _f3=function(_f4){_f1=_f4;};var _f5=function(){return _f1?_f1:[];};var _f6=function(){return _f1?_f1.length:0;};var _f7=4;var _f8=10;var _f9=2;var _fa=function(s,re){var m=s.match(re);return m?m.length:0;};var _fe=function(_ff,_100){var _101=_100.getMarkRegExp();if(!_101){return 1;}var _102=_ff.title.match(_101);var _103=_102?_102.length:0;var _104=_fa(_ff.getTags(),_101);var _105=_102?_102.join("").length:0;var _106=_ff.title.length>0?_105/_ff.title.length:0;var rank=_103*_f7+_104*_f9+_106*_f8+1;return rank;};var _108=function(_109,_10a,_10b,_10c,_10d,_10e){_f2=null;var _10f=_109.reverseLookup("tags",_10e,false);try{var _110=[];if(config.options.chkSearchInTitle){_110.push("title");}if(config.options.chkSearchInText){_110.push("text");}if(config.options.chkSearchInTags){_110.push("tags");}_f2=new abego.TiddlerQuery(_10a,_10b,_10c,_110,config.options.chkSearchExtendedFields);}catch(e){return [];}var _111=_f2.filter(_10f);var _112=abego.YourSearch.getRankFunction();for(var i=0;i<_111.length;i++){var _114=_111[i];var rank=_112(_114,_f2);_114.searchRank=rank;}if(!_10d){_10d="title";}var _116=function(a,b){var _119=a.searchRank-b.searchRank;if(_119==0){if(a[_10d]==b[_10d]){return (0);}else{return (a[_10d]<b[_10d])?-1:+1;}}else{return (_119>0)?-1:+1;}};_111.sort(_116);return _111;};var _11a=80;var _11b=50;var _11c=250;var _11d=50;var _11e=25;var _11f=10;var _120="yourSearchResult";var _121="yourSearchResultItems";var _122;var _123;var _124;var _125;var _126;var _127=function(){if(version.extensions.YourSearchPlugin.styleSheetInited){return;}version.extensions.YourSearchPlugin.styleSheetInited=true;setStylesheet(store.getTiddlerText("YourSearchStyleSheet"),"yourSearch");};var _128=function(){return _123!=null&&_123.parentNode==document.body;};var _129=function(){if(_128()){document.body.removeChild(_123);}};var _12a=function(e){_129();var _12c=this.getAttribute("tiddlyLink");if(_12c){var _12d=this.getAttribute("withHilite");var _12e=highlightHack;if(_12d&&_12d=="true"&&_f2){highlightHack=_f2.getMarkRegExp();}story.displayTiddler(this,_12c);highlightHack=_12e;}return (false);};var _12f=function(){if(!_124){return;}var root=_124;var _131=findPosX(root);var _132=findPosY(root);var _133=root.offsetHeight;var _134=_131;var _135=_132+_133;var _136=findWindowWidth();if(_136<_123.offsetWidth){_123.style.width=(_136-100)+"px";_136=findWindowWidth();}var _137=_123.offsetWidth;if(_134+_137>_136){_134=_136-_137-30;}if(_134<0){_134=0;}_123.style.left=_134+"px";_123.style.top=_135+"px";_123.style.display="block";};var _138=function(){if(_123){window.scrollTo(0,ensureVisible(_123));}if(_124){window.scrollTo(0,ensureVisible(_124));}};var _139=function(){_12f();_138();};var _13a;var _13b;var _13c=new abego.PageWiseRenderer();var _13d=function(_13e){this.itemHtml=store.getTiddlerText("YourSearchItemTemplate");if(!this.itemHtml){alertAndThrow("YourSearchItemTemplate not found");}this.place=document.getElementById(_121);if(!this.place){this.place=createTiddlyElement(_13e,"div",_121);}};merge(_13d.prototype,{render:function(_13f,_140,_141,_142){_13a=_142;_13b=_140;var item=createTiddlyElement(this.place,"div",null,"yourSearchItem");item.innerHTML=this.itemHtml;applyHtmlMacros(item,null);refreshElements(item,null);},endRendering:function(_144){_13b=null;}});var _145=function(){if(!_123||!_124){return;}var html=store.getTiddlerText("YourSearchResultTemplate");if(!html){html="<b>Tiddler YourSearchResultTemplate not found</b>";}_123.innerHTML=html;applyHtmlMacros(_123,null);refreshElements(_123,null);var _147=new _13d(_123);_13c.renderPage(_147);_139();};_13c.getItemsPerPage=function(){var n=(config.options.chkPreviewText)?abego.toInt(config.options.txtItemsPerPageWithPreview,_11f):abego.toInt(config.options.txtItemsPerPage,_11e);return (n>0)?n:1;};_13c.onPageChanged=function(){_145();};var _149=function(){if(!_123){_123=createTiddlyElement(document.body,"div",_120,"yourSearchResult");}else{if(_123.parentNode!=document.body){document.body.appendChild(_123);}}_145();};var _14a=function(){if(_124==null||!config.options.chkUseYourSearch){return;}if((_124.value==_122)&&_122&&!_128()){if(_123&&(_123.parentNode!=document.body)){document.body.appendChild(_123);_139();}else{_149();}}};var _14b=function(){_129();_123=null;_122=null;};var _14c=function(self,e){while(e!=null){if(self==e){return true;}e=e.parentNode;}return false;};var _14f=function(e){if(e.target==_124){return;}if(e.target==_125){return;}if(_123&&_14c(_123,e.target)){return;}_129();};var _151=function(e){if(e.keyCode==27){_129();}};addEvent(document,"click",_14f);addEvent(document,"keyup",_151);var _153=function(text,_155,_156){_122=text;_f3(_108(store,text,_155,_156,"title","excludeSearch"));highlightHack=_f2?_f2.getMarkRegExp():null;_13c.setItems(_f5());_149();highlightHack=null;};var _157=function(_158,_159,_15a,_15b,_15c,_15d){_127();_122="";var _15e=null;var _15f=function(txt){if(config.options.chkUseYourSearch){_153(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}else{story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}_122=txt.value;};var _161=function(e){_15f(_124);return false;};var _163=function(e){if(!e){var e=window.event;}_124=this;switch(e.keyCode){case 13:if(e.ctrlKey&&_126&&_128()){_126.onclick.apply(_126,[e]);}else{_15f(this);}break;case 27:if(_128()){_129();}else{this.value="";clearMessage();}break;}if(String.fromCharCode(e.keyCode)==this.accessKey||e.altKey){_14a();}if(this.value.length<3&&_15e){clearTimeout(_15e);}if(this.value.length>2){if(this.value!=_122){if(!config.options.chkUseYourSearch||config.options.chkSearchAsYouType){if(_15e){clearTimeout(_15e);}var txt=this;_15e=setTimeout(function(){_15f(txt);},500);}}else{if(_15e){clearTimeout(_15e);}}}if(this.value.length==0){_129();}};var _166=function(e){this.select();clearMessage();_14a();};var args=_15c.parseParams("list",null,true);var _169=getFlag(args,"buttonAtRight");var _16a=getParam(args,"sizeTextbox",this.sizeTextbox);var btn;if(!_169){btn=createTiddlyButton(_158,this.label,this.prompt,_161);}var txt=createTiddlyElement(_158,"input",null,null,null);if(_15a[0]){txt.value=_15a[0];}txt.onkeyup=_163;txt.onfocus=_166;txt.setAttribute("size",_16a);txt.setAttribute("accessKey",this.accessKey);txt.setAttribute("autocomplete","off");if(config.browser.isSafari){txt.setAttribute("type","search");txt.setAttribute("results","5");}else{txt.setAttribute("type","text");}if(_169){btn=createTiddlyButton(_158,this.label,this.prompt,_161);}_124=txt;_125=btn;};var _16d=function(){_129();var _16e=_f5();var n=_16e.length;if(n){var _170=[];for(var i=0;i<n;i++){_170.push(_16e[i].title);}story.displayTiddlers(null,_170);}};var _172=function(_173,_174,_175,_176){invokeMacro(_173,"option",_174,_175,_176);var elem=_173.lastChild;var _178=elem.onclick;elem.onclick=function(e){var _17a=_178.apply(this,arguments);_145();return _17a;};return elem;};var _17b=function(s){var _17d=["''","{{{","}}}","//","<<<","/***","***/"];var _17e="";for(var i=0;i<_17d.length;i++){if(i!=0){_17e+="|";}_17e+="("+_17d[i].escapeRegExp()+")";}return s.replace(new RegExp(_17e,"mg"),"").trim();};var _180=function(){var i=_13a;return (i>=0&&i<=9)?(i<9?(i+1):0):-1;};var _182=new abego.LimitedTextRenderer();var _183=function(_184,s,_186){_182.render(_184,s,_186,_f2.getMarkRegExp());};var _187=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_188,_189,_18a,_18b,_18c,tags,_18e){_187.apply(this,arguments);_14b();};var _18f=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_190){_18f.apply(this,arguments);_14b();};config.macros.yourSearch={label:"yourSearch",prompt:"Gives access to the current/last YourSearch result",handler:function(_191,_192,_193,_194,_195,_196){if(_193.length==0){return;}var name=_193[0];var func=config.macros.yourSearch.funcs[name];if(func){func(_191,_192,_193,_194,_195,_196);}},tests:{"true":function(){return true;},"false":function(){return false;},"found":function(){return _f6()>0;},"previewText":function(){return config.options.chkPreviewText;}},funcs:{itemRange:function(_199){if(_f6()){var _19a=_13c.getLastIndexOnPage();var s="%0 - %1".format([_13c.getFirstIndexOnPage()+1,_19a+1]);createTiddlyText(_199,s);}},count:function(_19c){createTiddlyText(_19c,_f6().toString());},query:function(_19d){if(_f2){createTiddlyText(_19d,_f2.toString());}},version:function(_19e){var t="YourSearch %0.%1.%2".format([version.extensions.YourSearchPlugin.major,version.extensions.YourSearchPlugin.minor,version.extensions.YourSearchPlugin.revision]);var e=createTiddlyElement(_19e,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#YourSearchPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_1a1){var e=createTiddlyElement(_1a1,"a");e.setAttribute("href","http://www.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2005-2006 <b><font color=\"red\">abego</font></b> Software<font>";},newTiddlerButton:function(_1a3){if(_f2){var r=abego.parseNewTiddlerCommandLine(_f2.getQueryText());var btn=config.macros.newTiddler.createNewTiddlerButton(_1a3,r.title,r.params,"new tiddler","Create a new tiddler based on search text. (Shortcut: Ctrl-Enter; Separators: '.', '#')",null,"text");var _1a6=btn.onclick;btn.onclick=function(){_129();_1a6.apply(this,arguments);};_126=btn;}},linkButton:function(_1a7,_1a8,_1a9,_1aa,_1ab,_1ac){if(_1a9<2){return;}var _1ad=_1a9[1];var text=_1a9<3?_1ad:_1a9[2];var _1af=_1a9<4?text:_1a9[3];var _1b0=_1a9<5?null:_1a9[4];var btn=createTiddlyButton(_1a7,text,_1af,_12a,null,null,_1b0);btn.setAttribute("tiddlyLink",_1ad);},closeButton:function(_1b2,_1b3,_1b4,_1b5,_1b6,_1b7){var _1b8=createTiddlyButton(_1b2,"close","Close the Search Results (Shortcut: ESC)",_129);},openAllButton:function(_1b9,_1ba,_1bb,_1bc,_1bd,_1be){var n=_f6();if(n==0){return;}var _1c0=n==1?"open tiddler":"open all %0 tiddlers".format([n]);var _1c1=createTiddlyButton(_1b9,_1c0,"Open all found tiddlers (Shortcut: Alt-O)",_16d);_1c1.setAttribute("accessKey","O");},naviBar:function(_1c2,_1c3,_1c4,_1c5,_1c6,_1c7){_13c.addPageNavigation(_1c2);},"if":function(_1c8,_1c9,_1ca,_1cb,_1cc,_1cd){if(_1ca.length<2){return;}var _1ce=_1ca[1];var _1cf=(_1ce=="not");if(_1cf){if(_1ca.length<3){return;}_1ce=_1ca[2];}var test=config.macros.yourSearch.tests[_1ce];var _1d1=false;try{if(test){_1d1=test(_1c8,_1c9,_1ca,_1cb,_1cc,_1cd)!=_1cf;}else{_1d1=(!eval(_1ce))==_1cf;}}catch(ex){}if(!_1d1){_1c8.style.display="none";}},chkPreviewText:function(_1d2,_1d3,_1d4,_1d5,_1d6,_1d7){var _1d8=_1d4.slice(1).join(" ");var elem=_172(_1d2,"chkPreviewText",_1d5,_1d7);elem.setAttribute("accessKey","P");elem.title="Show text preview of found tiddlers (Shortcut: Alt-P)";return elem;}}};config.macros.foundTiddler={label:"foundTiddler",prompt:"Provides information on the tiddler currently processed on the YourSearch result page",handler:function(_1da,_1db,_1dc,_1dd,_1de,_1df){var name=_1dc[0];var func=config.macros.foundTiddler.funcs[name];if(func){func(_1da,_1db,_1dc,_1dd,_1de,_1df);}},funcs:{title:function(_1e2,_1e3,_1e4,_1e5,_1e6,_1e7){if(!_13b){return;}var _1e8=_180();var _1e9=_1e8>=0?"Open tiddler (Shortcut: Alt-%0)".format([_1e8.toString()]):"Open tiddler";var btn=createTiddlyButton(_1e2,null,_1e9,_12a,null);btn.setAttribute("tiddlyLink",_13b.title);btn.setAttribute("withHilite","true");_183(btn,_13b.title,_11a);if(_1e8>=0){btn.setAttribute("accessKey",_1e8.toString());}},tags:function(_1eb,_1ec,_1ed,_1ee,_1ef,_1f0){if(!_13b){return;}_183(_1eb,_13b.getTags(),_11b);},text:function(_1f1,_1f2,_1f3,_1f4,_1f5,_1f6){if(!_13b){return;}_183(_1f1,_17b(_13b.text),_11c);},field:function(_1f7,_1f8,_1f9,_1fa,_1fb,_1fc){if(!_13b){return;}var name=_1f9[1];var len=_1f9.length>2?abego.toInt(_1f9[2],_11d):_11d;var v=store.getValue(_13b,name);if(v){_183(_1f7,_17b(v),len);}},number:function(_200,_201,_202,_203,_204,_205){var _206=_180();if(_206>=0){var text="%0)".format([_206.toString()]);createTiddlyElement(_200,"span",null,"shortcutNumber",text);}}}};var opts={chkUseYourSearch:true,chkPreviewText:true,chkSearchAsYouType:true,chkSearchInTitle:true,chkSearchInText:true,chkSearchInTags:true,chkSearchExtendedFields:true,txtItemsPerPage:_11e,txtItemsPerPageWithPreview:_11f};for(var n in opts){if(config.options[n]==undefined){config.options[n]=opts[n];}}config.shadowTiddlers.AdvancedOptions+="\n<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]]) ([[help|YourSearch Help]])// ";config.shadowTiddlers["YourSearch Help"]="!Field Search\nWith the Field Search you can restrict your search to certain fields of a tiddler, e.g"+" only search the tags or only the titles. The general form is //fieldname//'':''//textToSearch// (e."+"g. {{{title:intro}}}). In addition one-character shortcuts are also supported for the standard field"+"s {{{title}}}, {{{text}}} and {{{tags}}}:\n|!What you want|!What you type|!Example|\n|Search ''titles "+"only''|start word with ''!''|{{{!jonny}}} (shortcut for {{{title:jonny}}})|\n|Search ''contents/text "+"only''|start word with ''%''|{{{%football}}} (shortcut for {{{text:football}}})|\n|Search ''tags only"+"''|start word with ''#''|{{{#Plugin}}} (shortcut for {{{tags:Plugin}}})|\n\nUsing this feature you may"+" also search the extended fields (\"Metadata\") introduced with TiddlyWiki 2.1, e.g. use {{{priority:1"+"}}} to find all tiddlers with the priority field set to \"1\".\n\nYou may search a word in more than one"+" field. E.g. {{{!#Plugin}}} (or {{{title:tags:Plugin}}} in the \"long form\") finds tiddlers containin"+"g \"Plugin\" either in the title or in the tags (but does not look for \"Plugin\" in the text). \n\n!Boole"+"an Search\nThe Boolean Search is useful when searching for multiple words.\n|!What you want|!What you "+"type|!Example|\n|''All words'' must exist|List of words|{{{jonny jeremy}}} (or {{{jonny and jeremy}}}"+")|\n|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\n|A word ''must "+"not exist''|Start word with ''-''|{{{-jonny}}} (or {{{not jonny}}})|\n\n''Note:'' When you specify two"+" words, separated with a space, YourSearch finds all tiddlers that contain both words, but not neces"+"sarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need"+" to put the words into quotes. I.e. you type: {{{\"john brown\"}}}.\n\nUsing parenthesis you may change "+"the default \"left to right\" evaluation of the boolean search. E.g. {{{not (jonny or jeremy)}}} finds"+" all tiddlers that contain neither \"jonny\" nor \"jeremy. In contrast to this {{{not jonny or jeremy}}"+"} (i.e. without parenthesis) finds all tiddlers that either don't contain \"jonny\" or that contain \"j"+"eremy\".\n\n!'Exact Word' Search\nBy default a search result all matches that 'contain' the searched tex"+"t. E.g. if you search for {{{Task}}} you will get all tiddlers containing 'Task', but also '~Complet"+"edTask', '~TaskForce' etc.\n\nIf you only want to get the tiddlers that contain 'exactly the word' you"+" need to prefix it with a '='. E.g. typing '=Task' will find the tiddlers that contain the word 'Tas"+"k', ignoring words that just contain 'Task' as a substring.\n\n!~CaseSensitiveSearch and ~RegExpSearch"+"\nThe standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearc"+"h. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\n\nIn addition you m"+"ay do a \"regular expression\" search even with the ''~RegExpSearch'' set to false by directly enterin"+"g the regular expression into the search field, framed with {{{/.../}}}. \n\nExample: {{{/m[ae][iy]er/"+"}}} will find all tiddlers that contain either \"maier\", \"mayer\", \"meier\" or \"meyer\".\n\n!~JavaScript E"+"xpression Filtering\nIf you are familiar with JavaScript programming and know some TiddlyWiki interna"+"ls you may also use JavaScript expression for the search. Just enter a JavaScript boolean expression"+" into the search field, framed with {{{ { ... } }}}. In the code refer to the variable tiddler and e"+"valuate to {{{true}}} when the given tiddler should be included in the result. \n\nExample: {{{ { tidd"+"ler.modified > new Date(\"Jul 4, 2005\")} }}} returns all tiddler modified after July 4th, 2005.\n\n!Com"+"bined Search\nYou are free to combine the various search options. \n\n''Examples''\n|!What you type|!Res"+"ult|\n|{{{!jonny !jeremy -%football}}}|all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its tit"+"les, but no {{{football}}} in content.|\n|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact wor"+"d). Tags named '~CompletedTask', '~TaskForce' etc. are not considered.|\n\n!Access Keys\nYou are encour"+"aged to use the access keys (also called \"shortcut\" keys) for the most frequently used operations. F"+"or quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\n\n|"+"!Key|!Operation|\n|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search in"+"put field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the pr"+"evious search result. This way you can quickly display multiple tiddlers using \"Press {{{Alt-F}}}. S"+"elect tiddler.\" sequences.|\n|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Resul"+"t]] is already closed and the cursor is in the search input field the field's content is cleared so "+"you start a new query.|\n|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second e"+"tc. tiddler from the result list.|\n|{{{Alt-O}}}|Opens all found tiddlers.|\n|{{{Alt-P}}}|Toggles the "+"'Preview Text' mode.|\n|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[Your"+"Search Result]].|\n|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the "+"{{{Return}}} key actually starts the search (as does pressing the 'search' button).|\n\n//If some of t"+"hese shortcuts don't work for you check your browser if you have other extensions installed that alr"+"eady \"use\" these shortcuts.//";config.shadowTiddlers["YourSearch Options"]="|>|!YourSearch Options|\n|>|<<option chkUseYourSearch>> Use 'Your Search'|\n|!|<<option chkPreviewText"+">> Show Text Preview|\n|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required"+" to start search)|\n|!|Default Search Filter:<<option chkSearchInTitle>>Title ('!')     <<option chk"+"SearchInText>>Text ('%')     <<option chkSearchInTags>>Tags ('#')    <<option chkSearchExtendedFiel"+"ds>>Extended Fields<html><br><font size=\"-2\">The fields of a tiddlers that are searched when you don"+"'t explicitly specify a filter in the search text <br>(Explictly specify fields using one or more '!"+"', '%', '#' or 'fieldname:' prefix before the word/text to find).</font></html>|\n|!|Number of items "+"on search result page: <<option txtItemsPerPage>>|\n|!|Number of items on search result page with pre"+"view text: <<option txtItemsPerPageWithPreview>>|\n";config.shadowTiddlers["YourSearchStyleSheet"]="/***\n!~YourSearchResult Stylesheet\n***/\n/*{{{*/\n.yourSearchResult {\n\tposition: absolute;\n\twidth: 800"+"px;\n\n\tpadding: 0.2em;\n\tlist-style: none;\n\tmargin: 0;\n\n\tbackground: #ffd;\n\tborder: 1px solid DarkGra"+"y;\n}\n\n/*}}}*/\n/***\n!!Summary Section\n***/\n/*{{{*/\n.yourSearchResult .summary {\n\tborder-bottom-width:"+" thin;\n\tborder-bottom-style: solid;\n\tborder-bottom-color: #999999;\n\tpadding-bottom: 4px;\n}\n\n.yourSea"+"rchRange, .yourSearchCount, .yourSearchQuery   {\n\tfont-weight: bold;\n}\n\n.yourSearchResult .summary ."+"button {\n\tfont-size: 10px;\n\n\tpadding-left: 0.3em;\n\tpadding-right: 0.3em;\n}\n\n.yourSearchResult .summa"+"ry .chkBoxLabel {\n\tfont-size: 10px;\n\n\tpadding-right: 0.3em;\n}\n\n/*}}}*/\n/***\n!!Items Area\n***/\n/*{{{*"+"/\n.yourSearchResult .marked {\n\tbackground: none;\n\tfont-weight: bold;\n}\n\n.yourSearchItem {\n\tmargin-to"+"p: 2px;\n}\n\n.yourSearchNumber {\n\tcolor: #808080;\n}\n\n\n.yourSearchTags {\n\tcolor: #008000;\n}\n\n.yourSearc"+"hText {\n\tcolor: #808080;\n\tmargin-bottom: 6px;\n}\n\n/*}}}*/\n/***\n!!Footer\n***/\n/*{{{*/\n.yourSearchFoote"+"r {\n\tmargin-top: 8px;\n\tborder-top-width: thin;\n\tborder-top-style: solid;\n\tborder-top-color: #999999;"+"\n}\n\n.yourSearchFooter a:hover{\n\tbackground: none;\n\tcolor: none;\n}\n/*}}}*/\n/***\n!!Navigation Bar\n***/"+"\n/*{{{*/\n.yourSearchNaviBar a {\n\tfont-size: 16px;\n\tmargin-left: 4px;\n\tmargin-right: 4px;\n\tcolor: bla"+"ck;\n\ttext-decoration: underline;\n}\n\n.yourSearchNaviBar a:hover {\n\tbackground-color: none;\n}\n\n.yourSe"+"archNaviBar .prev {\n\tfont-weight: bold;\n\tcolor: blue;\n}\n\n.yourSearchNaviBar .currentPage {\n\tcolor: #"+"FF0000;\n\tfont-weight: bold;\n\ttext-decoration: none;\n}\n\n.yourSearchNaviBar .next {\n\tfont-weight: bold"+";\n\tcolor: blue;\n}\n/*}}}*/\n";config.shadowTiddlers["YourSearchResultTemplate"]="<!--\n{{{\n-->\n<span macro=\"yourSearch if found\">\n<!-- The Summary Header ============================"+"================ -->\n<table class=\"summary\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">"+"<tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Result <span class=\"yourSearchRange\" macro=\"yourSearc"+"h itemRange\"></span>\n\t\t&nbsp;of&nbsp;<span class=\"yourSearchCount\" macro=\"yourSearch count\"></span>\n"+"\t\tfor&nbsp;<span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>\n\t</td>\n\t<td class=\"yourSea"+"rchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch chkPreviewText\"></span><span class=\"chkBoxLabel"+"\">preview text</span>\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch openAllButton\"></span>\n\t\t<span macro=\"yourSearch lin"+"kButton 'YourSearch Options' options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkB"+"utton 'YourSearch Help' help 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch clo"+"seButton\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n\n<!-- The List of Found Tiddlers ================="+"=========================== -->\n<div id=\"yourSearchResultItems\" itemsPerPage=\"25\" itemsPerPageWithPr"+"eview=\"10\"></div>\n\n<!-- The Footer (with the Navigation) ==========================================="+"= -->\n<table class=\"yourSearchFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody"+">\n  <tr>\n\t<td align=\"left\">\n\t\tResult page: <span class=\"yourSearchNaviBar\" macro=\"yourSearch naviBar"+"\"></span>\n\t</td>\n\t<td align=\"right\"><span macro=\"yourSearch version\"></span>, <span macro=\"yourSearc"+"h copyright\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n<!-- end of the 'tiddlers found' case ========="+"================================== -->\n</span>\n\n\n<!-- The \"No tiddlers found\" case ================="+"========================== -->\n<span macro=\"yourSearch if not found\">\n<table class=\"summary\" border="+"\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Resu"+"lt: No tiddlers found for <span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>.\n\t</td>\n\t<t"+"d class=\"yourSearchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Options'"+" options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Help' help"+" 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch closeButton\"></span>\n\t</td>\n  <"+"/tr>\n</tbody></table>\n</span>\n\n\n<!--\n}}}\n-->\n";config.shadowTiddlers["YourSearchItemTemplate"]="<!--\n{{{\n-->\n<span class='yourSearchNumber' macro='foundTiddler number'></span>\n<span class='yourSea"+"rchTitle' macro='foundTiddler title'/></span>&nbsp;-&nbsp;\n<span class='yourSearchTags' macro='found"+"Tiddler field tags 50'/></span>\n<span macro=\"yourSearch if previewText\"><div class='yourSearchText' macro='fo"+"undTiddler field text 250'/></div></span>\n<!--\n}}}\n-->";config.shadowTiddlers["YourSearch"]="<<tiddler [[YourSearch Help]]>>";config.shadowTiddlers["YourSearch Result"]="The popup-like window displaying the result of a YourSearch query.";config.macros.search.handler=_157;var _20a=function(){if(config.macros.search.handler!=_157){alert("Message from YourSearchPlugin:\n\n\nAnother plugin has disabled the 'Your Search' features.\n\n\nYou may "+"disable the other plugin or change the load order of \nthe plugins (by changing the names of the tidd"+"lers)\nto enable the 'Your Search' features.");}};setTimeout(_20a,5000);abego.YourSearch.getStandardRankFunction=function(){return _fe;};abego.YourSearch.getRankFunction=function(){return abego.YourSearch.getStandardRankFunction();};abego.YourSearch.getCurrentTiddler=function(){return _13b;};abego.YourSearch.closeResult=function(){_129();};})();}
//%/