Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

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

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which use a logographic writing system and 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;}

.htmlarea .toolbarHA table {border:1px solid ButtonFace; margin:0em 0em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></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 +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

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

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

----
Also see AdvancedOptions
Happy New Year!  Still working on a bunch of things...  I have a [[Hordes of the Things]] army on my desk and a [[DBR]] army about half completed.  I have quite a backlog of painting to do and I should take photographs of the whole mess and photographs of the old mess...  I'm not sure when I going to do any of that...

Ugh!

Mark
After looking around I found this GTD theme version of TiddlyWiki.  I like the look of this better than the blue default version so this is what I'm going to use...
The day before the day before Christmas!  Have you done your Christmas shopping yet?  I did mine the first week of December and I am very happy I did!  Line-ups into the parking lots, line-ups into the Mall, line-ups at the cash register...  So are we supposed to be in an economic downturn?  I haven't seen much evidence of people "not" spending money...
The count down to the New Year is underway...  Can't say I have huge plans to do much -- see a movie, have a beer...  Gaming-wise I am currently painting a DBR (De Bellis Renationis) Florentine Army (pictures to follow).  Being relatively new to 15mm and not a terribly quick painter I got some help with the cavalry units.  I am now very slowly painting up the Pike and Blade units.
[[15 January 2009]]
[[Hotlead 2009]]
[[29 December 2008]]
[[23 December 2008]]
[[22 December 2008]]
[[Take 2!]]
[[First Go Round]]
Here we go!  This page started about 10 years ago and was all html coded using Notepad and sweat and it wasn't very pretty...  Time for change.  I am going to learn how to use this if it kills me...  Hopefully we'll see some good stuff here!
[[Hotlead 2009 | http://www.hotlead.ca/ ]] will be held on March 27, 28 and 29, 2009!  Mark your calendars now!  Hotlead is Canada's Finest Miniature Gaming Event.  Follow the link for more information!
[[1-64 Farm Toys (Part 3) | http://www.actionfarmtoys.com/64farm3.htm]]
[[1001 Manually selected Fantasy Roleplaying Resources | http://www.cbel.be/fantasy_roleplaying/]]
[[12 sided calendar | http://www.ii.uib.no/~arntzen/kalender/]]
[[1895 Atlas | http://www.livgenmi.com/1895/]]
[[1920's Interactive Literature Resources - Transportation | http://www.vialarp.org/20s/20s_transportation.htm#Aircraft%20and]]
[[2nd Expedition Pics | http://www.geocities.com/faskew/Opra/Expedition2Pics.htm]]
[[3D CAFE'S MODELS (AIRCRAFT) | http://www.3dcafe.com/asp/aircraft.asp]]
[[54mm World War 2 Action Figure Moulds - North Africa and European Campaigns | http://princeaugust.ie/WW2/]]
[[A Glossary of Literary Terms | http://www.virtualsalt.com/litterms.htm]]
[[ASL FAQ Index | http://www.users.bigpond.net.au/mantis/ASLFAQ/FAQ.htm]]
[[Action Figure Comics | http://www.actionfigurecomics.com]]
[[Adventure Street Omnibus | http://free.hostdepartment.com/c/cleireac/Risus/Omnibus/omnibus.html]]
[[Advice for the Evil Overlord | http://nielsenhayden.com/overlord/]]
[[Afrika Corps Uniforms | http://www.diggerhistory.info/pages-uniforms/afrika_korps.htm]]
[[Airborne Equipment | http://www.geocities.com/britsatwar/airborne_equipment.html]]
[[The Zeppelin history and photo website, featuring the Hindenburg, Graf Zeppelin, Akron, Macon, Shenandoah, Los Angele | http://www.airships.net/index.shtml Airships]]
[[Airships and Aerozeppelins | http://www.tlucretius.net/Sophie/Castle/Airships.html]]
[[Airshipsonline Airships Imperial Airship Service | http://www.aht.ndirect.co.uk/airships/imperial/index.html]]
[[Aliens Soundboard | http://www.btinternet.com/~paul.frary/]]
[[AltaVista - Babel Fish Translation - Translated Text | http://babelfish.altavista.com/tr ]]
[[Anonymizer - Anonymous Web Surfing, Anti Spyware, Anonymous Proxy, & Identity Protection | http://www.anonymizer.com/]]
[[Articles on 1-72 Links for small scale figure modellers | http://www.landships.freeservers.com/Links-figures.htm ]]
[[Artizan Designs | http://www.artizandesigns.com/ ]]
[[Austin Powers Soundboard | http://www.theflashgames.com/austinpowers_soundboard-swf.html ]]
[[Avalanche Press | http://www.avalanchepress.com/index.php ]]
[[Back Of Beyond Times | http://www.backofbeyond.de/index.html ]]
[[Battle Rules of Play | http://www.myplus.ca/battlerules.htm ]]
[[Battlefront Miniatures | http://www.battlefront.co.nz/ ]]
[[Battlestar Wiki | http://www.battlestarwiki.org/wiki/Main_Page?title=Main_Page ]]
[[Beecher's Island | http://www.miniaturewars.com/AmericanWest/BeecherIsland.asp ]]
[[Birdrock Downport | http://home.comcast.net/~downport/ ]]
[[BoardGameGeek | http://www.boardgamegeek.com/ ]]
[[BorderWars 2003 | http://www.hahmgs.org/BW2003.html ]]
[[Brief History of WWII Sicily and Italy  | http://www.worldwariihistory.info/WWII/Italy.html ]]
[[British Divisions WW2 | http://battlefieldsww2.50megs.com/british_divisions_ww2.htm ]]
[[British Red Devils in North Africa - World War II | http://www.firebirds.org/menu1/rdbejana.htm ]]
[[Building a Imperial Strongpoint | http://www2.gol.com/users/graham/strongpoint01.html ]]
[[Building the imperial bunker | http://www.rengels.de/warhammer/articles/bunker/index.html ]]
[[CALIVER BOOKS | http://www.caliverbooks.com/ ]]
[[CAPTAIN PROTON | http://www.star-trek-voyager.net/protonindex/proton.htm ]]
[[CBSRMT - CBS Radio Mystery Theater | http://www.cbsrmt.info/charlie/ ]]
[[CBSRMT Website | http://home.twcny.rr.com/myafchak/ ]]
[[Canvas Eagles Page | http://www.generalissue.com/canvas.html ]]
[[Captain Future Timeline | http://www.pjfarmer.com/secret/pulptrek/captain-future-timeline-web.htm ]]
[[Cold Navy at Xtreme Hobby! | http://coldnavy.xtreme-hobby.com/ ]]
[[Colossus Fan Page | http://www.milwaukeerumble.com/colossus/ ]]
[[Comic Art Community GALLERY OF COMIC ART | http://www.comicartcommunity.com/gallery/index.php ]]
[[Commander Keen Maps - Cerebral Cortex 314 | http://www.classicgaming.com/cc314/encyclopedia/maps/maps-k4-lvl14.html ]]
[[Conquest Miniatures - Terrain | http://www.conquestminiatures.com/terrain.htm ]]
[[Copplestone Castings | http://www.copplestonecastings.co.uk/ ]]
[[DEMONGROUND Reflections of a Darker Future | http://www.demonground.org/ ]]
[[DP F1996M HEPTARCHY Britain at war | http://www.diplom.org/Zine/F1996M/Bache/heptarchy.html ]]
[[Dan Becker's The Adventures of Hagbard and Hrothgar | http://www.io.com/~beckerdo/games/articles/HagbardAndHrothgar/ ]]
[[Danvers State Insane Asylum | http://www.danvers-state-ia.com/home.html ]]
[[Dirty 30s! - Hindenburg & Other Airships | http://www.paper-dragon.com/1939/hindenburg.html ]]
[[Dirty 30s! - Introduction | http://www.paper-dragon.com/1939/intro.html ]]
[[Divine Right Online | http://www.divinerightonline.com/foreword.html ]]
[[Dr Hermes Reviews XII | http://community-2.webtv.net/drhermes/RobertEHoward/page6.html ]]
[[Dr. Evil Soundboard | http://www.ebaumsworld.com/drevil.html ]]
[[Draw a Map | http://www.imagineimage.org/gbgen/gbmain.htm ]]
[[Drawing a blank map | http://www.webwargaming.com/maps/blankmap.html ]]
[[Dungeon Generator | http://www.aarg.net/~minam/dungeon.cgi ]]
[[Dungeons Unlimited | http://www.angelfire.com/rpg2/dungeonsunlimited/ ]]
[[Dungeons and Dragons Tools | http://www.dndadventure.com/dnda_dm_resources.html ]]
[[Dust Devils | http://www.chimera.info/dustdevils/index.html ]]
[[E. E. Doc Smith | http://www.cs.utexas.edu/~dastuart/fictiondir/authordir/eesmith/ ]]
[[Battlefields of Albion | http://www.callnetuk.com/home/aself/index.html ]]
[[England - Heptarchy | http://www.stephen.j.murray.btinternet.co.uk/saxkingdoms.htm ]]
[[English Civil War Society | http://english-civil-war-society.org/public_html/index.html ]]
[[eric strawcynski, artiste plasticien, sculptures, masques, robots, accessoires et visages en carton | http://www.ericstraw.com/ ]]
[[Erol Otus | http://www.erolotus.com/ ]]
[[Eternal Egypt | http://www.eternalegypt.org/EternalEgyptWebsiteWeb/HomeServlet ]]
[[Europe, Africa and the Med | http://www.donet.com/~mconrad/etolink.htm ]]
[[Ex Libris Mortis | http://www.dragonrealm.com/exlibrismortis/ExLibrisnew40K_LatinPhrases.html ]]
[[FETCO Toy Soldiers | http://www.fetcotoysoldiers.com/index.html ]]
[[FSG Presents - Starship! | http://www.flagshipgames.com/starship.htm ]]
[[Fantasy Grounds The Virtual Tabletop for Pen & Paper Roleplaying Games | http://www.fantasygrounds.com/home/ ]]
[[Farm Animals & Buildings | http://www.actionfarmtoys.com/farmanimals.htm ]]
[[Foldup Paper Models Compiled Archive | http://www.wizards.com/default.asp?x=dnd/fpm/archive ]]
[[Forbidden Kingdoms Adventure Seed Generator | http://otherworlds.cx/generator.htm ]]
[[Forgotten Realms chronology | http://www.o-love.net/realms/fr_time_notable.html ]]
[[Frankenstein | http://www.jahsonic.com/Frankenstein.html ]]
[[Free Online Graph Paper - Hexagonal PDF Generator | http://www.incompetech.com/beta/hexagonalGraphPaper/hex.html ]]
[[freewargamesrules.co.uk - Where all rules are free! | http://www.freewargamesrules.co.uk/ ]]
[[French Counterattack, Operation Torch | http://www.pcglabs.mun.ca/~timm/torch/ ]]
[[GURPS Russia | http://www.sjgames.com/gurps/books/Russia/ ]]
[[Generators The Brunching Shuttlecocks | http://www.brunching.com/generator-datearchive.html ]]
[[Goodman Games | http://www.goodman-games.com/5012preview.php ]]
[[Google Directory - Games Board Games War and Politics | http://directory.google.com/Top/Games/Board_Games/War_and_Politics/ ]]
[[Gothic Art Gallery | http://home.bresnan.net/~ravensblight5/gothart.html ]]
[[Graf Zeppelin | http://www.ciderpresspottery.com/ZLA/greatzeps/german/GrafZeppelin.html ]]
[[Gripping Beast | http://www.grippingbeast.com/ ]]
[[HAT armorfast miniatures | http://www.hat.com/current99.html ]]
[[HMGS East | http://www.hmgs.org/ ]]
[[Hammer of the Scots | http://www.f2fgaming.com/Tunguska/TunguskaServiceGames/HammeroftheScots/tabid/98/Default.aspx ]]
[[HeroQuest and Hero Quest - New Tiles by Ron Shirtz | http://www.aginsinn.com/tilesRon.html ]]
[[Histoire Et Figurines | http://www.histofig.com/ ]]
[[Historical resources | http://www.dimacleod.co.uk/history/ ]]
[[Homeworld Card Models | http://www.hwcard.cjb.net/ ]]
[[Hot Lead - Canada's finest miniature game convention | http://www.hotlead.ca/ ]]
[[How To Choose A Voice Acting Workshop | http://www.awn.com/mag/issue5.01/5.01pages/schiffvo.php3 ]]
[[How To Use The Gothic Graveyard Mold #46 | http://www.hirstarts.com/grave/grave.html ]]
[[Wehrmacht-Awards | http://www.wehrmacht-awards.net/campaign_awards/cufftitles/afrika_files/award_documents.htm]] 
[[Hyborian Age d20 Campaign | http://hyboria.xoth.net/ ]]
[[HyperWar US Army in WWII American Military History | http://www.ibiblio.org/hyperwar/AMH/AMH/AMH-22.html ]]
[[Hyperiums, THE Massively Multiplayer Strategy Game | http://www.hyperiums.com/#langs ]]
[[Jackson Gamers' Russian Civil War page | http://www.angelfire.com/games3/jacksongamer/reds.htm ]]
[[Knuckleduster Publications | http://www.knuckleduster.com/ ]]
[[Limey Yank Games | http://loakes.dyndsl.com/limeyyankgames/ ]]
[[Links -- Fun Places To Go | http://www.geocities.com/blackhatmatt/links.html ]]
[[Llewellyn's Web Tarot | http://www.llewellyn.com/free/tarot.php ]]
[[Lochagos.com - Wargaming in Antiquity | http://www.lochagos.com/ ]]
[[Long Range Desert Group (LRDG) Links | http://www.lrdg.de/links.htm#real ]]
[[Lossing's Field Book of the War of 1812, Chapter XII - Beginning of the War of 1812 | http://freepages.history.rootsweb.com/~wcarr1/Lossing2/Chap12.html ]]
[[Lost Battalions' WW2 Afrika Korps Uniforms | http://web2.airmail.net/recon36/german/heer/heertrop.html ]]
[[Luft '46 - WWII German aircraft projects | http://www.luft46.com/ ]]
[[MARTIAN TRIPOD | http://home.hetnet.nl/mr_11/173/erwin47/models/tripod/ ]]
[[MSC's Redoubt Enterprises Colonial Wars Catalog! | http://www.miniatureservicecenter.com/msc-redoubt-colonial.htm ]]
[[Major General Tremorden Rederring's Colonial Wargames Page | http://zeitcom.com/majgen/ ]]
[[MapSymbs - APP6 TrueType Fonts | http://www.mapsymbs.com/ ]]
[[Mapping Aids for Roleplayers | http://fitz.jsr.com/roleplay/props/mapping.html ]]
[[Martin Laerkes' Mythos Campaign Rules | http://home.worldonline.dk/nyskes/mythos/Epic.html ]]
[[Mercator's Civilization2 Site - Maps for Civilization II | http://www.civgaming.net/mercator/ ]]
[[Michael's Web Page | http://www.asmrb.org/michaelb/PersonalIndex.html ]]
[[Monster Magazines | http://www.gdarkness.com/monstermags/ ]]
[[Monster Pitch The Brunching Shuttlecocks | http://www.brunching.com/monsterpitch.html ]]
[[Mythos Group Source Rules | http://www.radix.net/~erewhon/rules/mythos_rules.html ]]
[[Names of Cowboys, Indians, Outlaws, Gunfighters, Legends & their Horses, etc... | http://www.lowchensaustralia.com/names/cinames.htm ]]
[[Napnuts Western Skirmish Rules | http://www.napnuts.com/west_gun_rules.htm ]]
[[NewDarkAge.net - Gallery | http://www.newdarkage.net/gallery.html ]]
[[No Quarter Given Pirate Links | http://www.noquartergiven.net/ports.htm ]]
[[Noble Miniatures, home of Hallmark & Perrin Minis | http://www.nobleminis.com/ ]]
[[Nodwick dot com | http://archive.gamespy.com/comics/nodwick/ ]]
[[North Africa | http://www.cs.ndsu.nodak.edu/~lugert/wwii.htm#conclusion ]]
[[Notes on League of Extraordinary Gentlemen #1 | http://www.geocities.com/ratmmjess/league1.html ]]
[[Nuklear Power - Home of 8-bit Theater | http://www.nuklearpower.com/archive.php ]]
[[OLD WEST Americana 1 | http://www.wargamesfoundry.com/collections/OW/index.asp ]]
[[Official Home of Whitewash City The Wild West in PDF | http://www.erichotz.com/whitewash.html ]]
[[Old Time Radio Fan Free Old Time Radio Shows | http://www.otrfan.com/ ]]
[[Old West Links | http://www.circagames.com/Resources/old_west.html ]]
[[old time radio shows in mp3 and real audio - EY's Audio Links | http://users2.ev1.net/~ey/audio.html ]]
[[Online Kingmaker | http://www.onlinekingmaker.co.uk/ ]]
[[Other Mystery Sites | http://www.who-dunnit.com/links/3/on.html ]]
[[PDF Conversion Central | http://www.pdfzone.com/category2/0,1874,1851561,00.asp ]]
[[PSASL Logbook Help | http://www.pindersoft.com/psaslhelp.htm ]]
[[pa3eqb -- Russian Communications Van | http://www.tactical-link.com/pa3eqb.htm ]]
[[paizo.com - Dungeon - Resources - Downloads | http://paizo.com/dungeon/resources/downloads ]]
[[Palm Pilot | http://www.notebooksplus.com/palmpilot.htm ]]
[[Paper Paradise Links | http://www.paperparadise.com/articles/cool_links.cfm ]]
[[Paper Toys - Paper Cut-Outs - Custom Paper Models at PaperToys.com | http://www.papertoys.com/ ]]
[[Paperware | http://www.brumbaer.de/Wm/Build/index.html ]]
[[Peter's guide to map creation How to create fantasy maps | http://www.brodt.dk/peter/maps.html ]]
[[PhilipGlass.com Glass Engine | http://www.philipglass.com/html/pages/glass-engine.html# ]]
[[Plastic Soldier Review - 172 Scale Military Figures | http://www.plasticsoldierreview.com/ ]]
[[Plot-o-matic (tm) movie plot generator | http://www.maddogproductions.com/plotomatic.htm ]]
[[Power Point PBEM | http://www.alanemrich.com/AE-TK_and_DS_pages/Lets_Play/tk-pppbem.htm ]]
[[Pulp 1933 Campaign Resources | http://www.asmrb.org/michaelb/PulpIndex.html ]]
[[Pulp Earth Timeline! | http://www.piscesallmedia.com/golden/pulp_timeline.htm ]]
[[Pulp Figures | http://www.pulpfigures.com/ ]]
[[Pulp Magazine Heroes | http://www.cs.uku.fi/~vaisala/Pulp.htm ]]
[[Pygmy Wars Home Page, wargaming the Russian Civil War 1919 1920, wargames scenarios | http://pygmy-wars.50megs.com/ ]]
[[QuickHex, The hex-paper maker... | http://www.zho.berka.com/goodies/hex/qh.html ]]
[[Quiet, Please Episodes | http://quietplease.org/listepisodes.php ]]
[[RANDOM SCENARIO GENERATOR | http://www.fanatic.dk/WhfbRandonScenario/rsg.asp ]]
[[RATTLESNAKE JACK'S FONT GALLERY | http://www3.memlane.com/gromboug/fontpage.htm ]]
[[REALMSPACE Geonomicon. A Dungeons & Dragons Online Archive | http://www.geonomicon.com/portal/ ]]
[[RMSS vs RMFRP | http://www.icewebring.com/RMSSvsRMFRP/RMSSvsRMFRP_pt07.shtml ]]
[[RPG Library | http://www.rpglibrary.org/main.php?showgenre=Action ]]
[[Radio Memories | http://radiomemories.libsyn.com/ ]]
[[RadioGOLDINdex.com, Old Time Radio Show Database | http://www.radiogoldindex.com/frame1.html ]]
[[RadioLovers.com - All Shows | http://www.radiolovers.com/pages/allshows.html#c ]]
[[Radiophile.com - Wood Radios | http://www.radiophile.com/wood.htm ]]
[[RailServe.com Links Railroad Computer Games & Trains Simulators | http://www.railserve.com/Computers/ ]]
[[Ralf's Homepage | http://www.rengels.de/index.html ]]
[[Rapid Fire! WWII Wargaming Rules | http://www.rapid-fire.uk.com/ ]]
[[Red Shadow | http://www.warflag.com/shadow/index.html ]]
[[Red Star Red Army Chorus and Dance Ensemble (Russia) | http://www.redstarensemble.chat.ru/ ]]
[[Role Playing Games Nethack, Rogue, Unreal World, and many more! | http://www.dosgames.com/g_rpg.php ]]
[[Round the World Flights | http://www.wingnet.org/rtw/rtw001j.htm ]]
[[SECTION31.COM | http://www.section31.com/ ]]
[[Saucy Tales of the Supernatural | http://www.freewebs.com/saucytales/ ]]
[[Scale Creep Miniatures | http://www.scalecreep.com/catalog/index.php?cPath=1013 ]]
[[Star Trek Voyager Season 5 SHIP'S LOGS | http://www.star-trek-voyager.net/a1episodes/season5.htm]]
[[Serena Dawn Spaceport | http://www.serenadawn.com/AlienRPG-Contents.htm ]]
[[Seventh Sanctum | http://www.seventhsanctum.com/ ]]
[[Shadowolf | http://home.iprimus.com.au/shadowolf/Index.htm ]]
[[Ships of the Mauridian Expeditionary Forces | http://coldnavy.xtreme-hobby.com/mauridian/ships.html ]]
[[Shivers #103 Horror Entertainment | http://www.visimag.com/shivers/h103_display.htm ]]
[[Silhouette Animals | http://www.mclink.it/personal/MC4799/pulp/animals/animal_intro.html ]]
[[Snyder's Treasures Zeppelin & Airship Items | http://www.snyderstreasures.com/pages/zeppelin.htm ]]
[[Solar System Synthesis Applet | http://www.geocities.com/Area51/6902/w_accr.html ]]
[[SovInformBureau | http://www.siber.com/sib/ ]]
[[Soviet Army Insignia of Rank-WW2 | http://www2.powercom.net/~rokats/wwiisoviet.html ]]
[[Soviet Organisation | http://www-solar.mcs.st-and.ac.uk/~aaron/WW2ORG/sov.html ]]
[[Space Opera Skill List | http://www.tux.uklinux.net/so/skills.html ]]
[[Specialist Games | http://www.specialist-games.com/ ]]
[[StarGen - Solar System Generator | http://home.comcast.net/~brons/NerdCorner/StarGen/StarGen.html ]]
[[Starfire Assistant | http://www.starfireassistant.com/ ]]
[[Starfire Online | http://www.digigamers.com/starfireonline/products/sma/index.jsp?DISPLAYPAGE=/starfireonline/content/article_20040505_002.jsp ]]
[[Starship Combat News - The latest info on space games and miniatures | http://www.star-ranger.com/Home.htm ]]
[[Streamload | http://www.streamload.com]]
[[Such Pulp As Dreams Are Made On | http://www.eldritchdark.com/misc/such_pulp_as_dreams_are_made_on.html ]]
[[Svalbard Images - Maps and Pictures | http://www.svalbard-images.com/ ]]
[[THE LENSMAN ALT LENSMAN FAQ. (v3.65, 08Jun98) | http://www.outel.org/decomposed/goe/ ]]
[[THE TOWN WITH NO NAME | http://www.mts.net/~gisby/tonymorris.htm ]]
[[Tanzanica, A Mordheim Darkest Africa Variant | http://www.tanzanica.com/ ]]
[[Tengwar - Quenya Language | http://www.geocities.com/TimesSquare/4948/tengwar/quenya.htm ]]
[[The 13th Warrior - Eaters of the Dead | http://www.geocities.com/Hollywood/Guild/1651/index2.html ]]
[[The Ancient Egypt Film Site | http://www.wepwawet.nl/films/default.htm ]]
[[The Art Deco Society of California | http://www.artdecosociety.org/ ]]
[[The Aspen Modeling Company | http://www.theaspenmodelingcompany.com/ ]]
[[The Bulwer-Lytton Fiction Contest | http://www.bulwer-lytton.com/#The%20rules ]]
[[The Commander Keen Web Page | http://www.angelfire.com/hi5/justinj88/ ]]
[[The Daily .WAV | http://www.dailywav.com/ ]]
[[The Dhole's House - Characters - Index | http://www.dholeshouse.co.uk/Characters/Index.asp ]]
[[The English Civil War Society of America Home Page | http://www.ecwsa.org/ ]]
[[The Forgotten Realms Bibliography | http://www.aeolia.net/realms/realms-articles.html ]]
[[The Genre Trap | http://storymind.com/articles/2004-06-03.htm ]]
[[The Holloway Pages Pulp Heroes | http://home.comcast.net/~cjh5801a/Pulp.htm ]]
[[The Italian Wars - WECW Army Lists | http://www.lochagos.com/cnc/italian_wars_spain.html ]]
[[The Lost World Steampunk | http://silentmoviemonsters.tripod.com/TheLostWorld/LWSTEAM.html ]]
[[The Mantis-Eye Experiment - Episode 101 - Dia de los Dangerous! | http://venture.mancubus.net/eps/101.php ]]
[[The Monkey Island SCUMM Bar | http://www.scummbar.com/ ]]
[[The Northern Journey Campaign | http://www.matthew.fenn.dsl.pipex.com/nj/Index.htm ]]
[[The Official Plutonian Shore Website | http://www.laughingsage.com/Fset_photogals.htm ]]
[[The Official Road Map of Ontario | http://www.mto.gov.on.ca/english/traveller/map/ ]]
[[The Official Venture Brothers Website | http://www.venturebros.com/ ]]
[[The Old Corral - Homepage | http://www.surfnetinc.com/chuck/trio.htm ]]
[[the Painted Anvil presents- Terry Dodson | http://www.paintedanvil.com/dodson2.html ]]
[[The Pearl Home Page | http://www.thekeep.org/~wombat/Stories/Pulp/ ]]
[[The Pulp Era Miniatures Showcase | http://wk.frothersunite.com/sc/pulp/Pulpsc.htm ]]
[[The Rules With No Name | http://www.mts.net/~gisby/owbuild.htm ]]
[[The SF Site New and Noteworthy Science Fiction and Fantasy Books | http://www.sfsite.com/vault/worth18.htm ]]
[[The Unbound Book - Resources | http://www.unboundbook.org/resources.htm ]]
[[The Valley of the Pharaohs | http://www.palladium-megaverse.com/cuttingroom/valley/valley.html ]]
[[The War of the Worlds the RPG | http://www.geocities.com/TimesSquare/Galaxy/3773/waroftheworlds/index.html ]]
[[The Weird WWII Miniatures Showcase | http://wk.frothersunite.com/sc/pulp/weirdwar.htm ]]
[[The Wold Newton Universe - Articles, Part V | http://www.pjfarmer.com/woldnewton/Articles5.htm#NEMO ]]
[[The Zhodani Base - Classic Traveller RPG in Foreven Sector, Spinward Marches and other Frontier Regions | http://zho.berka.com/ ]]
[[The approved Star Trek Voyager 5.12 Bride of Chaotica | http://www.flatoutblind.org/chaotica/members.php  ]]
[[Tim Peterson's Terrian Generation System for the American Civil War | http://www.indiawargamers.com/resources/misc/terrain.html ]]
[[Tony LoBue's Flash Gordon Web Site... | http://flashgordon.ws/ ]]
[[Traveling by Airship | http://www.oldbeacon.com/beacon/airships/airship-travel.htm ]]
[[TrekGuide.com =-= Star Trek Episode Guide | http://trekguide.com/ ]]
[[Trucks lend-leased to Russia in WW2 | http://www.o5m6.de/ ]]
[[ULTIMATE SCIENCE FICTION WEB GUIDE | http://www.magicdragon.com/UltimateSF/SF-Index.html ]]
[[Ultimate RuneQuest Resources - Best RuneQuest Resources on the Net! | http://www.runequestrealms.org/index.html ]]
[[Uniforms of die Panzertruppe | http://www.panzerworld.net/uniforms.html ]]
[[Unsolicited, but useful, advice for LARPers | http://www.skaro.com/larpcostlist.html ]]
[[VASL 4.0 User's Guide - Installation | http://www.vasl.org/users_guide/02.htm ]]
[[Vampire Counts - Blood Dragons | http://www.siegetower.com/warhammer/undead.htm ]]
[[Vaults of Pandius - the Official Mystara Homepage | http://pandius.com/index.html ]]
[[Veterans of Boskone Wars | http://www.graylensman.com/ ]]
[[Victoria Regina Tarot | http://www.thefool.com/info/index.asp ]]
[[Victorian Adventure Gaming | http://g.webring.com/hub?ring=vag ]]
[[Virtual Keyboard | http://www.theflashgames.com/virtualkeyboard_game-swf.html ]]
[[Voice Acting 101 | http://www.awn.com/mag/issue2.1/articles/bevilacqua2.1.html ]]
[[WEB-GEEK.COM | http://www.web-geek.com/index.html ]]
[[WSHobby, Toys and Collectibles | http://www.wshobby.com/catalog/catalog/default.php ]]
[[WWII Battle of Kursk Mine-Countermine operations | http://www.geocities.com/armysappersforward/kursk.htm ]]
[[War Times Journal | http://www.wtj.com/index_flash.htm ]]
[[War of 1812 Website- War of 1812 Articles, Books, Reenactment information, Quizes, links.... | http://www.warof1812.ca/charts/regts_na.htm ]]
[[Wargame Central | http://wgc.kenware.com/ ]]
[[wargamedownloads.com | http://www.wargamedownloads.com/?Site=AdWords2 ]]
[[Wargames Foundry Website | http://www.wargamesfoundry.com/watson/index2.asp ]]
[[Wargames Illustrated | http://www.wargamesillustrated.net/ ]]
[[Wargaming World War II - Megablitz - North Africa 1943 - The Race For Tunis | http://www.users.dircon.co.uk/~warden/ww2/Battles/rft.htm ]]
[[Wargaming World War II - Megablitz - Wargames | http://www.users.dircon.co.uk/~warden/ww2/Wargames.htm ]]
[[Wargaming World War One | http://www.geocities.com/terry1813/ ]]
[[Wargaming | http://stromata.tripod.com/id21.htm ]]
[[Warhammer Ahoy! | http://www.spiritofthegame.org.uk/warhammerahoy/ ]]
[[Web-Grognards the site for wargames on the web | http://grognard.com/ ]]
[[Welcome To Mark H. Walker's LOCK 'N LOAD | http://www.locknloadgame.com/ ]]
[[Welcome to Dime Novels | http://www-sul.stanford.edu/depts/dp/pennies/home.html ]]
[[Welcome to HereditaryTitles.com | http://www.hereditarytitles.com/ ]]
[[Welcome to TerraGenesis, No.1 for wargames terrain and model scenery. | http://www.terragenesis.co.uk/ ]]
[[Welcome to The Colonial Angle | http://home.comcast.net/~theangle/index.html ]]
[[Welcome to the Drunk Dwarves | http://www.drunkdwarves.com/ ]]
[[Welcome to the Foundry Website! | http://www.wargamesfoundry.com/main.asp ]]
[[WizKids - Mage Knight | http://www.wizkidsgames.com/mageknight/article.asp?frame=gameresources&cid=37135 ]]
[[Woad Creations News Archives | http://www.woadcreations.nl/newsarchives.php ]]
[[World History HyperHistory | http://www.hyperhistory.com/online_n2/History_n2/a.html ]]
[[World of Sulerin -- 3.5E & 3E monsters, spells, magic items and D&D resources | http://www.sulerin.com/creatures/creatures.asp?op=showletter&letter=p ]]
[[ww2 europe index | http://www.dean.usma.edu/history/web03/atlases/ww2%20europe/ww2%20europe%20war%20index.htm ]]
[[www.ps2pdf.com | http://www.ps2pdf.com/convert/convert.htm ]]
[[Yahoo! Groups | http://groups.yahoo.com/ ]]
[[You And Whose Army | http://www.amazonminiatures.com/youandwhosearmy/rings/ ]]
[[ZEPPELIN | http://spot.colorado.edu/~dziadeck/zeppelin.html ]]
[[Zeppelin | http://www.knowledgerush.com/kr/encyclopedia/Zeppelin ]]
[[15 January 2009]]
[[Hotlead 2009]]
[[29 December 2008]]
[[23 December 2008]]
[[22 December 2008]]
[[Take 2!]]
[[First Go Round]]
[[Might of Arms and DBx]]
[[Pigwars]]
[[Links]]
[[Painting]]



MainMenu
PageTemplate
StyleSheet
DefaultTiddlers
I started playing Might of Arms in 2004 or so...  I don't remember the exact details since it took forever to get a game going.  My buddy Ken and I were like the only 2 gamers living in Orangeville, ON (nobody my age would admit to playing wargames or more typically, the wargamers we did bump into were Warhammer fanatics under the age of 15 and had a tendency to babble)...  Those were the good old days!  Anyway, we did manage to cobble together this massive 2 player game involving a number of 15mm historical miniatures.  Ken's idea was to play a Hyborian scenario (King Conan and allies vs the Black Priest of Set Thoth-Amon and his evil Stygian hordes).  We had a great time and managed to learn the principal feature in Might of Arms: cascading morale effects are bad!  During the game both sides had a flank collapse due to morale issues.  The only reason the Evil Stygian Empire won was due to reinforcements arriving from behind a hill (where they had been stuck for about three-quarters of the game) to bolster a push in the middle...  

In April of 2007 I moved to Belleville, ON.  Before I left I did manage to contact a number of wargaming-types living in the area.  These lads play DBA and DBM and some DBx homebrew Seven Years War rules.  So now I'm learning a new rule set...  

I must admit, I find the DBx family of rules easy to learn but difficult to master, primarily due to issues over interpretation.  However I remain resolute a good sport at the gaming table so losing to a technicality doesn't disturb me (too much...)

I bought a copy of Hordes of the Things because I do enjoy fantasy wargaming (having played Warhammer for a number of years)...

Cheers,

Mark
<div id='header'>
<div id='titleLine'>
<span id='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span id='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='sidebar'>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div><div id="licensePanel">
<a rel="license" href="http://shared.snapgrid.com/gtd_tiddlywiki.html#RevisionHistory" target="_new">GTDTW Version <span macro="version"></span></a>
<a rel="license" href="http://www.tiddlywiki.com" target="_new">
TiddlyWiki is published by Jeremy Ruston at Osmosoft under a BSD open source license</a>
<a rel="license" href="http://snapgrid.com" target="_new">GTD TiddlyWiki is a modification by Nathan Bowers at Snapgrid under the same license terms.</a>
<a rel="license" href="http://davidco.com" target="_new">"Getting Things Done" is &#169; David Allen at Davidco. Davidco has no affiliation with TiddlyWiki or GTD TiddlyWiki.</a></div></div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
[img[warlock4.jpg]]

My Mordheim Reiklander Warband -- at one point I had a hired Wizard, an Ogre (on retainer), four archers (repainted Warhammer elves), a Captain (a Ral Partha Merchant figure modified to suit) and two big beefy guys (not shown) as muscle...

[img[warlock3.jpg]]

Close-up of the Wizard!

[img[reik03.jpg]]

The two big beefy guys (shown here)...

[img[undead01.jpg]]

Some snaps of a Mordheim Undead Warband (again with some Ral Partha figures modified to suit)...

[img[undead02.jpg]]

[img[undead03.jpg]]

[img[undead04.jpg]]
[img[pigwar.gif]]

*[[Pig Wars Roster Sheet | http://www.geocities.com/markgagnon/roster.pdf ]]
*[[Pig Wars! Quantified! | http://www.geocities.com/markgagnon/quantified.pdf ]]
*[[The Tale of Sir Galahad | http://www.geocities.com/markgagnon/galahad.pdf ]]
*[[The Tale of King Arthur and the Knights of Ni | http://www.geocities.com/markgagnon/knightsni.pdf ]]
*[[The Tale of Sir Robin | http://www.geocities.com/markgagnon/robin.pdf ]]
*[[The Tale of Sir Bedevere | http://www.geocities.com/markgagnon/bedevere.pdf ]]
*[[A Fantasy Skirmish Scenario... The Talisman of the Necromancer  | http://www.geocities.com/markgagnon/talisman.pdf]]
New and improved!
[img[mighty2.jpg]]

Mark's Wargaming Wiki (GTD version)
/***
!GTD Style
http://tiddlystyles.com/#theme:GTD

!Generic rules /%==================================================================== %/
***/
/*{{{*/
body {
 background: #464646 url('http://shared.snapgrid.com/images/tiddlywiki/bodygradient.png') repeat-x top fixed;
 color: #000;
 font: .82em/1.25em "Bitstream Vera Sans", Verdana, Helvetica, Arial, sans-serif;
/*"Lucida Sans Unicode", "Lucida Grande","Trebuchet MS", */
}
/*}}}*/
/***
!Header rules /%====================================================================== %/
***/
/*{{{*/
#contentWrapper
{
 margin: 0 auto;
width: 59em;
position: relative;
}

#header
{
 color: #fff;
 padding: 1.5em 1em .6em 0;
}

#siteTitle {

 font-size: 2.3em;
 margin: 0;
}

#siteSubtitle {
 font-size: 1em;
 padding-left: .8em;;
}

#titleLine{
 background: transparent;
 padding: 0;
}

#titleLine a {
 color: #cf6;
}

#titleLine a:hover {
 background: transparent;
}
/*}}}*/
/***
!Sidebar rules /%====================================================================== %/
***/
/*{{{*/
#sidebar{
 left: 0;
width: 18em;
 margin: .9em .9em 0 0;
 color: #000;
 background: transparent;
}
/*}}}*/
/***
!Main menu rules /%=================================================================== %/
***/
/*{{{*/
#mainMenu{
 position: static;
 width: auto;

 background: #600;
 border-right: 3px solid #500;
padding: 0;
 text-align: left;
 font-size: 1em;
}

#mainMenu h1{
 padding: 5px;
 margin: 0;
 font-size: 1em;
 font-weight: bold;
 background: transparent;
 color: #fff;
}

#mainMenu ul{
 padding: 0;
 margin: 0;
 list-style: none;
}

#mainMenu h1 a,
#mainMenu li a,
#mainMenu li a.button{
 display: block;
 padding: 0 5px 0 10px;
border: 0;
 border-bottom: 1px solid #500;
 border-top: 1px solid #900;
margin: 0;
}

#mainMenu a,
#mainMenu a.button{
 height: 22px;
height: 1.83em;
 line-height: 22px;
 color: #fff;
 background: #700;
margin-left: 1em;
}

#mainMenu a:hover,
#mainMenu a.button:hover {
 background: #b00;
 color: #fff;
}
/*}}}*/
/***
!Sidebar options rules /%============================================================ %/
***/
/*{{{*/
#sidebarOptions {
 background: #eeb;
 border-right: 3px solid #bb8;
 color: #B4C675;
 padding: .5em 0;
}

#sidebarOptions a {
 color: #700;
 margin: .2em .8em;
 padding: 0;
 border: 0;
}

#sidebarOptions a:hover, #sidebarOptions a:active {
 color: #fff;
 background: #700;
 border: 0;
}

#sidebarOptions input{
 margin: 2px 10px;
 border: 1px inset #333;
padding: 0;
}

#sidebarOptions .sliderPanel {
 background: #fff;
 color: #000;
 padding: 5px 10px;
 font-size: .9em;
}

#sidebarOptions .sliderPanel a{
 font-weight: normal;
 margin: 0;
}

#sidebarOptions .sliderPanel a:link,#sidebarOptions .sliderPanel a:visited {
 color: #700;
}

#sidebarOptions .sliderPanel a:hover,#sidebarOptions .sliderPanel a:active {
 color: #fff;
 background: #700;
}
/*}}}*/
/***
!Sidebar tabs rules /%===================================================================== %/
***/
/*{{{*/
#sidebarTabs {
 background: transparent;
 border-right: 3px solid #740;
 border-bottom: 3px solid #520;
 border: 0;
 padding: 0;
}

#contentWrapper #sidebarTabs a,
#contentWrapper #displayArea .tabContents a{
 color: #fff;
}

#contentWrapper #sidebarTabs a:hover,
#contentWrapper #displayArea .tabContents a:hover {
 background: #000;
 color: #fff;
}

#contentWrapper #sidebarTabs a:active,
#contentWrapper #displayArea .tabContents a:active{
 color: #000;
}



#contentWrapper .tabSelected {
 background: #960;
}

#contentWrapper .tabUnselected{
 background: #660;
}

#contentWrapper #sidebar .tabset{
 background: #eeb;
 border-right: 3px solid #bb8;
 padding: 0 0 0 .75em;
}

#contentWrapper .tabContents{
font-size: .95em;
background: #960;
border:0;
 border-right: 3px solid #740;
 border-bottom: 3px solid #520;
 padding: .75em;
}

#contentWrapper .tabContents{
 width: auto;
}

#contentWrapper #sidebarTabs .tabContents .tabset,
#contentWrapper .tabContents .tabset{
 border: 0;
 padding: 0;
 background: transparent;
}

#contentWrapper .tabContents .tabSelected,
#contentWrapper .tabContents .tabContents {
 background: #700;
 border: 0;
}

#contentWrapper .tabContents .tabUnselected {
 background: #440;
}

#contentWrapper .tabset a {
 color: #fff;
 padding: .2em .7em;
 margin: 0 .17em 0 0;
 height: 2em;
position: static;
}

#contentWrapper .tabset a:hover {
 background: #000;
 color: #fff;
}

#contentWrapper .tabset a:active {
 color: #000;
}

#contentWrapper .tabContents ul{
 margin: 0;
 padding: 0;
 list-style: none;
}

#contentWrapper .tabContents .tabContents ul{
 color: #eeb;
}

.tabContents ul a,
.tabContents ul .button{
 color: #fff;
 display: block;
 padding: .1em 0 .1em .7em;
 background: transparent;
 border: 0;
}

.tabContents ul a:hover {
 color: #fff;
 background: #000;
}
/*}}}*/
/***
!License panel rules /%==================================================================== %/
***/
/*{{{*/
#licensePanel {
 padding: 0px 1em;
 font-size: .9em;
}

#licensePanel a {
 color: #960;
 display: block;
 margin-top: .9em;
}

#licensePanel a:hover {
 color: #fff;
 background: transparent;
}
/*}}}*/
/***
!Popup rules /%================================================================= %/
***/
/*{{{*/
.popup {
 font-size: .8em;
 padding: 0em;
 background: #333;
 border: 1px solid #000;
}

.popup hr {
 margin: 1px 0 0 0;
 visibility: hidden;
}

.popup li.disabled {
 color: #666;
}

.popup li a,
.popup li a:visited{
 color: #000;
 border: .1em outset #cf6;
 background: #cf6;
}

.popup li a:hover {
border: .1em outset #cf6;
 background: #ef9;
 color: #000;
}
/*}}}*/
/***
!Message area rules /%================================================================= %/
***/
/*{{{*/
#messageArea{
 font-size: .9em;
 padding: .4em;
 background: #FFE72F;
 border-right: .25em solid #da1;
 border-bottom: .25em solid #a80;

position: fixed;
 top: 10px;
 right: 10px;
 color: #000;
}

#contentWrapper #messageArea a{
 color: #00e;
 text-decoration: none;
}

#contentWrapper #messageArea a:hover{
 color: #00e;
 text-decoration: underline;
 background: transparent;
}

#contentWrapper #messageArea .messageToolbar a.button{
 border: 1px solid #da1;
}

#contentWrapper #messageArea .messageToolbar a.button:hover{
 color: #00e;
 text-decoration: none;
 border: 1px solid #000;
 background: #fff;
}



/*}}}*/
/***
!Tiddler display rules /%================================================================== %/
***/
/*{{{*/
#displayArea {
 width: 39.75em;
 margin: 0 0 0 17em;
}

.tiddler {
 margin: 0 0 .9em 0;
 padding: 0 1em;
 border-right: .25em solid #aaa;
 border-bottom: .25em solid #555;
 background: #fff;
}

.title {
 font-size: 1.5em;
 font-weight: bold;
 color: #900;
}

.toolbar {
 font-size: .8em;
 padding: .5em 0;
}

.toolbar .button{
 padding: .1em .3em;
 color: #000;

 border: .1em outset #cf6;
 background: #cf6;
margin: .1em;
}

.toolbar .button:hover {
 background: #ef9;
 color: #000;
}

.toolbar .button:active {
 background: #ff0;
}

/*}}}*/
/***
!Viewer rules /% ------------------------------------------------------------------------------------------ %/
***/
/*{{{*/
.viewer {
 line-height: 1.4em;
 font-size: 1em;
}

.viewer a:link, .viewer a:visited {
 color: #15b;
}

.viewer a:hover {
 color: #fff;
 background: #000;
}

.viewer .button{
 background: transparent;
 border-top: 1px solid #eee;
 border-left: 1px solid #eee;
 border-bottom: 1px solid #000;
 border-right: 1px solid #000;
}

.viewer .button:hover{
 background: #eee;
 color: #000;
}

.viewer .button:active{
 background: #ccc;
 border-bottom: 1px solid #eee;
 border-right: 1px solid #eee;
 border-top: 1px solid #111;
 border-left: 1px solid #111;
}


.viewer blockquote {
 border-left: 3px solid #777;
 margin: .3em;
 padding: .3em;
}

.viewer pre{
 background: #fefefe;
 border: 1px solid #f1f1f1;
}

.viewer pre, .viewer code{
 color: #000;
}

.viewer ul {
 padding-left: 30px;
}

.viewer ol {
 padding-left: 30px;
}
ul{
list-style-type: asquare;
}
ol{ 
 list-style-type: decimal;
}

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

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

.viewer ul, .viewer ol, .viewer p {
 margin: .0;
}

.viewer li {
 margin: .2em 0;
}

h1,h2,h3,h4,h5,h6 {
 color: #000;
 font-weight: bold;
 background: #eee;
 padding: 2px 10px;
 margin: 5px 0;
}

.viewer h1 {font-size: 1.3em;}
.viewer h2 {font-size: 1.2em;}
.viewer h3 {font-size: 1.1em;}
.viewer h4 {font-size: 1em;}
.viewer h5 { font-size: .9em;}
.viewer h6 { font-size: .8em;}

.viewer table {
 border: 2px solid #303030;
 font-size: 11px;
 margin: 10px 0;
}

.viewer th, .viewer thead td{
 color: #000;
 background: #eee;
 border: 1px solid #aaa;
 padding: 0 3px;
}

.viewer td {
 border: 1px solid #aaa;
 padding: 0 3px;
}

.viewer caption {
 padding: 3px;
}

.viewer hr {
 border: none;
 border-top: dotted 1px #777;
 height: 1px;
 color: #777;
 margin: 7px 0;
}

.viewer
{
 margin: .5em 0 0 0;
 padding: .5em 0;
 border-top: 1px solid #ccc;
}

.highlight {
 color: #000;
 background: #ffe72f;
}
/*}}}*/
/***
!Editor rules /% ----------------------------------------------------------------------------------------- %/
***/
/*{{{*/
.editor {
 font-size: .8em;
 color: #402C74;
 padding: .3em 0;
}

.editor input, .editor textarea {
 font: 1.1em/130% "Andale Mono", "Monaco", "Lucida Console", "Courier New", monospace;
 margin: 0;
 border: 1px inset #333;
 padding: 2px 0;
}

.editor textarea {
 height: 42em;
 width: 100%;
}

input:focus, textarea:focus
{
 background: #ffe;
 border: 1px solid #000;
}
.footer
{
 padding: .5em 0;
 margin: .5em 0;
 border-top: 1px solid #ddd;
 color: #555;
 text-align: center; 
}
/*}}}*/
/***
!IE Display hacks /% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%/
***/
/*{{{*/
body{
 _text-align: center;
}

#contentWrapper
{
/* _width: 770px; CSS UNDERSCORE HACK FOR PROPER WIN/IE DISPLAY */
 _text-align: left; /* CSS UNDERSCORE HACK FOR PROPER WIN/IE DISPLAY */ 
}

#messageArea{
 _position: absolute;
}
/*}}}*/
Hello again!  This page started in 1996 when I first signed up for a Geocities account and started working on a webpage to showcase my interests and some of my painting.  My primary goal was to show the work of a small group of gamers living in London, ON.  We had 2 copies of Mighty Empires and we played that game for about a year and a half.  During that time we tweaked the rules and added some of our own.  

Since then my interests have changed and so has this webpage.  I'm not sure where this is going yet but I hope it will be entertaining.

!!A History of this Site!

Initially intended to act as a repository for Mighty Empires house rules, this site has changed as my interests have changed. Mighty Empires copyright is held by Games Workshop and is no longer produced or supported by them. Look for Mighty Empires on e-Bay... In the last 10 years I have dabbled with Mordheim, Warhammer Fantasy Battle, Warhammer 40K, as well as other table top wargames. In 2004 I was introduced to Rapid Fire! and I played that on and off for over the past two years. More recently I have played Pig Wars! a Dark Ages Skirmish game, and Might of Arms, which as a buddy likes to tell me, is a real wargame... 

Recent Changes to this Webpage!

*Updated Index page on 18 December 2008
*Updated Index page on 23 November 2006
*Casualty Marker page on 23 November 2006
*Fatigue Marker page on 23 November 2006
*Hit Marker page on 23 November 2006
*Shaken Marker page on 23 November 2006
*Shaken Marker - Version 2 page on 23 November 2006
*Shaken Markers -- A Version for Mike Manning! page on 23 November 2006
*How to Produce the Markers page on 23 November 2006
*Updated Index page on 22 November 2006
*Added Might of Arms page on 22 November 2006
*Added Pig Wars! page on 22 November 2006
*Added Pig Wars! Scenarios and Roster on 22 November 2006
*Updated Links page on 22 November 2006
*Updated Index page on 27 June 2006
*Updated Rapid Fire! page on 14 June 2005
*Revised the Mordheim Tattler page on 19 April 2005
*Added the Rapid Fire! World War 2 Wargaming page on 19 April 2005
*Revised the Links page on 19 April 2005
*Revised the Heroic Fantasy RPG page on 19 April 2005
*Removed old pages and unused graphics on 19 April 2005

-----------------------------------------------------------------
Mark Gagnon (markgagnon at yahoo.com)
-----------------------------------------------------------------
If you have any comments or suggestions regarding this Web Page feel free to email me!
section of the TiddlyWiki HTML file", MarkupPostBody: "This tiddler is inserted at the end of the
section of the TiddlyWiki HTML file immediately before the script block", OptionsPanel: "This shadow tiddler is used as the contents of the options panel slider in the right-hand sidebar", PageTemplate: "The HTML template in this shadow tiddler determines the overall ~TiddlyWiki layout", PluginManager: "This shadow tiddler provides access to the plugin manager", SideBarOptions: "This shadow tiddler is used as the contents of the option panel in the right-hand sidebar", SideBarTabs: "This shadow tiddler is used as the contents of the tabs panel in the right-hand sidebar", SiteSubtitle: "This shadow tiddler is used as the second part of the page title", SiteTitle: "This shadow tiddler is used as the first part of the page title", SiteUrl: "This shadow tiddler should be set to the full target URL for publication", StyleSheetColours: "This shadow tiddler contains CSS definitions related to the color of page elements", StyleSheet: "This tiddler can contain custom CSS definitions", StyleSheetLayout: "This shadow tiddler contains CSS definitions related to the layout of page elements", StyleSheetLocale: "This shadow tiddler contains CSS definitions related to the translation locale", StyleSheetPrint: "This shadow tiddler contains CSS definitions for printing", TabAll: "This shadow tiddler contains the contents of the 'All' tab in the right-hand sidebar", TabMore: "This shadow tiddler contains the contents of the 'More' tab in the right-hand sidebar", TabMoreMissing: "This shadow tiddler contains the contents of the 'Missing' tab in the right-hand sidebar", TabMoreOrphans: "This shadow tiddler contains the contents of the 'Orphans' tab in the right-hand sidebar", TabMoreShadowed: "This shadow tiddler contains the contents of the 'Shadowed' tab in the right-hand sidebar", TabTags: "This shadow tiddler contains the contents of the 'Tags' tab in the right-hand sidebar", TabTimeline: "This shadow tiddler contains the contents of the 'Timeline' tab in the right-hand sidebar", ViewTemplate: "The HTML template in this shadow tiddler determines how tiddlers look" }); //-- //-- Main //-- var params = null; // Command line parameters var store = null; // TiddlyWiki storage var story = null; // Main story var formatter = null; // Default formatters for the wikifier config.parsers = {}; // Hashmap of alternative parsers for the wikifier var anim = new Animator(); // Animation engine var readOnly = false; // Whether we're in readonly mode var highlightHack = null; // Embarrassing hack department... var hadConfirmExit = false; // Don't warn more than once var safeMode = false; // Disable all plugins and cookies var installedPlugins = []; // Information filled in when plugins are executed var startingUp = false; // Whether we're in the process of starting up var pluginInfo,tiddler; // Used to pass information to plugins in loadPlugins() // Whether to use the JavaSaver applet var useJavaSaver = config.browser.isSafari || config.browser.isOpera; // Starting up function main() { var t9,t8,t7,t6,t5,t4,t3,t2,t1,t0 = new Date(); startingUp = true; window.onbeforeunload = function(e) {if(window.confirmExit) return confirmExit();}; params = getParameters(); if(params) params = params.parseParams("open",null,false); store = new TiddlyWiki(); invokeParamifier(params,"oninit"); story = new Story("tiddlerDisplay","tiddler"); addEvent(document,"click",Popup.onDocumentClick); saveTest(); loadOptionsCookie(); for(var s=0; s 0) return verifyTail(plugin,false,config.messages.pluginVersionError); } return true; } function isPluginEnabled(plugin) { if(plugin.tiddler.isTagged("systemConfigDisable")) return verifyTail(plugin,false,config.messages.pluginDisabled); return true; } function verifyTail(plugin,result,message) { plugin.log.push(message); return result; } function invokeMacro(place,macro,params,wikifier,tiddler) { try { var m = config.macros[macro]; if(m && m.handler) m.handler(place,macro,params.readMacroParams(),wikifier,params,tiddler); else createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,config.messages.missingMacro])); } catch(ex) { createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,ex.toString()])); } } //-- //-- Paramifiers //-- function getParameters() { var p = null; if(window.location.hash) { p = decodeURI(window.location.hash.substr(1)); if(config.browser.firefoxDate != null && config.browser.firefoxDate[1] < "20051111") p = convertUTF8ToUnicode(p); } return p; } function invokeParamifier(params,handler) { if(!params || params.length == undefined || params.length <= 1) return; for(var t=1; t") { // Colspan colSpanCount++; w.nextMatch = this.cellRegExp.lastIndex-1; } else if(cellMatch[2]) { // End of row if(prevCell && colSpanCount > 1) { prevCell.setAttribute("colspan",colSpanCount); prevCell.setAttribute("colSpan",colSpanCount); // Needed for IE } w.nextMatch = this.cellRegExp.lastIndex; break; } else { // Cell w.nextMatch++; var styles = config.formatterHelpers.inlineCssHelper(w); var spaceLeft = false; var chr = w.source.substr(w.nextMatch,1); while(chr == " ") { spaceLeft = true; w.nextMatch++; chr = w.source.substr(w.nextMatch,1); } var cell; if(chr == "!") { cell = createTiddlyElement(e,"th"); w.nextMatch++; } else { cell = createTiddlyElement(e,"td"); } prevCell = cell; prevColumns[col] = {rowSpanCount:1,element:cell}; if(colSpanCount > 1) { cell.setAttribute("colspan",colSpanCount); cell.setAttribute("colSpan",colSpanCount); // Needed for IE colSpanCount = 1; } config.formatterHelpers.applyCssHelper(cell,styles); w.subWikifyTerm(cell,this.cellTermRegExp); if(w.matchText.substr(w.matchText.length-2,1) == " ") // spaceRight cell.align = spaceLeft ? "center" : "left"; else if(spaceLeft) cell.align = "right"; w.nextMatch--; } col++; this.cellRegExp.lastIndex = w.nextMatch; cellMatch = this.cellRegExp.exec(w.source); } } }, { name: "heading", match: "^!{1,6}", termRegExp: /(\n)/mg, handler: function(w) { w.subWikifyTerm(createTiddlyElement(w.output,"h" + w.matchLength),this.termRegExp); } }, { name: "list", match: "^(?:[\\*#;:]+)", lookaheadRegExp: /^(?:(?:(\*)|(#)|(;)|(:))+)/mg, termRegExp: /(\n)/mg, handler: function(w) { var stack = [w.output]; var currLevel = 0, currType = null; var listLevel, listType, itemType; w.nextMatch = w.matchStart; this.lookaheadRegExp.lastIndex = w.nextMatch; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) { if(lookaheadMatch[1]) { listType = "ul"; itemType = "li"; } else if(lookaheadMatch[2]) { listType = "ol"; itemType = "li"; } else if(lookaheadMatch[3]) { listType = "dl"; itemType = "dt"; } else if(lookaheadMatch[4]) { listType = "dl"; itemType = "dd"; } listLevel = lookaheadMatch[0].length; w.nextMatch += lookaheadMatch[0].length; var t; if(listLevel > currLevel) { for(t=currLevel; tlistLevel; t--) stack.pop(); } else if(listLevel == currLevel && listType != currType) { stack.pop(); stack.push(createTiddlyElement(stack[stack.length-1].lastChild,listType)); } currLevel = listLevel; currType = listType; var e = createTiddlyElement(stack[stack.length-1],itemType); w.subWikifyTerm(e,this.termRegExp); this.lookaheadRegExp.lastIndex = w.nextMatch; lookaheadMatch = this.lookaheadRegExp.exec(w.source); } } }, { name: "quoteByBlock", match: "^<<<\\n", termRegExp: /(^<<<(\n|$))/mg, element: "blockquote", handler: config.formatterHelpers.createElementAndWikify }, { name: "quoteByLine", match: "^>+", lookaheadRegExp: /^>+/mg, termRegExp: /(\n)/mg, element: "blockquote", handler: function(w) { var stack = [w.output]; var currLevel = 0; var newLevel = w.matchLength; var t; do { if(newLevel > currLevel) { for(t=currLevel; tnewLevel; t--) stack.pop(); } currLevel = newLevel; w.subWikifyTerm(stack[stack.length-1],this.termRegExp); createTiddlyElement(stack[stack.length-1],"br"); this.lookaheadRegExp.lastIndex = w.nextMatch; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch; if(matched) { newLevel = lookaheadMatch[0].length; w.nextMatch += lookaheadMatch[0].length; } } while(matched); } }, { name: "rule", match: "^----+$\\n?", handler: function(w) { createTiddlyElement(w.output,"hr"); } }, { name: "monospacedByLine", match: "^\\{\\{\\{\\n", lookaheadRegExp: /^\{\{\{\n((?:^[^\n]*\n)+?)(^\}\}\}$\n?)/mg, element: "pre", handler: config.formatterHelpers.enclosedTextHelper }, { name: "monospacedByLineForCSS", match: "^/\\*\\{\\{\\{\\*/\\n", lookaheadRegExp: /\/\*\{\{\{\*\/\n*((?:^[^\n]*\n)+?)(\n*^\/\*\}\}\}\*\/$\n?)/mg, element: "pre", handler: config.formatterHelpers.enclosedTextHelper }, { name: "monospacedByLineForPlugin", match: "^//\\{\\{\\{\\n", lookaheadRegExp: /^\/\/\{\{\{\n\n*((?:^[^\n]*\n)+?)(\n*^\/\/\}\}\}$\n?)/mg, element: "pre", handler: config.formatterHelpers.enclosedTextHelper }, { name: "monospacedByLineForTemplate", match: "^\\n", lookaheadRegExp: /\n*((?:^[^\n]*\n)+?)(\n*^$\n?)/mg, element: "pre", handler: config.formatterHelpers.enclosedTextHelper }, { name: "wikifyCommentForPlugin", match: "^/\\*\\*\\*\\n", termRegExp: /(^\*\*\*\/\n)/mg, handler: function(w) { w.subWikifyTerm(w.output,this.termRegExp); } }, { name: "wikifyCommentForTemplate", match: "^\n)/mg, handler: function(w) { w.subWikifyTerm(w.output,this.termRegExp); } }, { name: "macro", 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 && lookaheadMatch[1]) { w.nextMatch = this.lookaheadRegExp.lastIndex; invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler); } } }, { name: "prettyLink", match: "\\[\\[", lookaheadRegExp: /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { var e; var text = lookaheadMatch[1]; if(lookaheadMatch[3]) { // Pretty bracketted link var link = lookaheadMatch[3]; e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link)) ? createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler); } else { // Simple bracketted link e = createTiddlyLink(w.output,text,false,null,w.isStatic,w.tiddler); } createTiddlyText(e,text); w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "unWikiLink", match: config.textPrimitives.unWikiLink+config.textPrimitives.wikiLink, handler: function(w) { w.outputText(w.output,w.matchStart+1,w.nextMatch); } }, { name: "wikiLink", match: config.textPrimitives.wikiLink, handler: function(w) { if(w.matchStart > 0) { var preRegExp = new RegExp(config.textPrimitives.anyLetterStrict,"mg"); preRegExp.lastIndex = w.matchStart-1; var preMatch = preRegExp.exec(w.source); if(preMatch.index == w.matchStart-1) { w.outputText(w.output,w.matchStart,w.nextMatch); return; } } if(w.autoLinkWikiWords == true || store.isShadowTiddler(w.matchText)) { var link = createTiddlyLink(w.output,w.matchText,false,null,w.isStatic,w.tiddler); w.outputText(link,w.matchStart,w.nextMatch); } else { w.outputText(w.output,w.matchStart,w.nextMatch); } } }, { name: "urlLink", match: config.textPrimitives.urlPattern, handler: function(w) { w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch); } }, { name: "image", match: "\\[[<>]?[Ii][Mm][Gg]\\[", lookaheadRegExp: /\[([<]?)(>?)[Ii][Mm][Gg]\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { var e = w.output; if(lookaheadMatch[5]) { var link = lookaheadMatch[5]; e = config.formatterHelpers.isExternalLink(link) ? createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler); addClass(e,"imageLink"); } var img = createTiddlyElement(e,"img"); if(lookaheadMatch[1]) img.align = "left"; else if(lookaheadMatch[2]) img.align = "right"; if(lookaheadMatch[3]) img.title = lookaheadMatch[3]; img.src = lookaheadMatch[4]; w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "html", match: "<[Hh][Tt][Mm][Ll]>", lookaheadRegExp: /<[Hh][Tt][Mm][Ll]>((?:.|\n)*?)<\/[Hh][Tt][Mm][Ll]>/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { createTiddlyElement(w.output,"span").innerHTML = lookaheadMatch[1]; w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "commentByBlock", match: "/%", lookaheadRegExp: /\/%((?:.|\n)*?)%\//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; } }, { name: "boldByChar", match: "''", termRegExp: /('')/mg, element: "strong", handler: config.formatterHelpers.createElementAndWikify }, { name: "italicByChar", match: "//", termRegExp: /(\/\/)/mg, element: "em", handler: config.formatterHelpers.createElementAndWikify }, { name: "underlineByChar", match: "__", termRegExp: /(__)/mg, element: "u", handler: config.formatterHelpers.createElementAndWikify }, { name: "strikeByChar", match: "--(?!\\s|$)", termRegExp: /((?!\s)--|(?=\n\n))/mg, element: "strike", handler: config.formatterHelpers.createElementAndWikify }, { name: "superscriptByChar", match: "\\^\\^", termRegExp: /(\^\^)/mg, element: "sup", handler: config.formatterHelpers.createElementAndWikify }, { name: "subscriptByChar", match: "~~", termRegExp: /(~~)/mg, element: "sub", handler: config.formatterHelpers.createElementAndWikify }, { name: "monospacedByChar", match: "\\{\\{\\{", lookaheadRegExp: /\{\{\{((?:.|\n)*?)\}\}\}/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { createTiddlyElement(w.output,"code",null,null,lookaheadMatch[1]); w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "styleByChar", match: "@@", termRegExp: /(@@)/mg, handler: function(w) { var e = createTiddlyElement(w.output,"span"); var styles = config.formatterHelpers.inlineCssHelper(w); if(styles.length == 0) e.className = "marked"; else config.formatterHelpers.applyCssHelper(e,styles); w.subWikifyTerm(e,this.termRegExp); } }, { name: "lineBreak", match: "\\n|
", handler: function(w) { createTiddlyElement(w.output,"br"); } }, { name: "rawText", match: "\\\"{3}|", lookaheadRegExp: /(?:\"{3}|)((?:.|\n)*?)(?:\"{3}|<\/nowiki>)/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { createTiddlyElement(w.output,"span",null,null,lookaheadMatch[1]); w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "mdash", match: "--", handler: function(w) { createTiddlyElement(w.output,"span").innerHTML = "—"; } }, { name: "htmlEntitiesEncoding", match: "(?:(?:&#?[a-zA-Z0-9]{2,8};|.)(?:&#?(?:x0*(?:3[0-6][0-9a-fA-F]|1D[c-fC-F][0-9a-fA-F]|20[d-fD-F][0-9a-fA-F]|FE2[0-9a-fA-F])|0*(?:76[89]|7[7-9][0-9]|8[0-7][0-9]|761[6-9]|76[2-7][0-9]|84[0-3][0-9]|844[0-7]|6505[6-9]|6506[0-9]|6507[0-1]));)+|&#?[a-zA-Z0-9]{2,8};)", handler: function(w) { createTiddlyElement(w.output,"span").innerHTML = w.matchText; } }, { name: "customClasses", match: "\\{\\{", termRegExp: /(\}\}\})/mg, lookaheadRegExp: /\{\{[\s]*([\w]+[\s\w]*)[\s]*\{(\n?)/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch) { var e = createTiddlyElement(w.output,lookaheadMatch[2] == "\n" ? "div" : "span",null,lookaheadMatch[1]); w.nextMatch = this.lookaheadRegExp.lastIndex; w.subWikifyTerm(e,this.termRegExp); } } } ]; //-- //-- Wikifier //-- function getParser(tiddler,format) { if(tiddler) { if(!format) format = tiddler.fields["wikiformat"]; if(format) { for(var i in config.parsers) { if(format == config.parsers[i].format) return config.parsers[i]; } } else { for(var i in config.parsers) { if(tiddler.isTagged(config.parsers[i].formatTag)) return config.parsers[i]; } } } return formatter; } function wikify(source,output,highlightRegExp,tiddler) { if(source && source != "") { var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler); wikifier.subWikifyUnterm(output); } } function wikifyStatic(source,highlightRegExp,tiddler,format) { var e = createTiddlyElement(document.body,"div"); e.style.display = "none"; var html = ""; if(source && source != "") { var wikifier = new Wikifier(source,getParser(tiddler,format),highlightRegExp,tiddler); wikifier.isStatic = true; wikifier.subWikifyUnterm(e); html = e.innerHTML; removeNode(e); } return html; } function wikifyPlain(title,theStore,limit) { if(!theStore) theStore = store; if(theStore.tiddlerExists(title) || theStore.isShadowTiddler(title)) { return wikifyPlainText(theStore.getTiddlerText(title),limit,tiddler); } else { return ""; } } function wikifyPlainText(text,limit,tiddler) { if(limit > 0) text = text.substr(0,limit); var wikifier = new Wikifier(text,formatter,null,tiddler); return wikifier.wikifyPlain(); } function highlightify(source,output,highlightRegExp,tiddler) { if(source && source != "") { var wikifier = new Wikifier(source,formatter,highlightRegExp,tiddler); wikifier.outputText(output,0,source.length); } } function Wikifier(source,formatter,highlightRegExp,tiddler) { this.source = source; this.output = null; this.formatter = formatter; this.nextMatch = 0; this.autoLinkWikiWords = tiddler && tiddler.autoLinkWikiWords() == false ? false : true; this.highlightRegExp = highlightRegExp; this.highlightMatch = null; this.isStatic = false; if(highlightRegExp) { highlightRegExp.lastIndex = 0; this.highlightMatch = highlightRegExp.exec(source); } this.tiddler = tiddler; } Wikifier.prototype.wikifyPlain = function() { var e = createTiddlyElement(document.body,"div"); this.subWikify(e); var text = getPlainText(e); removeNode(e); return text; }; Wikifier.prototype.subWikify = function(output,terminator) { if(terminator) this.subWikifyTerm(output,new RegExp("(" + terminator + ")","mg")); else this.subWikifyUnterm(output); }; Wikifier.prototype.subWikifyUnterm = function(output) { // subWikify() can be indirectly recursive, so we need to save the old output pointer var oldOutput = this.output; this.output = output; this.formatter.formatterRegExp.lastIndex = this.nextMatch; var formatterMatch = this.formatter.formatterRegExp.exec(this.source); while(formatterMatch) { // Output any text before the match if(formatterMatch.index > this.nextMatch) this.outputText(this.output,this.nextMatch,formatterMatch.index); // Set the match parameters for the handler this.matchStart = formatterMatch.index; this.matchLength = formatterMatch[0].length; this.matchText = formatterMatch[0]; this.nextMatch = this.formatter.formatterRegExp.lastIndex; for(var t=1; t this.nextMatch) this.outputText(this.output,this.nextMatch,terminatorMatch.index); this.matchText = terminatorMatch[1]; this.matchLength = terminatorMatch[1].length; this.matchStart = terminatorMatch.index; this.nextMatch = this.matchStart + this.matchLength; this.output = oldOutput; return; } if(formatterMatch.index > this.nextMatch) this.outputText(this.output,this.nextMatch,formatterMatch.index); this.matchStart = formatterMatch.index; this.matchLength = formatterMatch[0].length; this.matchText = formatterMatch[0]; this.nextMatch = this.formatter.formatterRegExp.lastIndex; for(var t=1; t startPos) && (this.highlightMatch.index < endPos) && (startPos < endPos)) { if(this.highlightMatch.index > startPos) { createTiddlyText(place,this.source.substring(startPos,this.highlightMatch.index)); startPos = this.highlightMatch.index; } var highlightEnd = Math.min(this.highlightRegExp.lastIndex,endPos); var theHighlight = createTiddlyElement(place,"span",null,"highlight",this.source.substring(startPos,highlightEnd)); startPos = highlightEnd; if(startPos >= this.highlightRegExp.lastIndex) this.highlightMatch = this.highlightRegExp.exec(this.source); } if(startPos < endPos) { createTiddlyText(place,this.source.substring(startPos,endPos)); } }; //-- //-- Macro definitions //-- config.macros.today.handler = function(place,macroName,params) { var now = new Date(); var text; if(params[0]) text = now.formatString(params[0].trim()); else text = now.toLocaleString(); createTiddlyElement(place,"span",null,null,text); }; config.macros.version.handler = function(place) { createTiddlyElement(place,"span",null,null,version.major + "." + version.minor + "." + version.revision + (version.beta ? " (beta " + version.beta + ")" : "")); }; config.macros.list.handler = function(place,macroName,params) { var type = params[0] ? params[0] : "all"; var list = document.createElement("ul"); place.appendChild(list); if(this[type].prompt) createTiddlyElement(list,"li",null,"listTitle",this[type].prompt); var results; if(this[type].handler) results = this[type].handler(params); for(var t = 0; t < results.length; t++) { var li = document.createElement("li"); list.appendChild(li); createTiddlyLink(li,typeof results[t] == "string" ? results[t] : results[t].title,true); } }; config.macros.list.all.handler = function(params) { return store.reverseLookup("tags","excludeLists",false,"title"); }; config.macros.list.missing.handler = function(params) { return store.getMissingLinks(); }; config.macros.list.orphans.handler = function(params) { return store.getOrphans(); }; config.macros.list.shadowed.handler = function(params) { return store.getShadowed(); }; config.macros.list.touched.handler = function(params) { return store.getTouched(); }; config.macros.allTags.handler = function(place,macroName,params) { var tags = store.getTags(params[0]); var ul = createTiddlyElement(place,"ul"); if(tags.length == 0) createTiddlyElement(ul,"li",null,"listTitle",this.noTags); for(var t=0; t=last; t--) { var tiddler = tiddlers[t]; var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8); if(theDay != lastDay) { var theDateList = document.createElement("ul"); place.appendChild(theDateList); createTiddlyElement(theDateList,"li",null,"listTitle",tiddler[field].formatString(this.dateFormat)); lastDay = theDay; } var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink"); theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true)); } }; config.macros.search.handler = function(place,macroName,params) { var searchTimeout = null; var btn = createTiddlyButton(place,this.label,this.prompt,this.onClick); var txt = createTiddlyElement(place,"input",null,"txtOptionInput"); if(params[0]) txt.value = params[0]; txt.onkeyup = this.onKeyPress; txt.onfocus = this.onFocus; txt.setAttribute("size",this.sizeTextbox); txt.setAttribute("accessKey",this.accessKey); txt.setAttribute("autocomplete","off"); txt.setAttribute("lastSearchText",""); if(config.browser.isSafari) { txt.setAttribute("type","search"); txt.setAttribute("results","5"); } else { txt.setAttribute("type","text"); } }; // Global because there's only ever one outstanding incremental search timer config.macros.search.timeout = null; config.macros.search.doSearch = function(txt) { if(txt.value.length > 0) { story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch); txt.setAttribute("lastSearchText",txt.value); } }; config.macros.search.onClick = function(e) { config.macros.search.doSearch(this.nextSibling); return false; }; config.macros.search.onKeyPress = function(e) { if(!e) var e = window.event; switch(e.keyCode) { case 13: // Ctrl-Enter case 10: // Ctrl-Enter on IE PC config.macros.search.doSearch(this); break; case 27: // Escape this.value = ""; clearMessage(); break; } if(this.value.length > 2) { if(this.value != this.getAttribute("lastSearchText")) { if(config.macros.search.timeout) clearTimeout(config.macros.search.timeout); var txt = this; config.macros.search.timeout = setTimeout(function() {config.macros.search.doSearch(txt);},500); } } else { if(config.macros.search.timeout) clearTimeout(config.macros.search.timeout); } }; config.macros.search.onFocus = function(e) { this.select(); }; config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) { params = paramString.parseParams("name",null,true,false,true); var names = params[0]["name"]; var tiddlerName = names[0]; var className = names[1] ? names[1] : null; var args = params[0]["with"]; var wrapper = createTiddlyElement(place,"span",null,className); if(!args) { wrapper.setAttribute("refresh","content"); wrapper.setAttribute("tiddler",tiddlerName); } var text = store.getTiddlerText(tiddlerName); if(text) { var stack = config.macros.tiddler.tiddlerStack; if(stack.indexOf(tiddlerName) !== -1) return; stack.push(tiddlerName); try { var n = args ? Math.min(args.length,9) : 0; for(var i=0; i 0) btn.setAttribute("params",tags.join("|")); btn.setAttribute("newFocus",newFocus); btn.setAttribute("newTemplate",getParam(params,"template",DEFAULT_EDIT_TEMPLATE)); if(customFields !== "") btn.setAttribute("customFields",customFields); var text = getParam(params,"text"); if(text !== undefined) btn.setAttribute("newText",text); return btn; }; config.macros.newTiddler.onClickNewTiddler = function() { var title = this.getAttribute("newTitle"); if(this.getAttribute("isJournal") == "true") { var now = new Date(); title = now.formatString(title.trim()); } var params = this.getAttribute("params"); var tags = params ? params.split("|") : []; var focus = this.getAttribute("newFocus"); var template = this.getAttribute("newTemplate"); var customFields = this.getAttribute("customFields"); story.displayTiddler(null,title,template,false,null,null); var tiddlerElem = document.getElementById(story.idPrefix + title); if(customFields) story.addCustomFields(tiddlerElem,customFields); var text = this.getAttribute("newText"); if(typeof text == "string") story.getTiddlerField(title,"text").value = text.format([title]); for(var t=0;t max) max = v; data.push(v); } if(data.length < 1) return; var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160)); box.title = data.join(","); var w = box.offsetWidth; var h = box.offsetHeight; box.style.paddingRight = (data.length * 2 - w) + "px"; box.style.position = "relative"; for(var d=0; d> config.macros.gradient.handler = function(place,macroName,params,wikifier) { var terminator = ">>"; var panel; if(wikifier) panel = createTiddlyElement(place,"div",null,"gradient"); else panel = place; panel.style.position = "relative"; panel.style.overflow = "hidden"; panel.style.zIndex = "0"; var t; if(wikifier) { var styles = config.formatterHelpers.inlineCssHelper(wikifier); config.formatterHelpers.applyCssHelper(panel,styles); } var colours = []; for(t=1; t rows) rows = lines.length + 5; rows = Math.min(rows,maxLines); e.setAttribute("rows",rows); e.setAttribute("edit",field); place.appendChild(wrapper1); } } }; config.macros.tagChooser.onClick = function(e) { if(!e) var e = window.event; var lingo = config.views.editor.tagChooser; var popup = Popup.create(this); var tags = store.getTags(); if(tags.length == 0) createTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone); for(var t=0; t': var btn = createTiddlyButton(place,this.moreLabel,this.morePrompt,config.macros.toolbar.onClickMore); addClass(btn,"moreCommand"); var e = createTiddlyElement(place,"span",null,"moreCommand"); e.style.display = "none"; place = e; break; default: var theClass = ""; switch(c.substr(0,1)) { case "+": theClass = "defaultCommand"; c = c.substr(1); break; case "-": theClass = "cancelCommand"; c = c.substr(1); break; } if(c in config.commands) this.createCommand(place,c,tiddler,theClass); break; } } }; config.macros.refreshDisplay.handler = function(place) { createTiddlyButton(place,this.label,this.prompt,this.onClick); }; config.macros.refreshDisplay.onClick = function(e) { refreshAll(); return false; }; config.macros.annotations.handler = function(place,macroName,params,wikifier,paramString,tiddler) { var title = tiddler ? tiddler.title : null; var a = title ? config.annotations[title] : null; if(!tiddler || !title || !a) return; var text = a.format([title]); wikify(text,createTiddlyElement(place,"div",null,"annotation"),null,tiddler); }; //-- //-- Menu and toolbar commands //-- config.commands.closeTiddler.handler = function(event,src,title) { story.closeTiddler(title,true); return false; }; config.commands.closeOthers.handler = function(event,src,title) { story.closeAllTiddlers(title); return false; }; config.commands.editTiddler.handler = function(event,src,title) { clearMessage(); var tiddlerElem = document.getElementById(story.idPrefix + title); var fields = tiddlerElem.getAttribute("tiddlyFields"); story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE,false,null,fields); story.focusTiddler(title,"text"); return false; }; config.commands.saveTiddler.handler = function(event,src,title) { var newTitle = story.saveTiddler(title,event.shiftKey); if(newTitle) story.displayTiddler(null,newTitle); return false; }; config.commands.cancelTiddler.handler = function(event,src,title) { if(story.hasChanges(title) && !readOnly) { if(!confirm(this.warning.format([title]))) return false; } story.setDirty(title,false); story.displayTiddler(null,title); return false; }; config.commands.deleteTiddler.handler = function(event,src,title) { var deleteIt = true; if (config.options.chkConfirmDelete) deleteIt = confirm(this.warning.format([title])); if (deleteIt) { store.removeTiddler(title); story.closeTiddler(title,true); autoSaveChanges(); } return false; }; config.commands.permalink.handler = function(event,src,title) { var t = encodeURIComponent(String.encodeTiddlyLink(title)); if(window.location.hash != t) window.location.hash = t; return false; }; config.commands.references.handlePopup = function(popup,title) { var references = store.getReferringTiddlers(title); var c = false; for(var r=0; r 0) ListView.create(popup,items,this.listViewTemplate); else createTiddlyElement(popup,"div",null,null,this.emptyText); }; //-- //-- Tiddler() object //-- function Tiddler(title) { this.title = title; this.text = null; this.modifier = null; this.modified = new Date(); this.created = new Date(); this.links = []; this.linksUpdated = false; this.tags = []; this.fields = {}; return this; } Tiddler.prototype.getLinks = function() { if(this.linksUpdated==false) this.changed(); return this.links; }; // Returns the fields that are inherited in string field:"value" field2:"value2" format Tiddler.prototype.getInheritedFields = function() { var f = {}; for(i in this.fields) { if(i=="server.host" || i=="server.workspace" || i=="wikiformat"|| i=="server.type") { f[i] = this.fields[i]; } } return String.encodeHashMap(f); }; // Increment the changeCount of a tiddler Tiddler.prototype.incChangeCount = function() { var c = this.fields['changecount']; c = c ? parseInt(c) : 0; this.fields['changecount'] = String(c+1); }; // Clear the changeCount of a tiddler Tiddler.prototype.clearChangeCount = function() { if(this.fields['changecount']) { delete this.fields['changecount']; } }; // Returns true if the tiddler has been updated since the tiddler was created or downloaded Tiddler.prototype.isTouched = function() { var changeCount = this.fields['changecount']; if(changeCount === undefined) changeCount = 0; return changeCount > 0; }; // Format the text for storage in an RSS item Tiddler.prototype.saveToRss = function(url) { var s = []; s.push(""); s.push("" + this.title.htmlEncode() + ""); s.push("" + wikifyStatic(this.text,null,this).htmlEncode() + ""); for(var t=0; t" + this.tags[t] + ""); s.push("" + url + "#" + encodeURIComponent(String.encodeTiddlyLink(this.title)) + ""); s.push("" + this.modified.toGMTString() + ""); s.push(""); return s.join("\n"); }; // Change the text and other attributes of a tiddler Tiddler.prototype.set = function(title,text,modifier,modified,tags,created,fields) { this.assign(title,text,modifier,modified,tags,created,fields); this.changed(); return this; }; // Change the text and other attributes of a tiddler without triggered a tiddler.changed() call Tiddler.prototype.assign = function(title,text,modifier,modified,tags,created,fields) { if(title != undefined) this.title = title; if(text != undefined) this.text = text; if(modifier != undefined) this.modifier = modifier; if(modified != undefined) this.modified = modified; if(created != undefined) this.created = created; if(fields != undefined) this.fields = fields; if(tags != undefined) this.tags = (typeof tags == "string") ? tags.readBracketedList() : tags; else if(this.tags == undefined) this.tags = []; return this; }; // Get the tags for a tiddler as a string (space delimited, using [[brackets]] for tags containing spaces) Tiddler.prototype.getTags = function() { return String.encodeTiddlyLinkList(this.tags); }; // Test if a tiddler carries a tag Tiddler.prototype.isTagged = function(tag) { return this.tags.indexOf(tag) != -1; }; // Static method to convert "\n" to newlines, "\s" to "\" Tiddler.unescapeLineBreaks = function(text) { return text ? text.unescapeLineBreaks() : ""; }; // Convert newlines to "\n", "\" to "\s" Tiddler.prototype.escapeLineBreaks = function() { return this.text.escapeLineBreaks(); }; // Updates the secondary information (like links[] array) after a change to a tiddler Tiddler.prototype.changed = function() { this.links = []; var t = this.autoLinkWikiWords() ? 0 : 1; var tiddlerLinkRegExp = t==0 ? config.textPrimitives.tiddlerAnyLinkRegExp : config.textPrimitives.tiddlerForcedLinkRegExp; tiddlerLinkRegExp.lastIndex = 0; var formatMatch = tiddlerLinkRegExp.exec(this.text); while(formatMatch) { var lastIndex = tiddlerLinkRegExp.lastIndex; if(t==0 && formatMatch[1] && formatMatch[1] != this.title) { // wikiWordLink if(formatMatch.index > 0) { var preRegExp = new RegExp(config.textPrimitives.unWikiLink+"|"+config.textPrimitives.anyLetter,"mg"); preRegExp.lastIndex = formatMatch.index-1; var preMatch = preRegExp.exec(this.text); if(preMatch.index != formatMatch.index-1) this.links.pushUnique(formatMatch[1]); } else { this.links.pushUnique(formatMatch[1]); } } else if(formatMatch[2-t] && !config.formatterHelpers.isExternalLink(formatMatch[3-t])) // titledBrackettedLink this.links.pushUnique(formatMatch[3-t]); else if(formatMatch[4-t] && formatMatch[4-t] != this.title) // brackettedLink this.links.pushUnique(formatMatch[4-t]); tiddlerLinkRegExp.lastIndex = lastIndex; formatMatch = tiddlerLinkRegExp.exec(this.text); } this.linksUpdated = true; }; Tiddler.prototype.getSubtitle = function() { var theModifier = this.modifier; if(!theModifier) theModifier = config.messages.subtitleUnknown; var theModified = this.modified; if(theModified) theModified = theModified.toLocaleString(); else theModified = config.messages.subtitleUnknown; return config.messages.tiddlerLinkTooltip.format([this.title,theModifier,theModified]); }; Tiddler.prototype.isReadOnly = function() { return readOnly; }; Tiddler.prototype.autoLinkWikiWords = function() { return !(this.isTagged("systemConfig") || this.isTagged("excludeMissing")); }; Tiddler.prototype.generateFingerprint = function() { return "0x" + Crypto.hexSha1Str(this.text); }; Tiddler.prototype.getServerType = function() { var serverType = null; if(this.fields && this.fields['server.type']) serverType = this.fields['server.type']; if(!serverType) serverType = this.fields['wikiformat']; if(serverType && !config.adaptors[serverType]) serverType = null; return serverType; }; Tiddler.prototype.getAdaptor = function() { var serverType = this.getServerType(); if(serverType) return new config.adaptors[serverType]; else return null; }; //-- //-- TiddlyWiki() object contains Tiddler()s //-- function TiddlyWiki() { var tiddlers = {}; // Hashmap by name of tiddlers this.tiddlersUpdated = false; this.namedNotifications = []; // Array of {name:,notify:} of notification functions this.notificationLevel = 0; this.slices = {}; // map tiddlerName->(map sliceName->sliceValue). Lazy. this.clear = function() { tiddlers = {}; this.setDirty(false); }; this.fetchTiddler = function(title) { return tiddlers[title]; }; this.deleteTiddler = function(title) { delete this.slices[title]; delete tiddlers[title]; }; this.addTiddler = function(tiddler) { delete this.slices[tiddler.title]; tiddlers[tiddler.title] = tiddler; }; this.forEachTiddler = function(callback) { for(var t in tiddlers) { var tiddler = tiddlers[t]; if(tiddler instanceof Tiddler) callback.call(this,t,tiddler); } }; } TiddlyWiki.prototype.setDirty = function(dirty) { this.dirty = dirty; }; TiddlyWiki.prototype.isDirty = function() { return this.dirty; }; TiddlyWiki.prototype.suspendNotifications = function() { this.notificationLevel--; }; TiddlyWiki.prototype.resumeNotifications = function() { this.notificationLevel++; }; // Invoke the notification handlers for a particular tiddler TiddlyWiki.prototype.notify = function(title,doBlanket) { if(!this.notificationLevel) { for(var t=0; t<" + "body>" + text.substring(posDiv[0],posDiv[1] + endSaveArea.length) + "<" + "/body><" + "/html>"; // Create the iframe var iframe = document.createElement("iframe"); iframe.style.display = "none"; document.body.appendChild(iframe); var doc = iframe.document; if(iframe.contentDocument) doc = iframe.contentDocument; // For NS6 else if(iframe.contentWindow) doc = iframe.contentWindow.document; // For IE5.5 and IE6 // Put the content in the iframe doc.open(); doc.writeln(content); doc.close(); // Load the content into a TiddlyWiki() object var storeArea = doc.getElementById("storeArea"); this.loadFromDiv(storeArea,"store"); // Get rid of the iframe iframe.parentNode.removeChild(iframe); return this; }; TiddlyWiki.prototype.updateTiddlers = function() { this.tiddlersUpdated = true; this.forEachTiddler(function(title,tiddler) { tiddler.changed(); }); }; // Return all tiddlers formatted as an HTML string TiddlyWiki.prototype.allTiddlersAsHtml = function() { return store.getSaver().externalize(store); }; // Return an array of tiddlers matching a search regular expression TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag) { var candidates = this.reverseLookup("tags",excludeTag,false); var results = []; for(var t=0; tString value = value instanceof Date ? value.convertToYYYYMMDDHHMMSSMMM() : String(value); if(oldValue == value) return; t.fields[fieldName] = value; } } // When we are here the tiddler/store really was changed. this.notify(t.title,true); if(!fieldName.match(/^temp\./)) this.setDirty(true); }; // Returns the value of the given field of the tiddler. // The fieldName is case-insensitive. // Will only return String values (or undefined). TiddlyWiki.prototype.getValue = function(tiddler,fieldName) { var t = this.resolveTiddler(tiddler); if(!t) return undefined; fieldName = fieldName.toLowerCase(); var accessor = TiddlyWiki.standardFieldAccess[fieldName]; if(accessor) { return accessor.get(t); } return t.fields[fieldName]; }; // Calls the callback function for every field in the tiddler. // When callback function returns a non-false value the iteration stops // and that value is returned. // The order of the fields is not defined. // @param callback a function(tiddler,fieldName,value). TiddlyWiki.prototype.forEachField = function(tiddler,callback,onlyExtendedFields) { var t = this.resolveTiddler(tiddler); if(!t) return undefined; for(var n in t.fields) { var result = callback(t,n,t.fields[n]); if(result) return result; } if(onlyExtendedFields) return undefined; for(var n in TiddlyWiki.standardFieldAccess) { if(n == "tiddler") // even though the "title" field can also be referenced through the name "tiddler" // we only visit this field once. continue; var result = callback(t,n,TiddlyWiki.standardFieldAccess[n].get(t)); if(result) return result; } return undefined; }; //-- //-- Story functions //-- function Story(container,idPrefix) { this.container = container; this.idPrefix = idPrefix; this.highlightRegExp = null; } Story.prototype.forEachTiddler = function(fn) { var place = document.getElementById(this.container); if(!place) return; var e = place.firstChild; while(e) { var n = e.nextSibling; var title = e.getAttribute("tiddler"); fn.call(this,title,e); e = n; } }; Story.prototype.displayTiddlers = function(srcElement,titles,template,animate,unused,customFields,toggle) { for(var t = titles.length-1;t>=0;t--) this.displayTiddler(srcElement,titles[t],template,animate,unused,customFields); }; Story.prototype.displayTiddler = function(srcElement,title,template,animate,unused,customFields,toggle) { var place = document.getElementById(this.container); var tiddlerElem = document.getElementById(this.idPrefix + title); if(tiddlerElem) { if(toggle) this.closeTiddler(title,true); else this.refreshTiddler(title,template,false,customFields); } else { var before = this.positionTiddler(srcElement); tiddlerElem = this.createTiddler(place,before,title,template,customFields); } if(srcElement && typeof srcElement !== "string") { if(config.options.chkAnimate && (animate == undefined || animate == true) && anim && typeof Zoomer == "function" && typeof Scroller == "function") anim.startAnimating(new Zoomer(title,srcElement,tiddlerElem),new Scroller(tiddlerElem)); else window.scrollTo(0,ensureVisible(tiddlerElem)); } }; Story.prototype.positionTiddler = function(srcElement) { var place = document.getElementById(this.container); var before = null; if(typeof srcElement == "string") { switch(srcElement) { case "top": before = place.firstChild; break; case "bottom": before = null; break; } } else { var after = this.findContainingTiddler(srcElement); if(after == null) { before = place.firstChild; } else if(after.nextSibling) { before = after.nextSibling; if(before.nodeType != 1) before = null; } } return before; }; Story.prototype.createTiddler = function(place,before,title,template,customFields) { var tiddlerElem = createTiddlyElement(null,"div",this.idPrefix + title,"tiddler"); tiddlerElem.setAttribute("refresh","tiddler"); if(customFields) tiddlerElem.setAttribute("tiddlyFields",customFields); place.insertBefore(tiddlerElem,before); var defaultText = null; if(!store.tiddlerExists(title) && !store.isShadowTiddler(title)) defaultText = this.loadMissingTiddler(title,customFields,tiddlerElem); this.refreshTiddler(title,template,false,customFields,defaultText); return tiddlerElem; }; Story.prototype.loadMissingTiddler = function(title,fields,tiddlerElem) { var tiddler = new Tiddler(title); tiddler.fields = typeof fields == "string" ? fields.decodeHashMap() : (fields ? fields : {}); var serverType = tiddler.getServerType(); var host = tiddler.fields['server.host']; var workspace = tiddler.fields['server.workspace']; if(!serverType | !host) return null; var sm = new SyncMachine(serverType,{ start: function() { return this.openHost(host,"openWorkspace"); }, openWorkspace: function() { return this.openWorkspace(workspace,"getTiddler"); }, getTiddler: function() { return this.getTiddler(title,"gotTiddler"); }, gotTiddler: function(tiddler) { if(tiddler && tiddler.text) { var downloaded = new Date(); if(!tiddler.created) tiddler.created = downloaded; if(!tiddler.modified) tiddler.modified = tiddler.created; store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields,true,tiddler.created); autoSaveChanges(); } delete this; return true; }, error: function(message) { displayMessage("Error loading missing tiddler from %0: %1".format([host,message])); } }); sm.go(); return config.messages.loadingMissingTiddler.format([title,serverType,host,workspace]); }; Story.prototype.chooseTemplateForTiddler = function(title,template) { if(!template) template = DEFAULT_VIEW_TEMPLATE; if(template == DEFAULT_VIEW_TEMPLATE || template == DEFAULT_EDIT_TEMPLATE) template = config.tiddlerTemplates[template]; return template; }; Story.prototype.getTemplateForTiddler = function(title,template,tiddler) { return store.getRecursiveTiddlerText(template,null,10); }; Story.prototype.refreshTiddler = function(title,template,force,customFields,defaultText) { var tiddlerElem = document.getElementById(this.idPrefix + title); if(tiddlerElem) { if(tiddlerElem.getAttribute("dirty") == "true" && !force) return tiddlerElem; template = this.chooseTemplateForTiddler(title,template); var currTemplate = tiddlerElem.getAttribute("template"); if((template != currTemplate) || force) { var tiddler = store.getTiddler(title); if(!tiddler) { tiddler = new Tiddler(); if(store.isShadowTiddler(title)) { tiddler.set(title,store.getTiddlerText(title),config.views.wikified.shadowModifier,version.date,[],version.date); } else { var text = template=="EditTemplate" ? config.views.editor.defaultText.format([title]) : config.views.wikified.defaultText.format([title]); text = defaultText ? defaultText : text; var fields = customFields ? customFields.decodeHashMap() : null; tiddler.set(title,text,config.views.wikified.defaultModifier,version.date,[],version.date,fields); } } tiddlerElem.setAttribute("tags",tiddler.tags.join(" ")); tiddlerElem.setAttribute("tiddler",title); tiddlerElem.setAttribute("template",template); var me = this; tiddlerElem.onmouseover = this.onTiddlerMouseOver; tiddlerElem.onmouseout = this.onTiddlerMouseOut; tiddlerElem.ondblclick = this.onTiddlerDblClick; tiddlerElem[window.event?"onkeydown":"onkeypress"] = this.onTiddlerKeyPress; var html = this.getTemplateForTiddler(title,template,tiddler); tiddlerElem.innerHTML = html; applyHtmlMacros(tiddlerElem,tiddler); if(store.getTaggedTiddlers(title).length > 0) addClass(tiddlerElem,"isTag"); else removeClass(tiddlerElem,"isTag"); if(!store.tiddlerExists(title)) { if(store.isShadowTiddler(title)) addClass(tiddlerElem,"shadow"); else addClass(tiddlerElem,"missing"); } else { removeClass(tiddlerElem,"shadow"); removeClass(tiddlerElem,"missing"); } if(customFields) this.addCustomFields(tiddlerElem,customFields); forceReflow(); } } return tiddlerElem; }; Story.prototype.addCustomFields = function(place,customFields) { var fields = customFields.decodeHashMap(); var w = document.createElement("div"); w.style.display = "none"; place.appendChild(w); for(var t in fields) { var e = document.createElement("input"); e.setAttribute("type","text"); e.setAttribute("value",fields[t]); w.appendChild(e); e.setAttribute("edit",t); } }; Story.prototype.refreshAllTiddlers = function() { var place = document.getElementById(this.container); var e = place.firstChild; if(!e) return; this.refreshTiddler(e.getAttribute("tiddler"),e.getAttribute("template"),true); while((e = e.nextSibling) != null) this.refreshTiddler(e.getAttribute("tiddler"),e.getAttribute("template"),true); }; Story.prototype.onTiddlerMouseOver = function(e) { if(window.addClass instanceof Function) addClass(this,"selected"); }; Story.prototype.onTiddlerMouseOut = function(e) { if(window.removeClass instanceof Function) removeClass(this,"selected"); }; Story.prototype.onTiddlerDblClick = function(e) { if(!e) var e = window.event; var theTarget = resolveTarget(e); if(theTarget && theTarget.nodeName.toLowerCase() != "input" && theTarget.nodeName.toLowerCase() != "textarea") { if(document.selection && document.selection.empty) document.selection.empty(); config.macros.toolbar.invokeCommand(this,"defaultCommand",e); e.cancelBubble = true; if(e.stopPropagation) e.stopPropagation(); return true; } else { return false; } }; Story.prototype.onTiddlerKeyPress = function(e) { if(!e) var e = window.event; clearMessage(); var consume = false; var title = this.getAttribute("tiddler"); var target = resolveTarget(e); switch(e.keyCode) { case 9: // Tab if(config.options.chkInsertTabs && target.tagName.toLowerCase() == "textarea") { replaceSelection(target,String.fromCharCode(9)); consume = true; } if(config.isOpera) { target.onblur = function() { this.focus(); this.onblur = null; }; } break; case 13: // Ctrl-Enter case 10: // Ctrl-Enter on IE PC case 77: // Ctrl-Enter is "M" on some platforms if(e.ctrlKey) { blurElement(this); config.macros.toolbar.invokeCommand(this,"defaultCommand",e); consume = true; } break; case 27: // Escape blurElement(this); config.macros.toolbar.invokeCommand(this,"cancelCommand",e); consume = true; break; } e.cancelBubble = consume; if(consume) { if(e.stopPropagation) e.stopPropagation(); // Stop Propagation e.returnValue = true; // Cancel The Event in IE if(e.preventDefault ) e.preventDefault(); // Cancel The Event in Moz } return !consume; }; Story.prototype.getTiddlerField = function(title,field) { var tiddlerElem = document.getElementById(this.idPrefix + title); var e = null; if(tiddlerElem != null) { var children = tiddlerElem.getElementsByTagName("*"); for(var t=0; t 0) displayMessage(config.macros.search.successMsg.format([titles.length.toString(),q + text + q])); else displayMessage(config.macros.search.failureMsg.format([q + text + q])); }; Story.prototype.findContainingTiddler = function(e) { while(e && !hasClass(e,"tiddler")) e = e.parentNode; return e; }; Story.prototype.gatherSaveFields = function(e,fields) { if(e && e.getAttribute) { var f = e.getAttribute("edit"); if(f) fields[f] = e.value.replace(/\r/mg,""); if(e.hasChildNodes()) { var c = e.childNodes; for(var t=0; t 0) { if(!confirm(config.macros.importTiddlers.confirmOverwriteText.format([overwrite.join(", ")]))) return false; } wizard.addStep(config.macros.importTiddlers.step4Title.format([rowNames.length]),config.macros.importTiddlers.step4Html); for(t=0; t si.tiddler.fields['server.page.revision']) { si.syncStatus = config.macros.sync.syncStatusList[si.isTouched ? 'changedBoth' : 'changedServer']; } } else { si.syncStatus = config.macros.sync.syncStatusList.notFound; } config.macros.sync.updateSyncStatus(si); } }, getTiddler: function(title) { return this.getTiddler(title,"onGetTiddler"); }, onGetTiddler: function(tiddler) { var syncItem = st.syncItems.findByField("title",tiddler.title); if(syncItem !== null) { syncItem = st.syncItems[syncItem]; store.saveTiddler(tiddler.title, tiddler.title, tiddler.text, tiddler.modifier, tiddler.modified, tiddler.tags, tiddler.fields, true, tiddler.created); syncItem.syncStatus = config.macros.sync.syncStatusList.gotFromServer; config.macros.sync.updateSyncStatus(syncItem); } }, putTiddler: function(tiddler) { return this.putTiddler(tiddler,"onPutTiddler"); }, onPutTiddler: function(tiddler) { var syncItem = st.syncItems.findByField("title",tiddler.title); if(syncItem !== null) { syncItem = st.syncItems[syncItem]; store.resetTiddler(tiddler.title); syncItem.syncStatus = config.macros.sync.syncStatusList.putToServer; config.macros.sync.updateSyncStatus(syncItem); } } }); st.syncMachine.go(); return st; }; config.macros.sync.updateSyncStatus = function(syncItem) { var e = syncItem.colElements["status"]; removeChildren(e); createTiddlyText(e,syncItem.syncStatus.text); syncItem.rowElement.style.backgroundColor = syncItem.syncStatus.color; }; config.macros.sync.doSync = function(e) { var rowNames = ListView.getSelectedRows(currSync.listView); for(var t=0; t=0; t--) stash.appendChild(nodes[t]); } var wrapper = document.getElementById("contentWrapper"); if(!title) title = "PageTemplate"; var html = store.getRecursiveTiddlerText(title,null,10); wrapper.innerHTML = html; applyHtmlMacros(wrapper); refreshElements(wrapper); display = document.getElementById("tiddlerDisplay"); removeChildren(display); if(!display) display = createTiddlyElement(wrapper,"div","tiddlerDisplay"); nodes = stash.childNodes; for(t=nodes.length-1; t>=0; t--) display.appendChild(nodes[t]); removeNode(stash); } function refreshDisplay(hint) { if(typeof hint == "string") hint = [hint]; var e = document.getElementById("contentWrapper"); refreshElements(e,hint); if(backstage.isPanelVisible()) { e = document.getElementById("backstage"); refreshElements(e,hint); } } function refreshPageTitle() { document.title = getPageTitle(); } function getPageTitle() { var st = wikifyPlain("SiteTitle"); var ss = wikifyPlain("SiteSubtitle"); return st + ((st == "" || ss == "") ? "" : " - ") + ss; } function refreshStyles(title,doc) { if(!doc) doc = document; setStylesheet(title == null ? "" : store.getRecursiveTiddlerText(title,"",10),title,doc); } function refreshColorPalette(title) { if(!startingUp) refreshAll(); } function refreshAll() { refreshPageTemplate(); refreshDisplay(); refreshStyles("StyleSheetLayout"); refreshStyles("StyleSheetColors"); refreshStyles("StyleSheet"); refreshStyles("StyleSheetPrint"); } //-- //-- Options cookie stuff //-- config.optionHandlers = { 'txt': { get: function(name) {return encodeCookie(config.options[name].toString());}, set: function(name,value) {config.options[name] = decodeCookie(value);} }, 'chk': { get: function(name) {return config.options[name] ? "true" : "false";}, set: function(name,value) {config.options[name] = value == "true";} } }; function loadOptionsCookie() { if(safeMode) return; var cookies = document.cookie.split(";"); for(var c=0; c'; // Split up into two so that indexOf() of this source doesn't find it var endSaveArea = ''; // If there are unsaved changes, force the user to confirm before exitting function confirmExit() { hadConfirmExit = true; if((store && store.isDirty && store.isDirty()) || (story && story.areAnyDirty && story.areAnyDirty())) return config.messages.confirmExit; } // Give the user a chance to save changes before exitting function checkUnsavedChanges() { if(store && store.isDirty && store.isDirty() && window.hadConfirmExit === false) { if(confirm(config.messages.unsavedChangesWarning)) saveChanges(); } } function updateLanguageAttribute(s) { if(config.locale) { var mRE = /(/; var m = mRE.exec(s); if(m) { var t = m[1]; if(m[2]) t += ' xml:lang="' + config.locale + '"'; if(m[3]) t += ' lang="' + config.locale + '"'; t += ">"; s = s.substr(0,m.index) + t + s.substr(m.index+m[0].length); } } return s; } function updateMarkupBlock(s,blockName,tiddlerName) { return s.replaceChunk( "".format([blockName]), "".format([blockName]), "\n" + store.getRecursiveTiddlerText(tiddlerName,"") + "\n"); } function updateOriginal(original,posDiv) { if(!posDiv) posDiv = locateStoreArea(original); if(!posDiv) { alert(config.messages.invalidFileError.format([localPath])); return null; } var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" + convertUnicodeToUTF8(store.allTiddlersAsHtml()) + "\n" + original.substr(posDiv[1]); var newSiteTitle = convertUnicodeToUTF8(getPageTitle()).htmlEncode(); revised = revised.replaceChunk("",""," " + newSiteTitle + " "); revised = updateLanguageAttribute(revised); 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; } function locateStoreArea(original) { // Locate the storeArea div's var posOpeningDiv = original.indexOf(startSaveArea); var limitClosingDiv = original.indexOf("<"+"!--POST-STOREAREA--"+">"); if(limitClosingDiv == -1) limitClosingDiv = original.indexOf("<"+"!--POST-BODY-START--"+">"); var posClosingDiv = original.lastIndexOf(endSaveArea,limitClosingDiv == -1 ? original.length : limitClosingDiv); return (posOpeningDiv != -1 && posClosingDiv != -1) ? [posOpeningDiv,posClosingDiv] : null; } function autoSaveChanges(onlyIfDirty,tiddlers) { if(config.options.chkAutoSave) saveChanges(onlyIfDirty,tiddlers); } // Save this tiddlywiki with the pending changes function saveChanges(onlyIfDirty,tiddlers) { if(onlyIfDirty && !store.isDirty()) return; clearMessage(); // Get the URL of the document var originalPath = document.location.toString(); // Check we were loaded from a file URL if(originalPath.substr(0,5) != "file:") { alert(config.messages.notFileUrlError); if(store.tiddlerExists(config.messages.saveInstructions)) story.displayTiddler(null,config.messages.saveInstructions); return; } var localPath = getLocalPath(originalPath); // Load the original file var original = loadFile(localPath); if(original == null) { alert(config.messages.cantSaveError); if(store.tiddlerExists(config.messages.saveInstructions)) story.displayTiddler(null,config.messages.saveInstructions); return; } // Locate the storeArea div's var posDiv = locateStoreArea(original); if(!posDiv) { alert(config.messages.invalidFileError.format([localPath])); return; } saveBackup(localPath,original); saveRss(localPath); saveEmpty(localPath,original,posDiv); saveMain(localPath,original,posDiv); } function saveBackup(localPath,original) { // Save the backup if(config.options.chkSaveBackups) { var backupPath = getBackupPath(localPath); var backup = config.browser.isIE ? ieCopyFile(backupPath,localPath) : saveFile(backupPath,original); if(backup) displayMessage(config.messages.backupSaved,"file://" + backupPath); else alert(config.messages.backupFailed); } } function saveRss(localPath) { if(config.options.chkGenerateAnRssFeed) { var rssPath = localPath.substr(0,localPath.lastIndexOf(".")) + ".xml"; var rssSave = saveFile(rssPath,convertUnicodeToUTF8(generateRss())); if(rssSave) displayMessage(config.messages.rssSaved,"file://" + rssPath); else alert(config.messages.rssFailed); } } function saveEmpty(localPath,original,posDiv) { if(config.options.chkSaveEmptyTemplate) { var emptyPath,p; if((p = localPath.lastIndexOf("http://www.geocities.com/")) != -1) emptyPath = localPath.substr(0,p) + "/empty.html"; else if((p = localPath.lastIndexOf("\\")) != -1) emptyPath = localPath.substr(0,p) + "\\empty.html"; else emptyPath = localPath + ".empty.html"; var empty = original.substr(0,posDiv[0] + startSaveArea.length) + original.substr(posDiv[1]); var emptySave = saveFile(emptyPath,empty); if(emptySave) displayMessage(config.messages.emptySaved,"file://" + emptyPath); else alert(config.messages.emptyFailed); } } function saveMain(localPath,original,posDiv) { var save; try { var revised = updateOriginal(original,posDiv); save = saveFile(localPath,revised); } catch (ex) { showException(ex); } if(save) { displayMessage(config.messages.mainSaved,"file://" + localPath); store.setDirty(false); } else { alert(config.messages.mainFailed); } } function getLocalPath(origPath) { var originalPath = convertUriToUTF8(origPath,config.options.txtFileSystemCharSet); // Remove any location or query part of the URL var argPos = originalPath.indexOf("?"); if(argPos != -1) originalPath = originalPath.substr(0,argPos); var hashPos = originalPath.indexOf("#"); if(hashPos != -1) originalPath = originalPath.substr(0,hashPos); // Convert file://localhost/ to file:/// if(originalPath.indexOf("file:////localhost/") == 0) originalPath = "file://" + originalPath.substr(16); // Convert to a native file format var localPath; if(originalPath.charAt(9) == ":") // pc local file localPath = unescape(originalPath.substr(8)).replace(new RegExp("http://www.geocities.com/","g"),"\\"); else if(originalPath.indexOf("file://///") == 0) // FireFox pc network file localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("http://www.geocities.com/","g"),"\\"); else if(originalPath.indexOf("file:///") == 0) // mac/unix local file localPath = unescape(originalPath.substr(7)); else if(originalPath.indexOf("file:/") == 0) // mac/unix local file localPath = unescape(originalPath.substr(5)); else // pc network file localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("http://www.geocities.com/","g"),"\\"); return localPath; } function getBackupPath(localPath) { var backSlash = true; var dirPathPos = localPath.lastIndexOf("\\"); if(dirPathPos == -1) { dirPathPos = localPath.lastIndexOf("http://www.geocities.com/"); backSlash = false; } var backupFolder = config.options.txtBackupFolder; if(!backupFolder || backupFolder == "") backupFolder = "."; var backupPath = localPath.substr(0,dirPathPos) + (backSlash ? "\\" : "/") + backupFolder + localPath.substr(dirPathPos); backupPath = backupPath.substr(0,backupPath.lastIndexOf(".")) + "." + (new Date()).convertToYYYYMMDDHHMMSSMMM() + ".html"; return backupPath; } function generateRss() { var s = []; var d = new Date(); var u = store.getTiddlerText("SiteUrl"); // Assemble the header s.push("<" + "?xml version=\"1.0\"?" + ">"); s.push(""); s.push(""); s.push("" + wikifyPlain("SiteTitle").htmlEncode() + ""); if(u) s.push("" + u.htmlEncode() + ""); s.push("" + wikifyPlain("SiteSubtitle").htmlEncode() + ""); s.push("en-us"); s.push("Copyright " + d.getFullYear() + " " + config.options.txtUserName.htmlEncode() + ""); s.push("" + d.toGMTString() + ""); s.push("" + d.toGMTString() + ""); s.push("http://blogs.law.harvard.edu/tech/rss"); s.push("TiddlyWiki " + version.major + "." + version.minor + "." + version.revision + ""); // The body var tiddlers = store.getTiddlers("modified","excludeLists"); var n = config.numRssItems > tiddlers.length ? 0 : tiddlers.length-config.numRssItems; for (var t=tiddlers.length-1; t>=n; t--) s.push(tiddlers[t].saveToRss(u)); // And footer s.push(""); s.push(""); // Save it all return s.join("\n"); } //-- //-- Filesystem code //-- function convertUTF8ToUnicode(u) { if(window.netscape == undefined) return manualConvertUTF8ToUnicode(u); else return mozConvertUTF8ToUnicode(u); } function manualConvertUTF8ToUnicode(utf) { var uni = utf; var src = 0; var dst = 0; var b1, b2, b3; var c; while(src < utf.length) { b1 = utf.charCodeAt(src++); if(b1 < 0x80) { dst++; } else if(b1 < 0xE0) { b2 = utf.charCodeAt(src++); c = String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F)); uni = uni.substring(0,dst++).concat(c,utf.substr(src)); } else { b2 = utf.charCodeAt(src++); b3 = utf.charCodeAt(src++); c = String.fromCharCode(((b1 & 0xF) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)); uni = uni.substring(0,dst++).concat(c,utf.substr(src)); } } return uni; } function mozConvertUTF8ToUnicode(u) { try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); converter.charset = "UTF-8"; } catch(ex) { return manualConvertUTF8ToUnicode(u); } // fallback var s = converter.ConvertToUnicode(u); var fin = converter.Finish(); return (fin.length > 0) ? s+fin : s; } function convertUnicodeToUTF8(s) { if(window.netscape == undefined) return manualConvertUnicodeToUTF8(s); else return mozConvertUnicodeToUTF8(s); } function manualConvertUnicodeToUTF8(s) { var re = /[^\u0000-\u007F]/g ; return s.replace(re,function($0) {return "&#" + $0.charCodeAt(0).toString() + ";";}); } function mozConvertUnicodeToUTF8(s) { try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); converter.charset = "UTF-8"; } catch(ex) { return manualConvertUnicodeToUTF8(s); } // fallback var u = converter.ConvertFromUnicode(s); var fin = converter.Finish(); if(fin.length > 0) return u + fin; else return u; } function convertUriToUTF8(uri,charSet) { if(window.netscape == undefined || charSet == undefined || charSet == "") return uri; try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var converter = Components.classes["@mozilla.org/intl/utf8converterservice;1"].getService(Components.interfaces.nsIUTF8ConverterService); } catch(ex) { return uri; } return converter.convertURISpecToUTF8(uri,charSet); } function saveFile(fileUrl,content) { var r = null; if(!r) r = mozillaSaveFile(fileUrl,content); if(!r) r = ieSaveFile(fileUrl,content); if(!r) r = javaSaveFile(fileUrl,content); return r; } function loadFile(fileUrl) { var r = null; if((r == null) || (r == false)) r = mozillaLoadFile(fileUrl); if((r == null) || (r == false)) r = ieLoadFile(fileUrl); if((r == null) || (r == false)) r = javaLoadFile(fileUrl); return r; } // Returns null if it can't do it, false if there's an error, true if it saved OK function ieSaveFile(filePath,content) { try { var fso = new ActiveXObject("Scripting.FileSystemObject"); } catch(ex) { return null; } var file = fso.OpenTextFile(filePath,2,-1,0); file.Write(content); file.Close(); return true; } // Returns null if it can't do it, false if there's an error, or a string of the content if successful function ieLoadFile(filePath) { try { var fso = new ActiveXObject("Scripting.FileSystemObject"); var file = fso.OpenTextFile(filePath,1); var content = file.ReadAll(); file.Close(); } catch(ex) { return null; } return content; } function ieCopyFile(dest,source) { try { var fso = new ActiveXObject("Scripting.FileSystemObject"); fso.GetFile(source).Copy(dest); } catch(ex) { return false; } return true; } // Returns null if it can't do it, false if there's an error, true if it saved OK function mozillaSaveFile(filePath,content) { if(window.Components) { try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); file.initWithPath(filePath); if(!file.exists()) file.create(0,0664); var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); out.init(file,0x20|0x02,00004,null); out.write(content,content.length); out.flush(); out.close(); return true; } catch(ex) { return false; } } return null; } // Returns null if it can't do it, false if there's an error, or a string of the content if successful function mozillaLoadFile(filePath) { if(window.Components) { try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); file.initWithPath(filePath); if(!file.exists()) return null; var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream); inputStream.init(file,0x01,00004,null); var sInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream); sInputStream.init(inputStream); return sInputStream.read(sInputStream.available()); } catch(ex) { return false; } } return null; } function javaUrlToFilename(url) { var f = "//localhost"; if(url.indexOf(f) == 0) return url.substring(f.length); var i = url.indexOf(":"); if(i > 0) return url.substring(i-1); return url; } function javaSaveFile(filePath,content) { try { if(document.applets["TiddlySaver"]) return document.applets["TiddlySaver"].saveFile(javaUrlToFilename(filePath),"UTF-8",content); } catch(ex) { } try { var s = new java.io.PrintStream(new java.io.FileOutputStream(javaUrlToFilename(filePath))); s.print(content); s.close(); } catch(ex) { return null; } return true; } function javaLoadFile(filePath) { try { if(document.applets["TiddlySaver"]) return String(document.applets["TiddlySaver"].loadFile(javaUrlToFilename(filePath),"UTF-8")); } catch(ex) { } var content = []; try { var r = new java.io.BufferedReader(new java.io.FileReader(javaUrlToFilename(filePath))); var line; while((line = r.readLine()) != null) content.push(new String(line)); r.close(); } catch(ex) { return null; } return content.join("\n"); } //-- //-- Server adaptor for talking to static files //-- function FileAdaptor() { this.host = null; this.store = null; return this; } FileAdaptor.NotLoadedError = "TiddlyWiki file has not been loaded"; FileAdaptor.serverType = 'file'; // Open the specified host/server FileAdaptor.prototype.openHost = function(host,context,userParams,callback) { this.host = host; if(!context) context = {}; context.adaptor = this; context.callback = callback; context.userParams = userParams; var ret = loadRemoteFile(host,FileAdaptor.openHostCallback,context); return typeof(ret) == "string" ? ret : true; }; FileAdaptor.openHostCallback = function(status,context,responseText,url,xhr) { var adaptor = context.adaptor; context.status = status; if(!status) { context.statusText = "Error reading file: " + xhr.statusText; } else { // Load the content into a TiddlyWiki() object adaptor.store = new TiddlyWiki(); if(!adaptor.store.importTiddlyWiki(responseText)) context.statusText = config.messages.invalidFileError.format([url]); } context.callback(context,context.userParams); }; // Gets the list of workspaces on a given server FileAdaptor.prototype.getWorkspaceList = function(context,userParams,callback) { if(!context) context = {}; context.workspaces = [{title:"(default)"}]; context.status = true; window.setTimeout(function() {callback(context,userParams);},10); return true; }; // Open the specified workspace FileAdaptor.prototype.openWorkspace = function(workspace,context,userParams,callback) { if(!context) context = {}; context.status = true; window.setTimeout(function() {callback(context,userParams);},10); return true; }; // Gets the list of tiddlers within a given workspace FileAdaptor.prototype.getTiddlerList = function(context,userParams,callback) { if(!this.store) return FileAdaptor.NotLoadedError; if(!context) context = {}; context.tiddlers = []; this.store.forEachTiddler(function(title,tiddler) { var t = new Tiddler(title); t.text = tiddler.text; t.modified = tiddler.modified; t.modifier = tiddler.modifier; t.fields['server.page.revision'] = tiddler.modified.convertToYYYYMMDDHHMM(); t.tags = tiddler.tags; context.tiddlers.push(t); }); context.status = true; window.setTimeout(function() {callback(context,userParams);},10); return true; }; FileAdaptor.prototype.generateTiddlerInfo = function(tiddler) { var info = {}; info.uri = tiddler.fields['server.host'] + "#" + tiddler.title; return info; }; // Retrieves a tiddler from a given workspace on a given server FileAdaptor.prototype.getTiddler = function(title,context,userParams,callback) { if(!this.store) return FileAdaptor.NotLoadedError; if(!context) context = {}; context.tiddler = this.store.fetchTiddler(title); if(context.tiddler) { context.tiddler.fields['server.type'] = FileAdaptor.serverType; context.tiddler.fields['server.host'] = this.host; context.tiddler.fields['server.page.revision'] = context.tiddler.modified.convertToYYYYMMDDHHMM(); } context.status = true; if(context.allowSynchronous) { context.isSynchronous = true; callback(context,userParams); } else { window.setTimeout(function() {callback(context,userParams);},10); } return true; }; FileAdaptor.prototype.close = function() { delete this.store; this.store = null; }; config.adaptors[FileAdaptor.serverType] = FileAdaptor; //-- //-- Remote HTTP requests //-- function loadRemoteFile(url,callback,params) { return doHttp("GET",url,null,null,null,null,callback,params,null); } // HTTP status codes var httpStatus = { OK: 200, ContentCreated: 201, NoContent: 204, Unauthorized: 401, Forbidden: 403, NotFound: 404, MethodNotAllowed: 405 }; function doHttp(type,url,data,contentType,username,password,callback,params,headers) { // Get an xhr object var x = getXMLHttpRequest(); if(!x) return "Can't create XMLHttpRequest object"; // Install callback x.onreadystatechange = function() { if (x.readyState == 4 && callback && (x.status !== undefined)) { if([0, httpStatus.OK, httpStatus.ContentCreated, httpStatus.NoContent].contains(x.status)) callback(true,params,x.responseText,url,x); else callback(false,params,null,url,x); x.onreadystatechange = function(){}; x = null; } }; // Send request if(window.Components && window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1) window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); try { url = url + (url.indexOf("?") < 0 ? "?" : "&") + "nocache=" + Math.random(); x.open(type,url,true,username,password); if (data) x.setRequestHeader("Content-Type", contentType ? contentType : "application/x-www-form-urlencoded"); if (x.overrideMimeType) x.setRequestHeader("Connection", "close"); if(headers) { for(n in headers) x.setRequestHeader(n,headers[n]); } x.setRequestHeader("X-Requested-With", "TiddlyWiki " + version.major + "." + version.minor + "." + version.revision + (version.beta ? " (beta " + version.beta + ")" : "")); x.send(data); } catch (ex) { return exceptionText(ex); } return x; } function getXMLHttpRequest() { try { var x = new XMLHttpRequest(); // Modern } catch(ex) { try { x = new ActiveXObject("Msxml2.XMLHTTP"); // IE 6 } catch (ex2) { return null; } } return x; } //-- //-- TiddlyWiki-specific utility functions //-- function createTiddlyButton(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey) { var theButton = document.createElement("a"); if(theAction) { theButton.onclick = theAction; theButton.setAttribute("href","javascript:;"); } if(theTooltip) theButton.setAttribute("title",theTooltip); if(theText) theButton.appendChild(document.createTextNode(theText)); if(theClass) theButton.className = theClass; else theButton.className = "button"; if(theId) theButton.id = theId; if(theParent) theParent.appendChild(theButton); if(theAccessKey) theButton.setAttribute("accessKey",theAccessKey); return theButton; } function createTiddlyLink(place,title,includeText,theClass,isStatic,linkedFromTiddler,noToggle) { var text = includeText ? title : null; var i = getTiddlyLinkInfo(title,theClass); var btn = isStatic ? createExternalLink(place,store.getTiddlerText("SiteUrl",null) + "#" + title) : createTiddlyButton(place,text,i.subTitle,onClickTiddlerLink,i.classes); btn.setAttribute("refresh","link"); btn.setAttribute("tiddlyLink",title); if(noToggle) btn.setAttribute("noToggle","true"); if(linkedFromTiddler) { var fields = linkedFromTiddler.getInheritedFields(); if(fields) btn.setAttribute("tiddlyFields",fields); } return btn; } function refreshTiddlyLink(e,title) { var i = getTiddlyLinkInfo(title,e.className); e.className = i.classes; e.title = i.subTitle; } function getTiddlyLinkInfo(title,currClasses) { var classes = currClasses ? currClasses.split(" ") : []; classes.pushUnique("tiddlyLink"); var tiddler = store.fetchTiddler(title); var subTitle; if(tiddler) { subTitle = tiddler.getSubtitle(); classes.pushUnique("tiddlyLinkExisting"); classes.remove("tiddlyLinkNonExisting"); classes.remove("shadow"); } else { classes.remove("tiddlyLinkExisting"); classes.pushUnique("tiddlyLinkNonExisting"); if(store.isShadowTiddler(title)) { subTitle = config.messages.shadowedTiddlerToolTip.format([title]); classes.pushUnique("shadow"); } else { subTitle = config.messages.undefinedTiddlerToolTip.format([title]); classes.remove("shadow"); } } if(config.annotations[title]) subTitle = config.annotations[title]; return {classes: classes.join(" "),subTitle: subTitle}; } function createExternalLink(place,url) { var theLink = document.createElement("a"); theLink.className = "externalLink"; theLink.href = url; theLink.title = config.messages.externalLinkTooltip.format([url]); if(config.options.chkOpenInNewWindow) theLink.target = "_blank"; place.appendChild(theLink); return theLink; } // Event handler for clicking on a tiddly link function onClickTiddlerLink(e) { if(!e) e = window.event; var theTarget = resolveTarget(e); var theLink = theTarget; var title = null; var fields = null; var noToggle = null; do { title = theLink.getAttribute("tiddlyLink"); fields = theLink.getAttribute("tiddlyFields"); noToggle = theLink.getAttribute("noToggle"); theLink = theLink.parentNode; } while(title == null && theLink != null); if(!fields && !store.isShadowTiddler(title)) fields = String.encodeHashMap(config.defaultCustomFields); if(title) { var toggling = e.metaKey || e.ctrlKey; if(config.options.chkToggleLinks) toggling = !toggling; if(noToggle) toggling = false; story.displayTiddler(theTarget,title,null,true,null,fields,toggling); } clearMessage(); return false; } // Create a button for a tag with a popup listing all the tiddlers that it tags function createTagButton(place,tag,excludeTiddler) { var theTag = createTiddlyButton(place,tag,config.views.wikified.tag.tooltip.format([tag]),onClickTag); theTag.setAttribute("tag",tag); if(excludeTiddler) theTag.setAttribute("tiddler",excludeTiddler); return theTag; } // Event handler for clicking on a tiddler tag function onClickTag(e) { if(!e) var e = window.event; var theTarget = resolveTarget(e); var popup = Popup.create(this); var tag = this.getAttribute("tag"); var title = this.getAttribute("tiddler"); if(popup && tag) { var tagged = store.getTaggedTiddlers(tag); var titles = []; var li,r; for(r=0;r 0) { var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll); openAll.setAttribute("tag",tag); createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div"); for(r=0; r= this.endTime) { this.stop(); return false; } return true; }; //-- //-- Zoomer animation //-- function Zoomer(text,startElement,targetElement,unused) { var e = createTiddlyElement(document.body,"div",null,"zoomer"); createTiddlyElement(e,"div",null,null,text); var winWidth = findWindowWidth(); var winHeight = findWindowHeight(); var p = [ {style: 'left', start: findPosX(startElement), end: findPosX(targetElement), template: '%0px'}, {style: 'top', start: findPosY(startElement), end: findPosY(targetElement), template: '%0px'}, {style: 'width', start: Math.min(startElement.scrollWidth,winWidth), end: Math.min(targetElement.scrollWidth,winWidth), template: '%0px', atEnd: 'auto'}, {style: 'height', start: Math.min(startElement.scrollHeight,winHeight), end: Math.min(targetElement.scrollHeight,winHeight), template: '%0px', atEnd: 'auto'}, {style: 'fontSize', start: 8, end: 24, template: '%0pt'} ]; var c = function(element,properties) {removeNode(element);}; return new Morpher(e,config.animDuration,p,c); } //-- //-- Scroller animation //-- function Scroller(targetElement,unused) { var p = [ {style: '-tw-vertScroll', start: findScrollY(), end: ensureVisible(targetElement)} ]; return new Morpher(targetElement,config.animDuration,p); } //-- //-- Slider animation //-- // deleteMode - "none", "all" [delete target element and it's children], [only] "children" [but not the target element] function Slider(element,opening,unused,deleteMode) { element.style.overflow = 'hidden'; if(opening) element.style.height = '0px'; // Resolves a Firefox flashing bug element.style.display = 'block'; var left = findPosX(element); var width = element.scrollWidth; var height = element.scrollHeight; var winWidth = findWindowWidth(); var p = []; var c = null; if(opening) { p.push({style: 'height', start: 0, end: height, template: '%0px', atEnd: 'auto'}); p.push({style: 'opacity', start: 0, end: 1, template: '%0'}); p.push({style: 'filter', start: 0, end: 100, template: 'alpha(opacity:%0)'}); } else { p.push({style: 'height', start: height, end: 0, template: '%0px'}); 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)'}); switch(deleteMode) { case "all": c = function(element,properties) {removeNode(element);}; break; case "children": c = function(element,properties) {removeChildren(element);}; break; } } return new Morpher(element,config.animDuration,p,c); } //-- //-- Popup menu //-- var Popup = { stack: [] // Array of objects with members root: and popup: }; Popup.create = function(root,elem,theClass) { Popup.remove(); var popup = createTiddlyElement(document.body,elem ? elem : "ol","popup",theClass ? theClass : "popup"); Popup.stack.push({root: root, popup: popup}); return popup; }; Popup.onDocumentClick = function(e) { if (!e) var e = window.event; var target = resolveTarget(e); if(e.eventPhase == undefined) Popup.remove(); else if(e.eventPhase == Event.BUBBLING_PHASE || e.eventPhase == Event.AT_TARGET) Popup.remove(); return true; }; Popup.show = function(unused1,unused2) { var curr = Popup.stack[Popup.stack.length-1]; this.place(curr.root,curr.popup); addClass(curr.root,"highlight"); if(config.options.chkAnimate && anim && typeof Scroller == "function") anim.startAnimating(new Scroller(curr.popup)); else window.scrollTo(0,ensureVisible(curr.popup)); }; Popup.place = function(root,popup,offset) { if(!offset) var offset = {x:0, y:0}; var rootLeft = findPosX(root); var rootTop = findPosY(root); var rootHeight = root.offsetHeight; var popupLeft = rootLeft + offset.x; var popupTop = rootTop + rootHeight + offset.y; var winWidth = findWindowWidth(); if(popup.offsetWidth > winWidth*0.75) popup.style.width = winWidth*0.75 + "px"; var popupWidth = popup.offsetWidth; if(popupLeft + popupWidth > winWidth) popupLeft = winWidth - popupWidth; popup.style.left = popupLeft + "px"; popup.style.top = popupTop + "px"; popup.style.display = "block"; } Popup.remove = function() { if(Popup.stack.length > 0) { Popup.removeFrom(0); } }; Popup.removeFrom = function(from) { for(var t=Popup.stack.length-1; t>=from; t--) { var p = Popup.stack[t]; removeClass(p.root,"highlight"); removeNode(p.popup); } Popup.stack = Popup.stack.slice(0,from); }; //-- //-- Wizard support //-- function Wizard(elem) { if(elem) { this.formElem = findRelated(elem,"wizard","className"); this.bodyElem = findRelated(this.formElem.firstChild,"wizardBody","className","nextSibling"); this.footElem = findRelated(this.formElem.firstChild,"wizardFooter","className","nextSibling"); } else { this.formElem = null; this.bodyElem = null; this.footElem = null; } } Wizard.prototype.setValue = function(name,value) { if(this.formElem) this.formElem[name] = value; }; Wizard.prototype.getValue = function(name) { return this.formElem ? this.formElem[name] : null; }; Wizard.prototype.createWizard = function(place,title) { this.formElem = createTiddlyElement(place,"form",null,"wizard"); createTiddlyElement(this.formElem,"h1",null,null,title); this.bodyElem = createTiddlyElement(this.formElem,"div",null,"wizardBody"); this.footElem = createTiddlyElement(this.formElem,"div",null,"wizardFooter"); }; Wizard.prototype.clear = function() { removeChildren(this.bodyElem); }; Wizard.prototype.setButtons = function(buttonInfo,status) { removeChildren(this.footElem); for(var t=0; t max) c = max; return c; }; // Add indexOf function if browser does not support it if(!Array.indexOf) { Array.prototype.indexOf = function(item,from) { if(!from) from = 0; for(var i=from; i "backgroundColor") String.prototype.unDash = function() { var s = this.split("-"); if(s.length > 1) { for(var t=1; t currPos) r.push(this.substring(currPos,match.index)); r.push(substrings[parseInt(match[1])]); currPos = subRegExp.lastIndex; } } while(match); if(currPos < this.length) r.push(this.substring(currPos,this.length)); return r.join(""); }; // Escape any special RegExp characters with that character preceded by a backslash String.prototype.escapeRegExp = function() { var s = "\\^$*+?()=!|,{}[]."; var c = this; for(var t=0; t to ">" and " to """ String.prototype.htmlEncode = function() { return this.replace(/&/mg,"&").replace(//mg,">").replace(/\"/mg,"""); }; // Convert "&" to &, "<" to <, ">" to > and """ to " String.prototype.htmlDecode = function() { return this.replace(/</mg,"<").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&"); }; // Convert a string to it's JSON representation by encoding control characters, double quotes and backslash. See json.org String.prototype.toJSONString = function() { var m = { '\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t', '"' : '\\"', '\\': '\\\\' }; var replaceFn = function(a,b) { var c = m[b]; if(c) return c; c = b.charCodeAt(); return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); }; if(/["\\\x00-\x1f]/.test(this)) return '"' + this.replace(/([\x00-\x1f\\"])/g,replaceFn) + '"'; return '"' + this + '"'; }; // Parse a space-separated string of name:value parameters // The result is an array of objects: // result[0] = object with a member for each parameter name, value of that member being an array of values // result[1..n] = one object for each parameter, with 'name' and 'value' members String.prototype.parseParams = function(defaultName,defaultValue,allowEval,noNames,cascadeDefaults) { var parseToken = function(match,p) { var n; if(match[p]) // Double quoted n = match[p]; else if(match[p+1]) // Single quoted n = match[p+1]; else if(match[p+2]) // Double-square-bracket quoted n = match[p+2]; else if(match[p+3]) // Double-brace quoted try { n = match[p+3]; if(allowEval) n = window.eval(n); } catch(ex) { throw "Unable to evaluate {{" + match[p+3] + "}}: " + exceptionText(ex); } else if(match[p+4]) // Unquoted n = match[p+4]; else if(match[p+5]) // empty quote n = ""; return n; }; var r = [{}]; var dblQuote = "(?:\"((?:(?:\\\\\")|[^\"])+)\")"; var sngQuote = "(?:'((?:(?:\\\\\')|[^'])+)')"; var dblSquare = "(?:\\[\\[((?:\\s|\\S)*?)\\]\\])"; var dblBrace = "(?:\\{\\{((?:\\s|\\S)*?)\\}\\})"; var unQuoted = noNames ? "([^\"'\\s]\\S*)" : "([^\"':\\s][^\\s:]*)"; var emptyQuote = "((?:\"\")|(?:''))"; var skipSpace = "(?:\\s*)"; var token = "(?:" + dblQuote + "|" + sngQuote + "|" + dblSquare + "|" + dblBrace + "|" + unQuoted + "|" + emptyQuote + ")"; var re = noNames ? new RegExp(token,"mg") : new RegExp(skipSpace + token + skipSpace + "(?:(\\:)" + skipSpace + token + ")?","mg"); var params = []; do { var match = re.exec(this); if(match) { var n = parseToken(match,1); if(noNames) { r.push({name:"",value:n}); } else { var v = parseToken(match,8); if(v == null && defaultName) { v = n; n = defaultName; } else if(v == null && defaultValue) { v = defaultValue; } r.push({name:n,value:v}); if(cascadeDefaults) { defaultName = n; defaultValue = v; } } } } while(match); // Summarise parameters into first element for(var t=1; t 12 ? h-12 : ( h > 0 ? h : 12 ); }; Date.prototype.getAmPm = function() { return this.getHours() >= 12 ? config.messages.dates.pm : config.messages.dates.am; }; Date.prototype.daySuffix = function() { return config.messages.dates.daySuffixes[this.getDate()-1]; }; // Convert a date to local YYYYMMDDHHMM string format Date.prototype.convertToLocalYYYYMMDDHHMM = function() { return String.zeroPad(this.getFullYear(),4) + String.zeroPad(this.getMonth()+1,2) + String.zeroPad(this.getDate(),2) + String.zeroPad(this.getHours(),2) + String.zeroPad(this.getMinutes(),2); }; // Convert a date to UTC YYYYMMDDHHMM string format Date.prototype.convertToYYYYMMDDHHMM = function() { return String.zeroPad(this.getUTCFullYear(),4) + String.zeroPad(this.getUTCMonth()+1,2) + String.zeroPad(this.getUTCDate(),2) + String.zeroPad(this.getUTCHours(),2) + String.zeroPad(this.getUTCMinutes(),2); }; // Convert a date to UTC YYYYMMDD.HHMMSSMMM string format Date.prototype.convertToYYYYMMDDHHMMSSMMM = function() { return String.zeroPad(this.getUTCFullYear(),4) + String.zeroPad(this.getUTCMonth()+1,2) + String.zeroPad(this.getUTCDate(),2) + "." + String.zeroPad(this.getUTCHours(),2) + String.zeroPad(this.getUTCMinutes(),2) + String.zeroPad(this.getUTCSeconds(),2) + String.zeroPad(this.getUTCMilliseconds(),4); }; // Static method to create a date from a UTC YYYYMMDDHHMM format string Date.convertFromYYYYMMDDHHMM = function(d) { return new Date(Date.UTC(parseInt(d.substr(0,4),10), parseInt(d.substr(4,2),10)-1, parseInt(d.substr(6,2),10), parseInt(d.substr(8,2),10), parseInt(d.substr(10,2),10),0,0)); }; //-- //-- Crypto functions and associated conversion routines //-- // Crypto "namespace" function Crypto() {} // Convert a string to an array of big-endian 32-bit words Crypto.strToBe32s = function(str) { var be = Array(); var len = Math.floor(str.length/4); var i, j; for(i=0, j=0; i>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32); j++; } return be; }; // Convert an array of big-endian 32-bit words to a string Crypto.be32sToStr = function(be) { var str = ""; for(var i=0;i>5]>>>(24-i%32)) & 0xff); return str; }; // Convert an array of big-endian 32-bit words to a hex string Crypto.be32sToHex = function(be) { var hex = "0123456789ABCDEF"; var str = ""; for(var i=0;i>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF); return str; }; // Return, in hex, the SHA-1 hash of a string Crypto.hexSha1Str = function(str) { return Crypto.be32sToHex(Crypto.sha1Str(str)); }; // Return the SHA-1 hash of a string Crypto.sha1Str = function(str) { return Crypto.sha1(Crypto.strToBe32s(str),str.length); }; // Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words Crypto.sha1 = function(x,blen) { // Add 32-bit integers, wrapping at 32 bits add32 = function(a,b) { var lsw = (a&0xFFFF)+(b&0xFFFF); var msw = (a>>16)+(b>>16)+(lsw>>16); return (msw<<16)|(lsw&0xFFFF); }; // Add five 32-bit integers, wrapping at 32 bits add32x5 = function(a,b,c,d,e) { var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF); var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16); return (msw<<16)|(lsw&0xFFFF); }; // Bitwise rotate left a 32-bit integer by 1 bit rol32 = function(n) { return (n>>>31)|(n<<1); }; var len = blen*8; // Append padding so length in bits is 448 mod 512 x[len>>5] |= 0x80 << (24-len%32); // Append length x[((len+64>>9)<<4)+15] = len; var w = Array(80); var k1 = 0x5A827999; var k2 = 0x6ED9EBA1; var k3 = 0x8F1BBCDC; var k4 = 0xCA62C1D6; var h0 = 0x67452301; var h1 = 0xEFCDAB89; var h2 = 0x98BADCFE; var h3 = 0x10325476; var h4 = 0xC3D2E1F0; for(var i=0;i>>27)|(a<<5),d^(b&(c^d)),w[j],k1); e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t; } for(j=16;j<20;j++) { w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]); t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1); e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t; } for(j=20;j<40;j++) { w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]); t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2); e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t; } for(j=40;j<60;j++) { w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]); t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3); e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t; } for(j=60;j<80;j++) { w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]); t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4); e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t; } h0 = add32(h0,a); h1 = add32(h1,b); h2 = add32(h2,c); h3 = add32(h3,d); h4 = add32(h4,e); } return Array(h0,h1,h2,h3,h4); }; //-- //-- RGB colour object //-- // Construct an RGB colour object from a '#rrggbb', '#rgb' or 'rgb(n,n,n)' string or from separate r,g,b values function RGB(r,g,b) { this.r = 0; this.g = 0; this.b = 0; if(typeof r == "string") { if(r.substr(0,1) == "#") { if(r.length == 7) { this.r = parseInt(r.substr(1,2),16)/255; this.g = parseInt(r.substr(3,2),16)/255; this.b = parseInt(r.substr(5,2),16)/255; } else { this.r = parseInt(r.substr(1,1),16)/15; this.g = parseInt(r.substr(2,1),16)/15; this.b = parseInt(r.substr(3,1),16)/15; } } else { var rgbPattern = /rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/; var c = r.match(rgbPattern); if(c) { this.r = parseInt(c[1],10)/255; this.g = parseInt(c[2],10)/255; this.b = parseInt(c[3],10)/255; } } } else { this.r = r; this.g = g; this.b = b; } return this; } // Mixes this colour with another in a specified proportion // c = other colour to mix // f = 0..1 where 0 is this colour and 1 is the new colour // Returns an RGB object RGB.prototype.mix = function(c,f) { return new RGB(this.r + (c.r-this.r) * f,this.g + (c.g-this.g) * f,this.b + (c.b-this.b) * f); }; // Return an rgb colour as a #rrggbb format hex string RGB.prototype.toString = function() { return "#" + ("0" + Math.floor(this.r.clamp(0,1) * 255).toString(16)).right(2) + ("0" + Math.floor(this.g.clamp(0,1) * 255).toString(16)).right(2) + ("0" + Math.floor(this.b.clamp(0,1) * 255).toString(16)).right(2); }; //-- //-- DOM utilities - many derived from www.quirksmode.org //-- function drawGradient(place,horiz,colours) { for(var t=0; t<= 100; t+=2) { var bar = document.createElement("div"); place.appendChild(bar); bar.style.position = "absolute"; bar.style.left = horiz ? t + "%" : 0; bar.style.top = horiz ? 0 : t + "%"; bar.style.width = horiz ? (101-t) + "%" : "100%"; bar.style.height = horiz ? "100%" : (101-t) + "%"; bar.style.zIndex = -1; var f = t/100; var p = f*(colours.length-1); bar.style.backgroundColor = colours[Math.floor(p)].mix(colours[Math.ceil(p)],p-Math.floor(p)).toString(); } } function createTiddlyText(theParent,theText) { return theParent.appendChild(document.createTextNode(theText)); } function createTiddlyCheckbox(theParent,caption,checked,onChange) { var cb = document.createElement("input"); cb.setAttribute("type","checkbox"); cb.onclick = onChange; theParent.appendChild(cb); cb.checked = checked; cb.className = "chkOptionInput"; if(caption) wikify(caption,theParent); return cb; } function createTiddlyElement(theParent,theElement,theID,theClass,theText) { var e = document.createElement(theElement); if(theClass != null) e.className = theClass; if(theID != null) e.setAttribute("id",theID); if(theText != null) e.appendChild(document.createTextNode(theText)); if(theParent != null) theParent.appendChild(e); return e; } function addEvent(obj,type,fn) { if(obj.attachEvent) { obj['e'+type+fn] = fn; obj[type+fn] = function(){obj['e'+type+fn](window.event);}; obj.attachEvent('on'+type,obj[type+fn]); } else { obj.addEventListener(type,fn,false); } } function removeEvent(obj,type,fn) { if(obj.detachEvent) { obj.detachEvent('on'+type,obj[type+fn]); obj[type+fn] = null; } else { obj.removeEventListener(type,fn,false); } } function addClass(e,theClass) { var currClass = e.className.split(" "); if(currClass.indexOf(theClass) == -1) e.className += " " + theClass; } function removeClass(e,theClass) { var currClass = e.className.split(" "); var i = currClass.indexOf(theClass); while(i != -1) { currClass.splice(i,1); i = currClass.indexOf(theClass); } e.className = currClass.join(" "); } function hasClass(e,theClass) { if(e.className) { if(e.className.split(" ").indexOf(theClass) != -1) return true; } return false; } // Find the closest relative with a given property value (property defaults to tagName, relative defaults to parentNode) function findRelated(e,value,name,relative) { name = name ? name : "tagName"; relative = relative ? relative : "parentNode"; if(name == "className") { while(e && !hasClass(e,value)) { e = e[relative]; } } else { while(e && e[name] != value) { e = e[relative]; } } return e; } // Resolve the target object of an event function resolveTarget(e) { var obj; if(e.target) obj = e.target; else if(e.srcElement) obj = e.srcElement; if(obj.nodeType == 3) // defeat Safari bug obj = obj.parentNode; return obj; } // Return the content of an element as plain text with no formatting function getPlainText(e) { var text = ""; if(e.innerText) text = e.innerText; else if(e.textContent) text = e.textContent; return text; } // Get the scroll position for window.scrollTo necessary to scroll a given element into view function ensureVisible(e) { var posTop = findPosY(e); var posBot = posTop + e.offsetHeight; var winTop = findScrollY(); var winHeight = findWindowHeight(); var winBot = winTop + winHeight; if(posTop < winTop) { return posTop; } else if(posBot > winBot) { if(e.offsetHeight < winHeight) return posTop - (winHeight - e.offsetHeight); else return posTop; } else { return winTop; } } // Get the current width of the display window function findWindowWidth() { return window.innerWidth ? window.innerWidth : document.documentElement.clientWidth; } // Get the current height of the display window function findWindowHeight() { return window.innerHeight ? window.innerHeight : document.documentElement.clientHeight; } // Get the current horizontal page scroll position function findScrollX() { return window.scrollX ? window.scrollX : document.documentElement.scrollLeft; } // Get the current vertical page scroll position function findScrollY() { return window.scrollY ? window.scrollY : document.documentElement.scrollTop; } function findPosX(obj) { var curleft = 0; while(obj.offsetParent) { curleft += obj.offsetLeft; obj = obj.offsetParent; } return curleft; } function findPosY(obj) { var curtop = 0; while(obj.offsetParent) { curtop += obj.offsetTop; obj = obj.offsetParent; } return curtop; } // Blur a particular element function blurElement(e) { if(e != null && e.focus && e.blur) { e.focus(); e.blur(); } } // Create a non-breaking space function insertSpacer(place) { var e = document.createTextNode(String.fromCharCode(160)); if(place) place.appendChild(e); return e; } // Remove all children of a node function removeChildren(e) { while(e && e.hasChildNodes()) removeNode(e.firstChild); } // Remove a node and all it's children function removeNode(e) { scrubNode(e); e.parentNode.removeChild(e); } // Remove any event handlers or non-primitve custom attributes function scrubNode(e) { var att = e.attributes; if(att) { for(var t=0; t" + s + ""); } else { if(n) { n.replaceChild(doc.createTextNode(s),n.firstChild); } else { n = doc.createElement("style"); n.type = "text/css"; n.id = id; n.appendChild(doc.createTextNode(s)); doc.getElementsByTagName("head")[0].appendChild(n); } } } // Force the browser to do a document reflow when needed to workaround browser bugs function forceReflow() { if(config.browser.isGecko) { setStylesheet("body {top:-1em;margin-top:1em;}"); setStylesheet(""); } } // Replace the current selection of a textarea or text input and scroll it into view function replaceSelection(e,text) { if(e.setSelectionRange) { var oldpos = e.selectionStart; var isRange = e.selectionEnd > e.selectionStart; e.value = e.value.substr(0,e.selectionStart) + text + e.value.substr(e.selectionEnd); e.setSelectionRange(isRange ? oldpos : oldpos + text.length,oldpos + text.length); var linecount = e.value.split('\n').length; var thisline = e.value.substr(0,e.selectionStart).split('\n').length-1; e.scrollTop = Math.floor((thisline - e.rows / 2) * e.scrollHeight / linecount); } else if(document.selection) { var range = document.selection.createRange(); if(range.parentElement() == e) { var isCollapsed = range.text == ""; range.text = text; if(!isCollapsed) { range.moveStart('character', -text.length); range.select(); } } } } // Returns the text of the given (text) node, possibly merging subsequent text nodes function getNodeText(e) { var t = ""; while(e && e.nodeName == "#text") { t += e.nodeValue; e = e.nextSibling; } return t; } //-- //-- LoaderBase and SaverBase //-- function LoaderBase() {} LoaderBase.prototype.loadTiddler = function(store,node,tiddlers) { var title = this.getTitle(store,node); if(title) { var tiddler = store.createTiddler(title); this.internalizeTiddler(store,tiddler,title,node); tiddlers.push(tiddler); } }; LoaderBase.prototype.loadTiddlers = function(store,nodes) { var tiddlers = []; for(var t = 0; t < nodes.length; t++) { try { this.loadTiddler(store,nodes[t],tiddlers); } catch(ex) { showException(ex,config.messages.tiddlerLoadError.format([this.getTitle(store,nodes[t])])); } } return tiddlers; }; function SaverBase() {} SaverBase.prototype.externalize = function(store) { var results = []; var tiddlers = store.getTiddlers("title"); for(var t = 0; t < tiddlers.length; t++) results.push(this.externalizeTiddler(store,tiddlers[t])); return results.join("\n"); }; //-- //-- TW21Loader (inherits from LoaderBase) //-- function TW21Loader() {} TW21Loader.prototype = new LoaderBase(); TW21Loader.prototype.getTitle = function(store,node) { var title = null; if(node.getAttribute) { title = node.getAttribute("title"); if(!title) title = node.getAttribute("tiddler"); } if(!title && node.id) { var lenPrefix = store.idPrefix.length; if (node.id.substr(0,lenPrefix) == store.idPrefix) title = node.id.substr(lenPrefix); } return title; }; TW21Loader.prototype.internalizeTiddler = function(store,tiddler,title,node) { var e = node.firstChild; var text = null; if(node.getAttribute("tiddler")) { text = getNodeText(e).unescapeLineBreaks(); } else { while(e.nodeName!="PRE" && e.nodeName!="pre") { e = e.nextSibling; } text = e.innerHTML.replace(/\r/mg,"").htmlDecode(); } var modifier = node.getAttribute("modifier"); var c = node.getAttribute("created"); var m = node.getAttribute("modified"); var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date; var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created; var tags = node.getAttribute("tags"); var fields = {}; var attrs = node.attributes; for(var i = attrs.length-1; i >= 0; i--) { var name = attrs[i].name; if (attrs[i].specified && !TiddlyWiki.isStandardField(name)) { fields[name] = attrs[i].value.unescapeLineBreaks(); } } tiddler.assign(title,text,modifier,modified,tags,created,fields); return tiddler; }; //-- //-- TW21Saver (inherits from SaverBase) //-- function TW21Saver() {} TW21Saver.prototype = new SaverBase(); TW21Saver.prototype.externalizeTiddler = function(store,tiddler) { try { var extendedAttributes = ""; var usePre = config.options.chkUsePreForStorage; store.forEachField(tiddler, function(tiddler,fieldName,value) { // don't store stuff from the temp namespace if(typeof value != "string") value = ""; if (!fieldName.match(/^temp\./)) extendedAttributes += ' %0="%1"'.format([fieldName,value.escapeLineBreaks().htmlEncode()]); },true); var created = tiddler.created.convertToYYYYMMDDHHMM(); var modified = tiddler.modified.convertToYYYYMMDDHHMM(); var vdate = version.date.convertToYYYYMMDDHHMM(); var attributes = tiddler.modifier ? ' modifier="' + tiddler.modifier.htmlEncode() + '"' : ""; attributes += (usePre && modified == created) ? "" : ' modified="' + modified +'"'; attributes += (usePre && created == vdate) ? "" :' created="' + created + '"'; var tags = tiddler.getTags(); if(!usePre || tags) attributes += ' tags="' + tags.htmlEncode() + '"'; return ('
%4').format([ usePre ? "title" : "tiddler", tiddler.title.htmlEncode(), attributes, extendedAttributes, usePre ? "\n
" + tiddler.text.htmlEncode() + "
\n" : tiddler.text.escapeLineBreaks().htmlEncode() ]); } catch (ex) { throw exceptionText(ex,config.messages.tiddlerSaveError.format([tiddler.title])); } }; //-- //-- Deprecated code //-- // @Deprecated: Use createElementAndWikify and this.termRegExp instead config.formatterHelpers.charFormatHelper = function(w) { w.subWikify(createTiddlyElement(w.output,this.element),this.terminator); }; // @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead config.formatterHelpers.monospacedByLineHelper = 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 text = lookaheadMatch[1]; if(config.browser.isIE) text = text.replace(/\n/g,"\r"); createTiddlyElement(w.output,"pre",null,null,text); w.nextMatch = lookaheadRegExp.lastIndex; } }; // @Deprecated: Use
or
instead of <
> config.macros.br.handler = function(place) { createTiddlyElement(place,"br"); }; // Find an entry in an array. Returns the array index or null // @Deprecated: Use indexOf instead Array.prototype.find = function(item) { var i = this.indexOf(item); return i == -1 ? null : i; }; // Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed() // @Deprecated: Use store.getLoader().internalizeTiddler instead Tiddler.prototype.loadFromDiv = function(divRef,title) { return store.getLoader().internalizeTiddler(store,this,title,divRef); }; // Format the text for storage in an HTML DIV // @Deprecated Use store.getSaver().externalizeTiddler instead. Tiddler.prototype.saveToDiv = function() { return store.getSaver().externalizeTiddler(store,this); }; // @Deprecated: Use store.allTiddlersAsHtml() instead function allTiddlersAsHtml() { return store.allTiddlersAsHtml(); } // @Deprecated: Use refreshPageTemplate instead function applyPageTemplate(title) { refreshPageTemplate(title); } // @Deprecated: Use story.displayTiddlers instead function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3) { story.displayTiddlers(srcElement,titles,template,animate); } // @Deprecated: Use story.displayTiddler instead function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3) { story.displayTiddler(srcElement,title,template,animate); } // @Deprecated: Use functions on right hand side directly instead var createTiddlerPopup = Popup.create; var scrollToTiddlerPopup = Popup.show; var hideTiddlerPopup = Popup.remove; // @Deprecated: Use right hand side directly instead var regexpBackSlashEn = new RegExp("\\\\n","mg"); var regexpBackSlash = new RegExp("\\\\","mg"); var regexpBackSlashEss = new RegExp("\\\\s","mg"); var regexpNewLine = new RegExp("\n","mg"); var regexpCarriageReturn = new RegExp("\r","mg"); //-- //-- End of scripts config.shadowTiddlers["SiteTitle"] = "GTD"; config.shadowTiddlers["SiteSubtitle"] = "a theme for ~TiddlyWiki"; config.shadowTiddlers["MainMenu"] = "PageTemplate\nStyleSheet\nMainMenu\nDefaultTiddlers"; config.shadowTiddlers["LorumIpsum"] = "Aenean eros arcu, condimentum nec, dapibus ut, tincidunt sit amet, urna. Quisque viverra, eros sed imperdiet iaculis, est risus facilisis quam, id malesuada arcu nulla luctus urna. Nullam et est. Vestibulum velit sem, faucibus cursus, dapibus vestibulum, pellentesque et, urna. Donec luctus. Donec lectus. Aliquam eget eros facilisis tortor feugiat sollicitudin. Integer lobortis vulputate sapien. Sed iaculis erat ac nunc. Etiam eu enim. Mauris ipsum urna, rhoncus at, bibendum sit amet, euismod eget, dolor. Mauris fermentum quam vitae ligula. Vestibulum in libero feugiat justo dictum consectetuer. Vestibulum euismod purus eget elit. Nunc sed massa porta elit bibendum posuere. Nunc pulvinar justo sit amet odio. In sed est. Phasellus ornare elementum nulla. Nulla ipsum neque, cursus a, viverra a, imperdiet at, enim. Quisque facilisis, diam sed accumsan suscipit, odio arcu hendrerit dolor, quis aliquet massa nulla nec sem.\n!heading 1\n!!heading 2\n!!!heading3\n----\n<>\nThis is a link to a [[StyleSheet]] tiddler.\n\n> This is a blockquote\n> This is a blockquote\n> This is a blockquote\n|>|>| !This is a header |h\n|column1|column2|column3|\n|row2| row2 |row2|\n|column1|column2|column3|\n|row2| row2 |row2|\n|column1|column2|column3|\n|row2| row2 |row2|"; config.shadowTiddlers["DefaultTiddlers"] = "LorumIpsum"; //-- //]]>
Hosted by www.Geocities.ws

1