/% Be sure to tag this new task with a @contexttag and \n possibly a !projecttag. That way it will automatically get\n filed in GTD style. (leave the "action" tag as is) \n\n Edit the [[ Task]] TiddlerTemplate to get rid of this \n message. %/
/% Be sure to tag this new task with a @contexttag and \n possibly a !projecttag. That way it will automatically get\n filed in GTD style. (leave the "action" tag as is) \n\n Edit the [[ ReminderTask]] TiddlerTemplate to get rid of this \n message. %/\n\n<<reminder year: month: day: title:"">>
<<tiddler GTDProjectTemplate with: !projecttagname "Short Project Description">>\n/% Replace "!projecttagname" with the tag name associated with \n this context and "Short Project Description" with its \n description. \n\n NOTE: If you want to use the tag choosers at the top of the edit\n and view templates to assign context tags, you MUST \n make context tags ONE WORD LONG. Do not put any spaces\n in your context tags. ADDITIONALLY, be sure that they start \n with !.\n\n Edit [[ !Project]] to get rid of this message. %/
<<tiddler GTDContextTemplate with: @contexttagname "Context Full Name">>\n/% Replace "@contexttagname" with the tag name associated with \n this context and "Context Full Name" with its description. \n\n NOTE: If you want to use the tag choosers at the top of the edit\n and view templates to assign context tags, you MUST \n make context tags ONE WORD LONG. Do not put any spaces\n in your context tags. ADDITIONALLY, be sure that they start \n with @.\n\n NOTE: If you want to use the Actions and ActionsWithLabels\n tiddlers as they are, you MUST make the TAG NAME of\n each context EQUAL to its tiddler name. \n\n Edit [[ @context]] to get rid of this message. %/
\n\n<<reminder year: month: day: title:"">>\n/% Uncomment the following to make it easy to re-schedule this \n reminder as needed. %/\n/% <<newReminder>> %/
<<tiddler GTDProjectTemplate with: !foragingbook "Engineering Textbook on Applications of Foraging Theory">>
<<tiddler GTDProjectTemplate with: !projecttagname "Ideal Free Distribution (IFD) Internet Application">>
<<tiddler GTDProjectTemplate with: !sapatch "Research: Speed-Accuracy Patch Model Research">>
<<tiddler GTDProjectTemplate with: !saprey "Research: Speed-Accuracy Prey Model Research">>
* Find the song heard at Oxley's: "Dance Dance Revolution" repeated in refrain
!Agenda\n<<tiddler GTDAgendaTemplate with: passino KevinPassino>>\n/% For each new person on your agenda, use:\n\n<<tiddler GTDAgendaTemplate with: tagname name>>\n\n where "tagname" is the tag associated with items that should show \n up in this list and "name" is the title of this list (typically a \n person's name; typically a WikiWord) %/
<<tiddler GTDContextTemplate with: @blogging "Web and Blogging">>
<<tiddler GTDContextTemplate with: @calls "Calls and E-mails">>
<<tiddler GTDContextTemplate with: @cleaning "Cleaning and Organizing">>
<<tiddler GTDContextTemplate with: @computer "Computer">>
<<tiddler GTDContextTemplate with: @groceries "Groceries">>\n
<<tiddler GTDContextTemplate with: @shopping "Shopping and Errands">>
<<tiddler GTDContextTemplate with: @skills "Skills">>
! Someday Maybe Not?\n\nI'm not convinced this context should exist. Technically, "someday maybe" describes PROJECTS, which is why projects can be tagged with somedayMaybe. \n\nHowever, actions that have THEIR OWN context may also be put off for another day, thus action scan be tagged with somedayMaybe as well.\n\nSo this context will probably go away soon...\n-----\n<<tiddler GTDContextTemplate with: @someday "Someday Maybe">>
<<tiddler GTDContextTemplate with: @waiting "Waiting">>
<<tiddler GTDContextTemplate with: @work "Work">>
!GTD an TW 2.0\nThis is TiddlyWiki <<version>> using StyleSheet and PageTemplate tiddlers for the GTD Theme.\n\nGTD Tiddly Wiki is a GettingThingsDone adaptation by NathanBowers of JeremyRuston's Open Source TiddlyWiki. The purpose of GTD Tiddly Wiki is to give users a single repository for their GTD lists and support materials so they can create/edit lists, and then print directly to 3x5 cards for use with the HipsterPDA.\n\n!Features Include:\n* Free and Open Source.\n* Easy to update.\n* Prints directly to 3x5.\n* Searchable.\n* Exists as a single, portable, cross platform file.\n* It runs on your computer, so you can make changes when you're not online. It's not a ServerSide thing.\n!Get started:\nStart by saving GTDTiddlyWiki to your computer (right click on [[this link|#]] and select 'Save link as...' or 'Save target as...' See SaveChanges for details).\n \nYou can edit entries, or "Tidders", by clicking "edit" or double clicking anywhere on the Tiddler. When you click "done" or press [ctrl+enter] your changes are saved.\n\nThere are some pre-populated action lists in the MainMenu on the left. If you want to start with a blank slate, here is an [[empty template|http://www.checkettsweb.com/tw/gtd_empty.htm]].\n\n!!More information:\n*SupportedBrowsers\n*KeyFeatures\n*KeyboardShortcuts\n*[[Print3x5]]\n*FormattingInstructions (create lists, headings, and other formatting)\n*AboutTiddlers\n*CreateTiddlers\n*DeleteTiddlers\n* PermaView\n*KnownBugs\n* HowToUpgrade\n* ServerSide version.\n*Jeremy's original HelloThere.\n\nThanks to JeremyRuston for creating such a great Open Source project!\n----\nTiddlyWiki and GTD Tiddly Wiki are published under an OpenSourceLicense and carry NoWarranty.\n\nCurrent Version: <<version>> | RevisionHistory | UpdateNotification
"Tiddlers" are the building blocks of TiddlyWiki. Each "entry" or "post" is a Tiddler. There are also SpecialTiddlers that control the MainMenu, SiteTitle, SiteSubtitle, and list of DefaultTiddlers that display on start up.
(see also: ActionsWithLabels)\n/%\n % The rest of this page automatically lists all context tiddlers\n % as well as any actions tagged with their tiddler names. \n %/\n<part PendingActions>\n! Pending Actions\n<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"next\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"somedayMaybe\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'next\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn\s'\s" \s>\s>\s<\s<forEachTiddler where \s'tiddler.tags.contains(\s"' + tiddler.title + '\s") && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"next\s") && ! tiddler.tags.contains(\s"somedayMaybe\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn\s'\s" \s>\s>\sn'">></part>\n\n<part SomedayMaybeActions>\n+++![Someday Maybe Actions]\n<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"next\s",\s"somedayMaybe\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'somedayMaybe\s',\s'next\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn\s'\s" \s>\s>\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"somedayMaybe\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"next\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'somedayMaybe\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn\s'\s" \s>\s>\sn'">>\n===\n</part>\n\n<part DoneActions>\n+++![Done Actions]\n<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"done\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'done\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn\s'\s" \s>\s>\sn'">>\n===\n</part>
(see also: [[Actions]])\n/%\n % The rest of this page automatically lists all context tiddlers\n % as well as any actions tagged with their tiddler names. \n %\n % It also displays a list of other tags present on each action\n % tiddler.\n %/\n<part PendingActions>\n! Pending Actions\n<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"next\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"somedayMaybe\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'next\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn**\s' + ( getSortedTagsText(tiddler, [\s'action\s',\s'' + tiddler.title + '\s']) ? getSortedTagsText(tiddler, [\s'action\s',\s'' + tiddler.title + '\s']) + \s'\s\sn\s' : \s'\s' )\s" \s>\s>\s<\s<forEachTiddler where \s'tiddler.tags.contains(\s"' + tiddler.title + '\s") && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"next\s") && ! tiddler.tags.contains(\s"somedayMaybe\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn**\s' + ( getSortedTagsText(tiddler, [\s'action\s',\s'' + tiddler.title + '\s']) ? getSortedTagsText(tiddler, [\s'action\s',\s'' + tiddler.title + '\s']) + \s'\s\sn\s' : \s'\s' )\s" \s>\s>\sn'">></part>\n\n<part SomedayMaybeActions>\n+++![Someday Maybe Actions]\n<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"next\s",\s"somedayMaybe\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'somedayMaybe\s',\s'next\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn**\s' + ( getSortedTagsText(tiddler, [\s'somedayMaybe\s',\s'action\s',\s'' + tiddler.title + '\s']) ? getSortedTagsText(tiddler, [\s'somedayMaybe\s',\s'action\s',\s'' + tiddler.title + '\s']) + \s'\s\sn\s' : \s'\s' )\s" \s>\s>\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"somedayMaybe\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"next\s") && ! tiddler.tags.contains(\s"done\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'somedayMaybe\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn**\s' + ( getSortedTagsText(tiddler, [\s'somedayMaybe\s',\s'action\s',\s'' + tiddler.title + '\s']) ? getSortedTagsText(tiddler, [\s'somedayMaybe\s',\s'action\s',\s'' + tiddler.title + '\s']) + \s'\s\sn\s' : \s'\s' )\s" \s>\s>\sn'">>\n===\n</part>\n\n<part DoneActions>\n+++![Done Actions]\n<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\s<\s<forEachTiddler where \s'tiddler.tags.containsAll([\s"' + tiddler.title + '\s",\s"done\s"]) && ! tiddler.tags.contains(\s"context\s") && ! tiddler.tags.contains(\s"TiddlerTemplates\s")\s' sortBy \s"getSortedTagsText(tiddler,[\s'done\s',\s'action\s',\s'' + tiddler.title + '\s'])+\s'###\s'+tiddler.title\s" script \s'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return \s"\s"; tags.sort(); var result = \s"\s"; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? \s"\s" : \s" \s" ) + ( store.tiddlerExists(tags[i]) ? \s"[[\s" + tags[i] + \s"]]\s" : \s"\s\s<\s\s<tag \s" + tags[i] + \s"\s\s>\s\s>\s" );} return result;}\s' write \s"\s'* [[\s' + tiddler.title + \s']]\s\sn**\s' + ( getSortedTagsText(tiddler, [\s'done\s',\s'action\s',\s'' + tiddler.title + '\s']) ? getSortedTagsText(tiddler, [\s'done\s',\s'action\s',\s'' + tiddler.title + '\s']) + \s'\s\sn\s' : \s'\s' )\s" \s>\s>\sn'">>\n===\n</part>
//{{{\nconfig.options.txtBackupFolder = "twBackups";\n//}}}
JeremyRuston said:\n<<<\nA TiddlyWiki is like a blog because it's divided up into neat little chunks, but it encourages you to read it by hyperlinking rather than sequentially: if you like, a non-linear blog analogue that binds the individual microcontent items into a cohesive whole. I think that TiddlyWiki represents a novel medium for writing, and will promote it's own distinctive WritingStyle. This is the first version of TiddlyWiki and so, as discussed in TiddlyWikiDev, it's bound to be FullOfBugs, have many MissingFeatures and fail to meet all of the DesignGoals. And of course there's NoWarranty, and it might be judged a StupidName.\n<<<\n\n>level 1\n>level 1\n>>level 2\n>>level 2\n>>>level 3\n>>>level 3\n>>level 2\n>level 1\n
This ThirdVersion of TiddlyWiki fixes a problem with line breaks within tiddlers under InternetExplorer. It also tries to avoid closing tiddlers while they are being edited. There's a bunch of smaller BugFixes as well, but they are somewhat balanced by the KnownBugs.
Edit this tiddler to see how to create BulletPoints\n* Like this one\n* And this one\n** And this second-level one\n* And a final one
/***\n''Name:'' Calendar plugin\n''Version:'' 0.5\n''Author:'' SteveRumsby\n\n''Syntax:'' \n{{{<<calendar>>}}} or {{{<<calendar year>>}}} or {{{<<calendar year month>>}}} or {{{<<calendar thismonth>>}}}\n\n''Description:'' \nThe first form produces an full-year calendar for the current year. The second produces a full-year calendar for the given year. The third produces a single month calendar for the given month and year. The fourth form produces a single month calendar for the current month.\nWeekends and holidays are highlighted (see below for how to specify holdays).\n\n''Configuration:''\nModify this section to change the text displayed for the month and day names, to a different language for example. You can also change the format of the tiddler names linked to from each date, and the colours used.\n\n''Changes by ELS 2005.10.30:''\nconfig.macros.calendar.handler()\n^^use "tbody" element for IE compatibility^^\n^^IE returns 2005 for current year, FF returns 105... fix year adjustment accordingly^^\ncreateCalendarDays()\n^^use showDate() function (if defined) to render autostyled date with linked popup^^\ncalendar stylesheet definition\n^^use .calendar class-specific selectors, add text centering and margin settings^^\n***/\n//{{{\nconfig.macros.calendar = {};\n\nconfig.macros.calendar.monthnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];\nconfig.macros.calendar.daynames = ["M", "T", "W", "T", "F", "S", "S"];\nconfig.macros.calendar.firstday = 6; \nconfig.macros.calendar.firstweekend = 5;\n\nconfig.macros.calendar.weekendbg = "#eeeebb";\nconfig.macros.calendar.monthbg = "#770000";\nconfig.macros.calendar.holidaybg = "#ffc0c0";\n//}}}\n/***\n!Code section:\n***/\n// (you should not need to alter anything below here)//\n//{{{\nconfig.macros.calendar.tiddlerformat = "0DD/0MM/YYYY"; // This used to be changeable - for now, it isn't// <<smiley :-(>> \n\nversion.extensions.calendar = { major: 0, minor: 5, revision: 0, date: new Date(2006, 0, 11)};\nconfig.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\nconfig.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead\n//}}}\n\n// //Is the given date a holiday?\n//{{{\nfunction calendarIsHoliday(date)\n{\n var longHoliday = date.formatString("0DD/0MM/YYYY");\n var shortHoliday = date.formatString("0DD/0MM");\n\n for(var i = 0; i < config.macros.calendar.holidays.length; i++) {\n if(config.macros.calendar.holidays[i] == longHoliday || config.macros.calendar.holidays[i] == shortHoliday) {\n return true;\n }\n }\n return false;\n}\n//}}}\n\n// //The main entry point - the macro handler.\n// //Decide what sort of calendar we are creating (month or year, and which month or year)\n// // Create the main calendar container and pass that to sub-ordinate functions to create the structure.\n// ELS 2005.10.30: added creation and use of "tbody" for IE compatibility and fixup for year >1900//\n// ELS 2005.10.30: fix year calculation for IE's getYear() function (which returns '2005' instead of '105')//\n//{{{\nconfig.macros.calendar.handler = function(place,macroName,params)\n{\n var calendar = createTiddlyElement(place, "table", null, "calendar", null);\n var tbody = createTiddlyElement(calendar, "tbody", null, null, null);\n var today = new Date();\n var year = today.getYear();\n if (year<1900) year+=1900;\n if (params[0] == "thismonth")\n createCalendarOneMonth(tbody, year, today.getMonth());\n else if (params[0] == "lastmonth") {\n var month = today.getMonth()-1; if (month==-1) { month=11; year--; }\n createCalendarOneMonth(tbody, year, month);\n }\n else if (params[0] == "nextmonth") {\n var month = today.getMonth()+1; if (month>11) { month=0; year++; }\n createCalendarOneMonth(tbody, year, month);\n }\n else {\n if (params[0]) year = params[0];\n if(params[1])\n createCalendarOneMonth(tbody, year, params[1]-1);\n else\n createCalendarYear(tbody, year);\n }\n}\n//}}}\n\n//{{{\nfunction createCalendarOneMonth(calendar, year, mon)\n{\n var row = createTiddlyElement(calendar, "tr", null, "calenderMonthTitle", null);\n createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);\n row = createTiddlyElement(calendar, "tr", null, "calendarDaysOfWeek", null);\n createCalendarDayHeader(row, 1);\n createCalendarDayRowsSingle(calendar, year, mon);\n}\n//}}}\n\n//{{{\nfunction createCalendarMonth(calendar, year, mon)\n{\n var row = createTiddlyElement(calendar, "tr", null, null, null);\n createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, false, year, mon);\n row = createTiddlyElement(calendar, "tr", null, null, null);\n createCalendarDayHeader(row, 1);\n createCalendarDayRowsSingle(calendar, year, mon);\n}\n//}}}\n\n//{{{\nfunction createCalendarYear(calendar, year)\n{\n var row;\n row = createTiddlyElement(calendar, "tr", null, null, null);\n var back = createTiddlyElement(row, "td", null, null, null);\n var backHandler = function() {\n removeChildren(calendar);\n createCalendarYear(calendar, year-1);\n };\n createTiddlyButton(back, "<", "Back", backHandler);\n back.align = "center";\n\n var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);\n yearHeader.align = "center";\n yearHeader.setAttribute("colSpan", 19);\n\n var fwd = createTiddlyElement(row, "td", null, null, null);\n var fwdHandler = function() {\n removeChildren(calendar);\n createCalendarYear(calendar, year+1);\n };\n createTiddlyButton(fwd, ">", "Fwd", fwdHandler);\n fwd.align = "center";\n\n createCalendarMonthRow(calendar, year, 0);\n createCalendarMonthRow(calendar, year, 3);\n createCalendarMonthRow(calendar, year, 6);\n createCalendarMonthRow(calendar, year, 9);\n}\n//}}}\n\n//{{{\nfunction createCalendarMonthRow(cal, year, mon)\n{\n var row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);\n createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);\n createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);\n row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarDayHeader(row, 3);\n createCalendarDayRows(cal, year, mon);\n}\n//}}}\n\n//{{{\nfunction createCalendarMonthHeader(cal, row, name, nav, year, mon)\n{\n var month;\n if(nav) {\n var back = createTiddlyElement(row, "td", null, null, null);\n var backHandler = function() {\n var newyear = year;\n var newmon = mon-1;\n if(newmon == -1) { newmon = 11; newyear = newyear-1;}\n removeChildren(cal);\n createCalendarOneMonth(cal, newyear, newmon);\n };\n createTiddlyButton(back, "<", "Back", backHandler);\n back.align = "center";\n back.style.background = config.macros.calendar.monthbg; \n month = createTiddlyElement(row, "td", null, "calendarMonthname", name)\n month.setAttribute("colSpan", 5);\n var fwd = createTiddlyElement(row, "td", null, null, null);\n var fwdHandler = function() {\n var newyear = year;\n var newmon = mon+1;\n if(newmon == 12) { newmon = 0; newyear = newyear+1;}\n removeChildren(cal);\n createCalendarOneMonth(cal, newyear, newmon);\n };\n createTiddlyButton(fwd, ">", "Fwd", fwdHandler);\n fwd.align = "center";\n fwd.style.background = config.macros.calendar.monthbg; \n } else {\n month = createTiddlyElement(row, "td", null, "calendarMonthname", name)\n month.setAttribute("colSpan", 7);\n }\n month.align = "center";\n month.style.background = config.macros.calendar.monthbg;\n}\n//}}}\n\n//{{{\nfunction createCalendarDayHeader(row, num)\n{\n var cell;\n for(var i = 0; i < num; i++) {\n for(var j = 0; j < 7; j++) {\n var d = j + config.macros.calendar.firstday;\n if(d > 6) d = d - 7;\n cell = createTiddlyElement(row, "td", null, null, config.macros.calendar.daynames[d]);\n\n if(d == config.macros.calendar.firstweekend || d == config.macros.calendar.firstweekend+1)\n cell.className = "calendarWeekend";\n }\n }\n}\n//}}}\n\n//{{{\nfunction createCalendarDays(row, col, first, max, year, mon)\n{\n var i;\n for(i = 0; i < col; i++) {\n createTiddlyElement(row, "td", null, null, null);\n }\n var day = first;\n for(i = col; i < 7; i++) {\n var d = i + config.macros.calendar.firstday;\n if(d > 6) d = d - 7;\n var daycell = createTiddlyElement(row, "td", null, null, null);\n var isaWeekend = ((d == config.macros.calendar.firstweekend || d == (config.macros.calendar.firstweekend+1))? true:false);\n\n if(day > 0 && day <= max) {\n var celldate = new Date(year, mon, day);\n // ELS 2005.10.30: use <<date>> macro's showDate() function to create popup\n if (window.showDate) {\n showDate(daycell,celldate,"popup","DD","DD-MMM-YYYY",true, isaWeekend); \n } else {\n if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;\n var title = celldate.formatString(config.macros.calendar.tiddlerformat);\n if(calendarIsHoliday(celldate)) {\n daycell.style.background = config.macros.calendar.holidaybg;\n }\n if(window.findTiddlersWithReminders == null) {\n var link = createTiddlyLink(daycell, title, false);\n link.appendChild(document.createTextNode(day));\n } else {\n var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);\n }\n }\n }\n day++;\n }\n}\n//}}}\n\n// //We've clicked on a day in a calendar - create a suitable pop-up of options.\n// //The pop-up should contain:\n// // * a link to create a new entry for that date\n// // * a link to create a new reminder for that date\n// // * an <hr>\n// // * the list of reminders for that date\n//{{{\nfunction onClickCalendarDate(e)\n{\n var button = this;\n var date = button.getAttribute("title");\n var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));\n\n date = dat.formatString(config.macros.calendar.tiddlerformat);\n var popup = createTiddlerPopup(this);\n popup.appendChild(document.createTextNode(date));\n var newReminder = function() {\n var t = store.getTiddlers(date);\n displayTiddler(null, date, 2, null, null, false, false);\n if(t) {\n document.getElementById("editorBody" + date).value += "\sn<<reminder day:" + dat.getDate() +\n " month:" + (dat.getMonth()+1) +\n " year:" + (dat.getYear()+1900) + " title: >>";\n } else {\n document.getElementById("editorBody" + date).value = "<<reminder day:" + dat.getDate() +\n " month:" + (dat.getMonth()+1) +\n " year:" + (dat.getYear()+1900) + " title: >>";\n }\n };\n var link = createTiddlyButton(popup, "New reminder", null, newReminder); \n popup.appendChild(document.createElement("hr"));\n\n var t = findTiddlersWithReminders(dat, 0, null, null);\n for(var i = 0; i < t.length; i++) {\n link = createTiddlyLink(popup, t[i].tiddler, false);\n link.appendChild(document.createTextNode(t[i].tiddler));\n }\n}\n//}}}\n\n//{{{\nfunction calendarMaxDays(year, mon)\n{\n var max = config.macros.calendar.monthdays[mon];\n if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {\n max++;\n }\n return max;\n}\n//}}}\n\n//{{{\nfunction createCalendarDayRows(cal, year, mon)\n{\n var row = createTiddlyElement(cal, "tr", null, null, null);\n\n var first1 = (new Date(year, mon, 1)).getDay() -1 - config.macros.calendar.firstday;\n if(first1 < 0) first1 = first1 + 7;\n var day1 = -first1 + 1;\n var first2 = (new Date(year, mon+1, 1)).getDay() -1 - config.macros.calendar.firstday;\n if(first2 < 0) first2 = first2 + 7;\n var day2 = -first2 + 1;\n var first3 = (new Date(year, mon+2, 1)).getDay() -1 - config.macros.calendar.firstday;\n if(first3 < 0) first3 = first3 + 7;\n var day3 = -first3 + 1;\n\n var max1 = calendarMaxDays(year, mon);\n var max2 = calendarMaxDays(year, mon+1);\n var max3 = calendarMaxDays(year, mon+2);\n\n while(day1 <= max1 || day2 <= max2 || day3 <= max3) {\n row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;\n createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;\n createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;\n }\n}\n//}}}\n\n//{{{\nfunction createCalendarDayRowsSingle(cal, year, mon)\n{\n var row = createTiddlyElement(cal, "tr", null, null, null);\n\n var first1 = (new Date(year, mon, 1)).getDay() -1 - config.macros.calendar.firstday;\n if(first1 < 0) first1 = first1+ 7;\n var day1 = -first1 + 1;\n var max1 = calendarMaxDays(year, mon);\n\n while(day1 <= max1) {\n row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;\n }\n}\n//}}}\n\n// //ELS 2005.10.30: added styles\n//{{{\nsetStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { font-size:10pt; text-align:center; } .calendar { margin:0px !important; }", "calendarStyles");\n//}}}\n
/***\n''CheckboxPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman\nsource: http://www.TiddlyTools.com/#CheckboxPlugin \nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nAdd checkboxes to your tiddler content. Checkbox states can be preserved in the document by either automatically modifying the tiddler content or setting/removing tags on specified tiddlers, or they may be saved as local cookies by assigning an optional 'chkID' to the checkbox. Add custom javascript for programmatic initialization and onClick handling for any checkbox. Also provides access to checkbox DOM element data and tracks the checkbox state in TiddlyWiki's config.options[] internal data.\n\n!!!!!Usage\n<<<\nThe checkbox syntax, including all optional parameters, is contained inside a matched set of [ and ] brackets.\n{{{ [x=id(title:tag){init_script}{onclick_script}] }}}\n\nAn alternative syntax lets you place the optional parameters ''outside'' the [ and ] brackets, and is provided for backward-compatibility with existing content that may include checkbox definitions based on earlier releases of this plugin:\n{{{ [x]=id(title:tag){init_script}{onclick_script} }}}\n\n//{{{\n[ ]or[_] and [x]or[X]\n//}}}\nSimple checkboxes. The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked). When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets\n//{{{\n[x=id]\n//}}}\nAssign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}. If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value). If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.\n//{{{\n[x(title:tag)]\n//}}}\nInitializes and tracks the current checkbox state by setting or removing ("TogglyTagging") a particular tag value from a specified tiddler. If you omit the tiddler title (and the ":" separator), the specified tag is assigned to the current tiddler. If you omit the tag value, as in {{{(title:)}}}, the default tag, {{{checked}}}, is assumed. Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler. When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If a tiddler title named in the tag does not exist, the checkbox state defaults to //unselected//. When the checkbox is subsequently changed to //selected//, it will automatically (and silently) create the missing tiddler and then add the tag to it.\n//{{{\n[x{javascript}{javascript}]\n//}}}\nYou can define optional javascript code segments to add custom initialization and/or 'onClick' handling to a checkbox. The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to the default context-object, 'this'.\n\nThe first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state. The second code segment (if present) is executed whenever the checkbox is clicked, so that you can perform programmed responses or intercept and override the checkbox state based on complex logic using the TW core API or custom functions defined in plugins (e.g. testing a particular tiddler title to see if certain tags are set or setting some tags when the checkbox is clicked).\n\nNote: if you want to use the default checkbox initialization processing with a custom onclick function, use this syntax: {{{ [x=id{}{javascript}] }}} \n<<<\n!!!!!Examples\n<<<\n//{{{\n[X] label\n[_] label\n//}}}\nchecked and unchecked static default values\n[X] label\n[_] label\n\n//{{{\n[_=demo] label\n//}}}\ndocument-based value (id='demo', no cookie)\n[_=demo] label\n\n//{{{\n[_=chkDemo] label\n//}}}\ncookie-based value (id='chkDemo')\n[_=chkDemo] label\n\n//{{{\n[_(CheckboxPlugin:demotag)] toggle 'demotag'\n//}}}\ntag-based value (TogglyTagging)\n[_(CheckboxPlugin:demotag)] toggle 'demotag'\ncurrent tags: <script>return store.getTiddler(story.findContainingTiddler(place).id.substr(7)).tags.toString();</script>\n\n//{{{\n[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\n//}}}\ncustom init and onClick functions\n[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\n\nRetrieving option values:\nconfig.options['demo']=<script>return config.options['demo']?"true":"false";</script>\nconfig.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>\n\n!!!!!Installation\nimport (or copy/paste) the following tiddlers into your document:\n''CheckboxPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n2006.02.23 - 2.0.4\nwhen toggling tags, force refresh of the tiddler containing the checkbox.\n\n2006.02.23 - 2.0.3\nwhen toggling tags, force refresh of the 'tagged tiddler' so that tag-related tiddler content (such as "to-do" lists) can be re-rendered.\n\n2006.02.23 - 2.0.2\nwhen using tag-based storage, allow use [[ and ]] to quote tiddler or tag names that contain spaces:\n"""[x([[Tiddler with spaces]]:[[tag with spaces]])]"""\n\n2006.01.10 - 2.0.1\nwhen toggling tags, force refresh of the 'tagging tiddler'. For example, if you toggle the "systemConfig" tag on a plugin, the corresponding "systemConfig" TIDDLER will be automatically refreshed (if currently displayed), so that the 'tagged' list in that tiddler will remain up-to-date.\n\n2006.01.04 - 2.0.0\nupdate for ~TW2.0\n\n2005.12.27 - 1.1.2\nFix lookAhead regExp handling for """[x=id]""", which had been including the "]" in the extracted ID. \nAdded check for "chk" prefix on ID before calling saveOptionCookie()\n\n2005.12.26 - 1.1.2\nCorrected use of toUpperCase() in tiddler re-write code when comparing """[X]""" in tiddler content with checkbox state. Fixes a problem where simple checkboxes could be set, but never cleared.\n\n2005.12.26 - 1.1.0\nRevise syntax so all optional parameters are included INSIDE the [ and ] brackets. Backward compatibility with older syntax is supported, so content changes are not required when upgrading to the current version of this plugin. Based on a suggestion by GeoffSlocock\n\n2005.12.25 - 1.0.0\nadded support for tracking checkbox state using tags ("TogglyTagging")\nRevised version number for official post-beta release.\n\n2005.12.08 - 0.9.3\nsupport separate 'init' and 'onclick' function definitions.\n\n2005.12.08 - 0.9.2\nclean up lookahead pattern\n\n2005.12.07 - 0.9.1\nonly update tiddler source content if checkbox state is actually different. Eliminates unnecessary tiddler changes (and 'unsaved changes' warnings)\n\n2005.12.07 - 0.9.0\ninitial BETA release\n<<<\n!!!!!Credits\n<<<\nThis feature was created by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.CheckboxPlugin = {major: 2, minor: 0, revision:4 , date: new Date(2006,2,23)};\n//}}}\n\n// // 1.2.x compatibility\n//{{{\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n//{{{\nconfig.formatters.push( {\n name: "checkbox",\n match: "\s\s[[xX_ ][\s\s]\s\s=\s\s(\s\s{]",\n lookahead: "\s\s[([xX_ ])(\s\s])?(=[^\s\ss\s\s(\s\s]{]+)?(\s\s([^\s\s)]*\s\s))?({[^}]*})?({[^}]*})?(\s\s])?",\n handler: function(w)\n {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n // get params\n var checked=lookaheadMatch[1];\n var id=lookaheadMatch[3];\n var tag=lookaheadMatch[4];\n var fn_init=lookaheadMatch[5];\n var fn_click=lookaheadMatch[6];\n // create checkbox element\n var c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick=onClickCheckbox;\n c.srcpos=w.matchStart+1; // remember location of "X"\n w.output.appendChild(c);\n // set default state\n c.checked=(checked.toUpperCase()=="X");\n // get/set state by ID\n if (id) {\n c.id=id.substr(1); // trim off leading "="\n if (config.options[c.id]!=undefined)\n c.checked=config.options[c.id];\n else\n config.options[c.id]=c.checked;\n }\n // get/set state by tag\n if (tag) {\n c.tiddler=story.findContainingTiddler(w.output).id.substr(7);\n c.tag=tag.substr(1,tag.length-2).trim(); // trim off parentheses\n var pos=c.tag.indexOf(":");\n if (pos==0) { c.tag=tag.substr(1); }\n if (pos>0) { c.tiddler=c.tag.substr(0,pos).replace(/\s[\s[/g,"").replace(/\s]\s]/g,""); c.tag=c.tag.substr(pos+1); }\n c.tag.replace(/\s[\s[/g,"").replace(/\s]\s]/g,"");\n if (!c.tag.length) c.tag="checked";\n var t=store.getTiddler(c.tiddler);\n c.checked = (t && t.tags)?(t.tags.find(c.tag)!=null):false;\n }\n if (fn_init) c.fn_init=fn_init.trim().substr(1,fn_init.length-2); // trim off surrounding { and } delimiters\n if (fn_click) c.fn_click=fn_click.trim().substr(1,fn_click.length-2);\n c.onclick(); // compute initial state and save in tiddler/config/cookie\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n }\n)\n//}}}\n\n//{{{\nfunction onClickCheckbox()\n{\n if (this.fn_init)\n // custom function hook to set initial state (run only once)\n { try { eval(this.fn_init); this.fn_init=null; } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }\n else if (this.fn_click)\n // custom function hook to override or react to changes in checkbox state\n { try { eval(this.fn_click) } catch(e) { displayMessage("Checkbox click error: "+e.toString()); } }\n if (this.id)\n // save state in config AND cookie (only when ID starts with 'chk')\n { config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }\n if ((!this.id || this.id.substr(0,3)!="chk") && !this.tag) {\n // save state in tiddler content only if not using cookie or tag tracking\n var t=store.getTiddler(story.findContainingTiddler(this).id.substr(7));\n if (this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed\n t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);\n store.setDirty(true);\n }\n }\n if (this.tag) {\n var t=store.getTiddler(this.tiddler);\n if (!t) { t=(new Tiddler()); t.set(this.tiddler,"",config.options.txtUserName,(new Date()),null); store.addTiddler(t); } \n var tagged=(t.tags && t.tags.find(this.tag)!=null);\n if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }\n if (!this.checked && tagged) { t.tags.splice(t.tags.find(this.tag),1); store.setDirty(true); }\n // if tag state has been changed, force a display update\n if (this.checked!=tagged) {\n story.refreshTiddler(this.tiddler,null,true); // the TAGGED tiddler\n story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler\n if (t=store.getTiddler(story.findContainingTiddler(this).id.substr(7)))\n if (t.title!=this.tiddler) story.refreshTiddler(t.title,null,true); // the tiddler CONTAINING the checkbox\n }\n }\n return true;\n}\n//}}}
/***\nCopyTiddlerPlugin\nAuthor: TimMorgan\nSource: http://ziddlywiki.org/#CopyTiddlerPlugin\n\nadds a "copy" option to duplicate a tiddler\n***/\n//{{{\nconfig.shadowTiddlers.EditTemplate = "<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler copyTiddler deleteTiddler'></div>\sn<div class='title' macro='view title'></div>\sn<div class='editor' macro='edit title'></div>\sn<div class='editor' macro='edit text'></div>\sn<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>";\n\nconfig.commands.copyTiddler = {\n text: 'copy',\n tooltip: 'Make a copy of this tiddler',\n handler: function(event,src,title) {\n story.displayTiddler(null,title,DEFAULT_VIEW_TEMPLATE);\n var tiddler = store.fetchTiddler(title);\n var newTitle = 'Copy of ' + title;\n var newTiddler = store.createTiddler(newTitle);\n newTiddler.text = tiddler.text;\n newTiddler.tags = tiddler.tags;\n story.displayTiddler(null,newTitle,DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(newTitle,"title");\n return false;\n }\n};\n//}}}
Create OSUEvents tiddler with OSU reminders in it\n* See USHolidays for an example
! Preferred Method\n# Create new Tiddlers directly in the MainMenu by typing them in the MainMenu Tiddler.\n\n! Method 2\n# Click CreateNewTiddler in the MainMenu.\n# Edit the title and content to create.\n\n! Method 3\n# Enter a mixed-case WikiWord (or double square brackets for NonWikiWordLinks) into an existing Tiddler.\n# Click on the new italicized "empty" Tiddler to edit.\n# When you are done editing, the Tiddler is created.
You can specify your own styles -- that will persist even if you upgrade GTDTW -- in the new special tiddler, StyleSheet.\n\nStyleSheet is pre-populated so you can see how it works. If you want to print to different sizes of paper, or resize the base fonts, or use different fonts, the body style rules are where you'd start. If you are upgrading your version of GTDTW, you'll need to create and populate the StyleSheet for yourself.\n\nStyleSheet suffers from a bug that truncates long entries with many non-alphanumeric characters, so if you try to put the entire set off styles in there, it probably won't work.
This is a test.\n\n<part SpecialExample>\n! Daily Reminders\n<<showReminders format:"|[x(TIDDLER:done)]|DIFF|TITLE|TIDDLER|">>\n</part>\n<html><a onClick="onClickAction()">Click here to reset daily reminders</a></html>\n<script>\n// This function contributed by Eric Shulman\nwindow.onClickAction = function() {\nvar dailyTiddlers = store.getTaggedTiddlers('dailyreminder');\nfor( var i = 0; i < dailyTiddlers.length; ++i )\n{\n if( dailyTiddlers[i].tags.contains("done") )\n dailyTiddlers[i].tags.splice(dailyTiddlers[i].tags.find("done"), 1);\n}\nstore.setDirty(true); // so TW knows it has to save now\n\nstory.forEachTiddler(function(title,element) {\n story.refreshTiddler(title,false,true)\n});\nreturn false;\n}\n\nif (!window.story) window.story=window;\n\nvar nowDate = new Date();\nvar thisTiddler=story.findContainingTiddler(place);\n\nif( thisTiddler )\n{\n var thisTiddler = store.getTiddler(thisTiddler.id.substr(7));\n\n if( thisTiddler )\n {\n var theseTags = thisTiddler.tags;\n for( var i = 0; i < theseTags.length; ++i )\n {\n var result = theseTags[i].match(/dailytag(\sd+)/);\n if( result )\n {\n if( result[1] != nowDate.getDate() )\n {\nthisTiddler.tags.splice(thisTiddler.tags.find(result[1]), 1);\n\nthisTiddler.tags.push('dailytag' + nowDate.getDate() );\n window.onClickAction();\n }\n break;\n }\n }\n }\n}\n</script>
/***\n|''Name:''|DataTiddlerPlugin|\n|''Version:''|1.0.4 (2006-02-05)|\n|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|1.2.38+, 2.0|\n|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|\n!Description\nEnhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).\n\nSuch tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers. \n\n''//Example: "Table with all December Expenses"//''\n{{{\n<<forEachTiddler\n where\n 'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\sn"'\n>>\n}}}\n//(This assumes that expenses are stored in tiddlers tagged with "expense".)//\n<<forEachTiddler\n where\n 'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\sn"'\n>>\nFor other examples see DataTiddlerExamples.\n\n\n\n\n''Access and Modify Tiddler Data''\n\nYou can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields. \n\nThese values can be accessed and modified through the following Tiddler methods:\n|!Method|!Example|!Description|\n|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|\n|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|\n|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|\n|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|\n|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|\n\nAlternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.\n|!Method|!Description|\n|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|\n|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|\n|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|\n|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|\n|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|\n//(For details on the various functions see the detailed comments in the source code.)//\n\n\n''Data Representation in a Tiddler''\n\nThe data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]]. \n\n//''Data Section Example:''//\n{{{\n<data>{"isVIP":true,"user":"John Brown","age":34}</data>\n}}}\n\nThe data section is not displayed when viewing the tiddler (see also "The showData Macro").\n\nBeside the data section a tiddler may have all kind of other content.\n\nTypically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.\n\n\n''Saving Changes''\n\nThe "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.\n\n\n''Notifications''\n\nNo notifications are sent when a tiddler's data value is changed through the "setData" methods. \n\n''Escape Data Section''\nIn case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.\n\n\n''The showData Macro''\n\nBy default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:\n\n''Syntax:'' \n|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|\n|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|\n|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n\n\n!Revision history\n* v1.0.4 (2006-02-05)\n** Bugfix: showData fails in TiddlyWiki 2.0\n* v1.0.3 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.2 (2005-12-22)\n** Enhancements:\n*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.\n*** Improved (JSON) error messages.\n** Bugs fixed: \n*** References are not updated when using the DataTiddler.\n*** Changes to compound objects are not always saved.\n*** "~</data>" is not rendered correctly (expected "</data>")\n* v1.0.1 (2005-12-13)\n** Features: \n*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed\n** Bugs fixed: \n*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)\n* v1.0.0 (2005-12-12)\n** initial version\n\n!Code\n***/\n//{{{\n//============================================================================\n//============================================================================\n// DataTiddlerPlugin\n//============================================================================\n//============================================================================\n\n// Ensure that the DataTiddler Plugin is only installed once.\n//\nif (!version.extensions.DataTiddlerPlugin) {\n\n\n\nversion.extensions.DataTiddlerPlugin = {\n major: 1, minor: 0, revision: 4,\n date: new Date(2006, 2, 5), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"\n};\n\n// For backward compatibility with v1.2.x\n//\nif (!window.story) window.story=window; \nif (!TiddlyWiki.prototype.getTiddler) TiddlyWiki.prototype.getTiddler = function(title) { return t = this.tiddlers[title]; return (t != undefined && t instanceof Tiddler) ? t : null; } \n\n//============================================================================\n// DataTiddler Class\n//============================================================================\n\n// ---------------------------------------------------------------------------\n// Configurations and constants \n// ---------------------------------------------------------------------------\n\nfunction DataTiddler() {\n}\n\nDataTiddler = {\n // Function to stringify a JavaScript value, producing the text for the data section content.\n // (Must match the implementation of DataTiddler.parse.)\n //\n stringify : null,\n \n\n // Function to parse the text for the data section content, producing a JavaScript value.\n // (Must match the implementation of DataTiddler.stringify.)\n //\n parse : null\n};\n\n// Ensure access for IE\nwindow.DataTiddler = DataTiddler;\n\n// ---------------------------------------------------------------------------\n// Data Accessor and Mutator\n// ---------------------------------------------------------------------------\n\n\n// Returns the value of the given data field of the tiddler.\n// When no such field is defined or its value is undefined\n// the defaultValue is returned.\n// \n// @param tiddler either a tiddler name or a tiddler\n//\nDataTiddler.getData = function(tiddler, field, defaultValue) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.getTiddlerDataValue(t, field, defaultValue);\n}\n\n\n// Sets the value of the given data field of the tiddler to\n// the value. When the value is equal to the defaultValue\n// no value is set (and the field is removed)\n//\n// Changing data of a tiddler will not trigger notifications.\n// \n// @param tiddler either a tiddler name or a tiddler\n//\nDataTiddler.setData = function(tiddler, field, value, defaultValue) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler+ "("+t+")";\n }\n\n DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);\n}\n\n\n// Returns the data object of the tiddler, with a property for every field.\n//\n// The properties of the returned data object may only be read and\n// not be modified. To modify the data use DataTiddler.setData(...) \n// or the corresponding Tiddler method.\n//\n// If no data section is defined a new (empty) object is returned.\n//\n// @param tiddler either a tiddler name or a Tiddler\n//\nDataTiddler.getDataObject = function(tiddler) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.getTiddlerDataObject(t);\n}\n\n// Returns the text of the content of the data section of the tiddler.\n//\n// When no data section is defined for the tiddler null is returned \n//\n// @param tiddler either a tiddler name or a Tiddler\n// @return [may be null]\n//\nDataTiddler.getDataText = function(tiddler) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.readDataSectionText(t);\n}\n\n\n// ---------------------------------------------------------------------------\n// Internal helper methods (must not be used by code from outside this plugin)\n// ---------------------------------------------------------------------------\n\n// Internal.\n//\n// The original JSONError is not very user friendly, \n// especially it does not define a toString() method\n// Therefore we extend it here.\n//\nDataTiddler.extendJSONError = function(ex) {\n if (ex.name == 'JSONError') {\n ex.toString = function() {\n return ex.name + ": "+ex.message+" ("+ex.text+")";\n }\n }\n return ex;\n}\n\n// Internal.\n//\n// @param t a Tiddler\n//\nDataTiddler.getTiddlerDataObject = function(t) {\n if (t.dataObject == undefined) {\n var data = DataTiddler.readData(t);\n t.dataObject = (data) ? data : {};\n }\n \n return t.dataObject;\n}\n\n\n// Internal.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {\n var value = DataTiddler.getTiddlerDataObject(tiddler)[field];\n return (value == undefined) ? defaultValue : value;\n}\n\n\n// Internal.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {\n var data = DataTiddler.getTiddlerDataObject(tiddler);\n var oldValue = data[field];\n \n if (value == defaultValue) {\n if (oldValue != undefined) {\n delete data[field];\n DataTiddler.save(tiddler);\n }\n return;\n }\n data[field] = value;\n DataTiddler.save(tiddler);\n}\n\n// Internal.\n//\n// Reads the data section from the tiddler's content and returns its text\n// (as a String).\n//\n// Returns null when no data is defined.\n//\n// @param tiddler a Tiddler\n// @return [may be null]\n//\nDataTiddler.readDataSectionText = function(tiddler) {\n var matches = DataTiddler.getDataTiddlerMatches(tiddler);\n if (matches == null || !matches[2]) {\n return null;\n }\n return matches[2];\n}\n\n// Internal.\n//\n// Reads the data section from the tiddler's content and returns it\n// (as an internalized object).\n//\n// Returns null when no data is defined.\n//\n// @param tiddler a Tiddler\n// @return [may be null]\n//\nDataTiddler.readData = function(tiddler) {\n var text = DataTiddler.readDataSectionText(tiddler);\n try {\n return text ? DataTiddler.parse(text) : null;\n } catch(ex) {\n throw DataTiddler.extendJSONError(ex);\n }\n}\n\n// Internal.\n// \n// Returns the serialized text of the data of the given tiddler, as it\n// should be stored in the data section.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.getDataTextOfTiddler = function(tiddler) {\n var data = DataTiddler.getTiddlerDataObject(tiddler);\n return DataTiddler.stringify(data);\n}\n\n\n// Internal.\n// \nDataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {\n var index = s.indexOf(subString, startIndex);\n while ((index > 0) && (s[index-1] == '~')) { \n index = s.indexOf(subString, index+1);\n }\n return index;\n}\n\n// Internal.\n//\nDataTiddler.getDataSectionInfo = function(text) {\n // Special care must be taken to handle "<data>" and "</data>" texts inside\n // a data section. \n // Also take care not to use an escaped <data> (i.e. "~<data>") as the start \n // of a data section. (Same for </data>)\n\n // NOTE: we are explicitly searching for a data section that contains a JSON\n // string, i.e. framed with braces. This way we are little bit more robust in\n // case the tiddler contains unescaped texts "<data>" or "</data>". This must\n // be changed when using a different stringifier.\n\n var startTagText = "<data>{";\n var endTagText = "}</data>";\n\n var startPos = 0;\n\n // Find the first not escaped "<data>".\n var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);\n if (startDataTagIndex < 0) {\n return null;\n }\n\n // Find the *last* not escaped "</data>".\n var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);\n if (endDataTagIndex < 0) {\n return null;\n }\n var nextEndDataTagIndex;\n while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {\n endDataTagIndex = nextEndDataTagIndex;\n };\n\n return {\n prefixEnd: startDataTagIndex, \n dataStart: startDataTagIndex+(startTagText.length)-1, \n dataEnd: endDataTagIndex, \n suffixStart: endDataTagIndex+(endTagText.length)\n };\n}\n\n// Internal.\n// \n// Returns the "matches" of a content of a DataTiddler on the\n// "data" regular expression. Return null when no data is defined\n// in the tiddler content.\n//\n// Group 1: text before data section (prefix)\n// Group 2: content of data section\n// Group 3: text behind data section (suffix)\n//\n// @param tiddler a Tiddler\n// @return [may be null] null when the tiddler contains no data section, otherwise see above.\n//\nDataTiddler.getDataTiddlerMatches = function(tiddler) {\n var text = tiddler.text;\n var info = DataTiddler.getDataSectionInfo(text);\n if (!info) {\n return null;\n }\n\n var prefix = text.substr(0,info.prefixEnd);\n var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);\n var suffix = text.substr(info.suffixStart);\n \n return [text, prefix, data, suffix];\n}\n\n\n// Internal.\n//\n// Saves the data in a <data> block of the given tiddler (as a minor change). \n//\n// The "chkAutoSave" and "chkForceMinorUpdate" options are respected. \n// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.\n//\n// Notifications are not send. \n//\n// This method should only be called when the data really has changed. \n//\n// @param tiddler\n// the tiddler to be saved.\n//\nDataTiddler.save = function(tiddler) {\n\n var matches = DataTiddler.getDataTiddlerMatches(tiddler);\n\n var prefix;\n var suffix;\n if (matches == null) {\n prefix = tiddler.text;\n suffix = "";\n } else {\n prefix = matches[1];\n suffix = matches[3];\n }\n\n var dataText = DataTiddler.getDataTextOfTiddler(tiddler);\n var newText = \n (dataText != null) \n ? prefix + "<data>" + dataText + "</data>" + suffix\n : prefix + suffix;\n if (newText != tiddler.text) {\n // make the change in the tiddlers text\n \n // ... see DataTiddler.MyTiddlerChangedFunction\n tiddler.isDataTiddlerChange = true;\n \n // ... do the action change\n tiddler.set(\n tiddler.title,\n newText,\n config.options.txtUserName, \n config.options.chkForceMinorUpdate? undefined : new Date(),\n tiddler.tags);\n\n // ... see DataTiddler.MyTiddlerChangedFunction\n delete tiddler.isDataTiddlerChange;\n\n // Mark the store as dirty.\n store.dirty = true;\n \n // AutoSave if option is selected\n if(config.options.chkAutoSave) {\n saveChanges();\n }\n }\n}\n\n// Internal.\n//\nDataTiddler.MyTiddlerChangedFunction = function() {\n // Remove the data object from the tiddler when the tiddler is changed\n // by code other than DataTiddler code. \n //\n // This is necessary since the data object is just a "cached version" \n // of the data defined in the data section of the tiddler and the \n // "external" change may have changed the content of the data section.\n // Thus we are not sure if the data object reflects the data section \n // contents. \n // \n // By deleting the data object we ensure that the data object is \n // reconstructed the next time it is needed, with the data defined by\n // the data section in the tiddler's text.\n \n // To indicate that a change is a "DataTiddler change" a temporary\n // property "isDataTiddlerChange" is added to the tiddler.\n if (this.dataObject && !this.isDataTiddlerChange) {\n delete this.dataObject;\n }\n \n // call the original code.\n DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);\n}\n\n\n//============================================================================\n// Formatters\n//============================================================================\n\n// This formatter ensures that "~<data>" is rendered as "<data>". This is used to \n// escape the "<data>" of a data section, just in case someone really wants to use\n// "<data>" as a text in a tiddler and not start a data section.\n//\n// Same for </data>.\n//\nconfig.formatters.push( {\n name: "data-escape",\n match: "~<\s\s/?data>",\n\n handler: function(w) {\n w.outputText(w.output,w.matchStart + 1,w.nextMatch);\n }\n} )\n\n\n// This formatter ensures that <data>...</data> sections are not rendered.\n//\nconfig.formatters.push( {\n name: "data",\n match: "<data>",\n\n handler: function(w) {\n var info = DataTiddler.getDataSectionInfo(w.source);\n if (info && info.prefixEnd == w.matchStart) {\n w.nextMatch = info.suffixStart;\n } else {\n w.outputText(w.output,w.matchStart,w.nextMatch);\n }\n }\n} )\n\n\n//============================================================================\n// Tiddler Class Extension\n//============================================================================\n\n// "Hijack" the changed method ---------------------------------------------------\n\nDataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;\nTiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;\n\n// Define accessor methods -------------------------------------------------------\n\n// Returns the value of the given data field of the tiddler. When no such field \n// is defined or its value is undefined the defaultValue is returned.\n//\n// When field is undefined (or null) the data object is returned. (See \n// DataTiddler.getDataObject.)\n//\n// @param field [may be null, undefined]\n// @param defaultValue [may be null, undefined]\n// @return [may be null, undefined]\n//\nTiddler.prototype.data = function(field, defaultValue) {\n return (field) \n ? DataTiddler.getTiddlerDataValue(this, field, defaultValue)\n : DataTiddler.getTiddlerDataObject(this);\n}\n\n// Sets the value of the given data field of the tiddler to the value. When the \n// value is equal to the defaultValue no value is set (and the field is removed).\n//\n// @param value [may be null, undefined]\n// @param defaultValue [may be null, undefined]\n//\nTiddler.prototype.setData = function(field, value, defaultValue) {\n DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);\n}\n\n\n//============================================================================\n// showData Macro\n//============================================================================\n\nconfig.macros.showData = {\n // Standard Properties\n label: "showData",\n prompt: "Display the values stored in the data section of the tiddler"\n}\n\nconfig.macros.showData.handler = function(place,macroName,params) {\n // --- Parsing ------------------------------------------\n\n var i = 0; // index running over the params\n // Parse the optional "JSON"\n var showInJSONFormat = false;\n if ((i < params.length) && params[i] == "JSON") {\n i++;\n showInJSONFormat = true;\n }\n \n var tiddlerName = story.findContainingTiddler(place).id.substr(7);\n if (i < params.length) {\n tiddlerName = params[i]\n i++;\n }\n\n // --- Processing ------------------------------------------\n try {\n if (showInJSONFormat) {\n this.renderDataInJSONFormat(place, tiddlerName);\n } else {\n this.renderDataAsTable(place, tiddlerName);\n }\n } catch (e) {\n this.createErrorElement(place, e);\n }\n}\n\nconfig.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {\n var text = DataTiddler.getDataText(tiddlerName);\n if (text) {\n createTiddlyElement(place,"pre",null,null,text);\n }\n}\n\nconfig.macros.showData.renderDataAsTable = function(place,tiddlerName) {\n var text = "|!Name|!Value|\sn";\n var data = DataTiddler.getDataObject(tiddlerName);\n if (data) {\n for (var i in data) {\n var value = data[i];\n text += "|"+i+"|"+DataTiddler.stringify(value)+"|\sn";\n }\n }\n \n wikify(text, place);\n}\n\n\n// Internal.\n//\n// Creates an element that holds an error message\n// \nconfig.macros.showData.createErrorElement = function(place, exception) {\n var message = (exception.description) ? exception.description : exception.toString();\n return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);\n}\n\n// ---------------------------------------------------------------------------\n// Stylesheet Extensions (may be overridden by local StyleSheet)\n// ---------------------------------------------------------------------------\n//\nsetStylesheet(\n ".showDataError{color: #ffffff;background-color: #880000;}",\n "showData");\n\n\n} // of "install only once"\n//}}}\n\n\n\n/***\n!JSON Code, used to serialize the data\n//(embedded in the plugin tiddler to make it selfcontained)//\n***/\n//{{{\n/*\nCopyright (c) 2005 JSON.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe Software shall be used for Good, not Evil.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n/*\n The global object JSON contains two methods.\n\n JSON.stringify(value) takes a JavaScript value and produces a JSON text.\n The value must not be cyclical.\n\n JSON.parse(text) takes a JSON text and produces a JavaScript value. It will\n throw a 'JSONError' exception if there is an error.\n*/\nvar JSON = {\n copyright: '(c)2005 JSON.org',\n license: 'http://www.crockford.com/JSON/license.html',\n/*\n Stringify a JavaScript value, producing a JSON text.\n*/\n stringify: function (v) {\n var a = [];\n\n/*\n Emit a string.\n*/\n function e(s) {\n a[a.length] = s;\n }\n\n/*\n Convert a value.\n*/\n function g(x) {\n var c, i, l, v;\n\n switch (typeof x) {\n case 'object':\n if (x) {\n if (x instanceof Array) {\n e('[');\n l = a.length;\n for (i = 0; i < x.length; i += 1) {\n v = x[i];\n if (typeof v != 'undefined' &&\n typeof v != 'function') {\n if (l < a.length) {\n e(',');\n }\n g(v);\n }\n }\n e(']');\n return;\n } else if (typeof x.toString != 'undefined') {\n e('{');\n l = a.length;\n for (i in x) {\n v = x[i];\n if (x.hasOwnProperty(i) &&\n typeof v != 'undefined' &&\n typeof v != 'function') {\n if (l < a.length) {\n e(',');\n }\n g(i);\n e(':');\n g(v);\n }\n }\n return e('}');\n }\n }\n e('null');\n return;\n case 'number':\n e(isFinite(x) ? +x : 'null');\n return;\n case 'string':\n l = x.length;\n e('"');\n for (i = 0; i < l; i += 1) {\n c = x.charAt(i);\n if (c >= ' ') {\n if (c == '\s\s' || c == '"') {\n e('\s\s');\n }\n e(c);\n } else {\n switch (c) {\n case '\sb':\n e('\s\sb');\n break;\n case '\sf':\n e('\s\sf');\n break;\n case '\sn':\n e('\s\sn');\n break;\n case '\sr':\n e('\s\sr');\n break;\n case '\st':\n e('\s\st');\n break;\n default:\n c = c.charCodeAt();\n e('\s\su00' + Math.floor(c / 16).toString(16) +\n (c % 16).toString(16));\n }\n }\n }\n e('"');\n return;\n case 'boolean':\n e(String(x));\n return;\n default:\n e('null');\n return;\n }\n }\n g(v);\n return a.join('');\n },\n/*\n Parse a JSON text, producing a JavaScript value.\n*/\n parse: function (text) {\n var p = /^\ss*(([,:{}\s[\s]])|"(\s\s.|[^\sx00-\sx1f"\s\s])*"|-?\sd+(\s.\sd*)?([eE][+-]?\sd+)?|true|false|null)\ss*/,\n token,\n operator;\n\n function error(m, t) {\n throw {\n name: 'JSONError',\n message: m,\n text: t || operator || token\n };\n }\n\n function next(b) {\n if (b && b != operator) {\n error("Expected '" + b + "'");\n }\n if (text) {\n var t = p.exec(text);\n if (t) {\n if (t[2]) {\n token = null;\n operator = t[2];\n } else {\n operator = null;\n try {\n token = eval(t[1]);\n } catch (e) {\n error("Bad token", t[1]);\n }\n }\n text = text.substring(t[0].length);\n } else {\n error("Unrecognized token", text);\n }\n } else {\n token = operator = undefined;\n }\n }\n\n\n function val() {\n var k, o;\n switch (operator) {\n case '{':\n next('{');\n o = {};\n if (operator != '}') {\n for (;;) {\n if (operator || typeof token != 'string') {\n error("Missing key");\n }\n k = token;\n next();\n next(':');\n o[k] = val();\n if (operator != ',') {\n break;\n }\n next(',');\n }\n }\n next('}');\n return o;\n case '[':\n next('[');\n o = [];\n if (operator != ']') {\n for (;;) {\n o.push(val());\n if (operator != ',') {\n break;\n }\n next(',');\n }\n }\n next(']');\n return o;\n default:\n if (operator !== null) {\n error("Missing value");\n }\n k = token;\n next();\n return k;\n }\n }\n next();\n return val();\n }\n};\n//}}}\n/***\n!Setup the data serialization\n***/\n//{{{\nDataTiddler.format = "JSON";\nDataTiddler.stringify = JSON.stringify;\nDataTiddler.parse = JSON.parse;\n\n//}}}
/***\n''Date Plugin for TiddlyWiki version 2.x''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#DatePlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n^^last update: <<date tiddler "DDD, MMM DDth, YYYY hh:0mm:0ss">>^^\n\nThere are quite a few calendar generators, reminders, to-do lists, 'dated tiddlers' journals, blog-makers and GTD-like schedule managers that have been built around TW. While they all have different purposes, and vary in format, interaction, and style, in one way or another each of these plugins displays and/or uses date-based information to make finding, accessing and managing relevant tiddlers easier. This plugin provides a general approach to embedding dates and date-based links/menus within tiddler content.\n\nYou can ''specify a date using a combination of year, month, and day number values or mathematical expressions (such as "Y+1" or "D+30")'', and then just display it as formatted date text, or create a ''link to a 'dated tiddler''' for quick blogging, or create a ''popup menu'' containing the dated tiddler link plus links to ''tiddlers that were changed'' as well as any ''scheduled reminders'' for that date.\n!!!!!Usage\n<<<\nWhen installed, this plugin defines a macro: {{{<<date [mode] [date] [format] [linkformat]>>}}}. All of the macro parameters are optional and, in it's simplest form, {{{<<date>>}}}, it is equivalent to the ~TiddlyWiki core macro, {{{<<today>>}}}.\n\nHowever, where {{{<<today>>}}} simply inserts the current date/time in a predefined format (or custom format, using {{{<<today [format]>>}}}), the {{{<<date>>}}} macro's parameters take it much further than that:\n* [mode] is either ''display'', ''link'' or ''popup''. If omitted, it defaults to ''display''. This param let's you select between simply displaying a formatted date, or creating a link to a specific 'date titled' tiddler or a popup menu containing a dated tiddler link, plus links to changes and reminders.\n* [date] lets you enter ANY date (not just today) as ''year, month, and day values or simple mathematical expressions'' using pre-defined variables, Y, M, and D for the current year, month and day, repectively. You can display the modification date of the current tiddler by using the keyword: ''tiddler'' in place of the year, month and day parameters. Use ''tiddler://name-of-tiddler//'' to display the modification date of a specific tiddler. You can also use keywords ''today'' or ''filedate'' to refer to these //dynamically changing// date/time values. \n* [format] and [linkformat] uses standard ~TiddlyWiki date formatting syntax. The default is "YYYY.0MM.0DD"\n>^^''DDD'' - day of week in full (eg, "Monday"), ''DD'' - day of month, ''0DD'' - adds leading zero^^\n>^^''MMM'' - month in full (eg, "July"), ''MM'' - month number, ''0MM'' - adds leading zero^^\n>^^''YYYY'' - full year, ''YY'' - two digit year, ''hh'' - hours, ''mm'' - minutes, ''ss'' - seconds^^\n>^^//note: use of hh, mm or ss format codes is only supported with ''tiddler'', ''today'' or ''filedate'' values//^^\n* [linkformat] - specify an alternative date format so that the title of a 'dated tiddler' link can have a format that differs from the date's displayed format\n\nIn addition to the macro syntax, DatePlugin also provides a public javascript API so that other plugins that work with dates (such as calendar generators, etc.) can quickly incorporate date formatted links or popups into their output:\n\n''{{{showDate(place, date, mode, format, linkformat, autostyle, weekend)}}}'' \n\nNote that in addition to the parameters provided by the macro interface, the javascript API also supports two optional true/false parameters:\n* [autostyle] - when true, the font/background styles of formatted dates are automatically adjusted to show the date's status: 'today' is boxed, 'changes' are bold, 'reminders' are underlined, while weekends and holidays (as well as changes and reminders) can each have a different background color to make them more visibly distinct from each other.\n* [weekend] - true indicates a weekend, false indicates a weekday. When this parameter is omitted, the plugin uses internal defaults to automatically determine when a given date falls on a weekend.\n<<<\n!!!!!Examples\n<<<\nThe current date: <<date>>\nThe current time: <<date today "0hh:0mm:0ss">>\nToday's blog: <<date link today "DDD, MMM DDth, YYYY">>\nRecent blogs/changes/reminders: <<date popup Y M D-1 "yesterday">> <<date popup today "today">> <<date popup Y M D+1 "tomorrow">>\nThe first day of next month will be a <<date Y M+1 1 "DDD">>\nThis tiddler (DatePlugin) was last updated on: <<date tiddler "DDD, MMM DDth, YYYY">>\nThe SiteUrl was last updated on: <<date tiddler:SiteUrl "DDD, MMM DDth, YYYY">>\nThis document was last saved on <<date filedate "DDD, MMM DDth, YYYY at 0hh:0mm:0ss">>\n<<date 2006 07 24 "MMM DDth, YYYY">> will be a <<date 2006 07 24 "DDD">>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''DatePlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.02.05 [2.0.4]''\nadded var to variables that were unintentionally global. Avoids FireFox 1.5.0.1 crash bug when referencing global variables\n''2006.01.18 [2.0.3]''\nIn 1.2.x the tiddler editor's text area control was given an element ID=("tiddlerBody"+title), so that it was easy to locate this field and programmatically modify its content. With the addition of configuration templates in 2.x, the textarea no longer has an ID assigned. To find this control we now look through all the child nodes of the tiddler editor to locate a "textarea" control where attribute("edit") equals "text", and then append the new reminder to the contents of that control.\n''2006.01.11 [2.0.2]''\ncorrect 'weekend' override detection logic in showDate()\n''2006.01.10 [2.0.1]''\nallow custom-defined weekend days (default defined in config.macros.date.weekend[] array)\nadded flag param to showDate() API to override internal weekend[] array\n''2005.12.27 [2.0.0]''\nUpdate for TW2.0\nAdded parameter handling for 'linkformat'\n''2005.12.21 [1.2.2]''\nFF's date.getYear() function returns 105 (for the current year, 2005). When calculating a date value from Y M and D expressions, the plugin adds 1900 to the returned year value get the current year number. But IE's date.getYear() already returns 2005. As a result, plugin calculated date values on IE were incorrect (e.g., 3905 instead of 2005). Adding +1900 is now conditional so the values will be correct on both browsers.\n''2005.11.07 [1.2.1]''\nadded support for "tiddler" dynamic date parameter\n''2005.11.06 [1.2.0]''\nadded support for "tiddler:title" dynamic date parameter\n''2005.11.03 [1.1.2]''\nwhen a reminder doesn't have a specified title parameter, use the title of the tiddler that contains the reminder as "fallback" text in the popup menu. Based on a suggestion from BenjaminKudria.\n''2005.11.03 [1.1.1]''\nTemporarily bypass hasReminders() logic to avoid excessive overhead from generating the indexReminders() cache. While reminders can still appear in the popup menu, they just won't be indicated by auto-styling the date number that is displayed. This single change saves approx. 60% overhead (5 second delay reduced to under 2 seconds).\n''2005.11.01 [1.1.0]''\ncorrected logic in hasModifieds() and hasReminders() so caching of indexed modifieds and reminders is done just once, as intended. This should hopefully speed up calendar generators and other plugins that render multiple dates...\n''2005.10.31 [1.0.1]''\ndocumentation and code cleanup\n''2005.10.31 [1.0.0]''\ninitial public release\n''2005.10.30 [0.9.0]''\npre-release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.date = {major: 2, minor: 0, revision: 4, date: new Date(2006,2,5)};\n//}}}\n\n//{{{\n// 1.2.x compatibility\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n//{{{\nconfig.macros.date = {\n format: "YYYY.0MM.0DD", // default date display format\n linkformat: "YYYY.0MM.0DD", // 'dated tiddler' link format\n weekendbg: "#c0c0c0", // "cocoa"\n holidaybg: "#c0ffee", // "coffee"\n modifiedsbg: "#bbeeff", // "beef"\n remindersbg: "#ffaace", // "face"\n holidays: [ "01/01", "07/04", "07/24", "11/24" ], // NewYearsDay, IndependenceDay(US), Eric's Birthday (hooray!), Thanksgiving(US)\n weekend: [ 1,0,0,0,0,0,1 ] // [ day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6 ]\n};\n//}}}\n\n//{{{\nconfig.macros.date.handler = function(place,macroName,params)\n{\n // do we want to see a link, a popup, or just a formatted date?\n var mode="display";\n if (params[0]=="display") { mode=params[0]; params.shift(); }\n if (params[0]=="popup") { mode=params[0]; params.shift(); }\n if (params[0]=="link") { mode=params[0]; params.shift(); }\n // get the date\n var now = new Date();\n var date = now;\n if (!params[0] || params[0]=="today")\n { params.shift(); }\n else if (params[0]=="filedate")\n { date=new Date(document.lastModified); params.shift(); }\n else if (params[0]=="tiddler")\n { date=store.getTiddler(story.findContainingTiddler(place).id.substr(7)).modified; params.shift(); }\n else if (params[0].substr(0,8)=="tiddler:")\n { var t; if ((t=store.getTiddler(params[0].substr(8)))) date=t.modified; params.shift(); }\n else {\n var y = eval(params.shift().replace(/Y/ig,(now.getYear()<1900)?now.getYear()+1900:now.getYear()));\n var m = eval(params.shift().replace(/M/ig,now.getMonth()+1));\n var d = eval(params.shift().replace(/D/ig,now.getDate()+0));\n date = new Date(y,m-1,d);\n }\n // date format with optional custom override\n var format=this.format; if (params[0]) format=params.shift();\n var linkformat=this.linkformat; if (params[0]) linkformat=params.shift();\n showDate(place,date,mode,format,linkformat);\n}\n//}}}\n\n//{{{\nwindow.showDate=showDate;\nfunction showDate(place,date,mode,format,linkformat,autostyle,weekend)\n{\n if (!mode) mode="display";\n if (!format) format=config.macros.date.format;\n if (!linkformat) linkformat=config.macros.date.linkformat;\n if (!autostyle) autostyle=false;\n\n // format the date output\n var title = date.formatString(format);\n var linkto = date.formatString(linkformat);\n\n // just show the formatted output\n if (mode=="display") { place.appendChild(document.createTextNode(title)); return; }\n\n // link to a 'dated tiddler'\n var link = createTiddlyLink(place, linkto, false);\n link.appendChild(document.createTextNode(title));\n link.title = linkto;\n link.date = date;\n link.format = format;\n link.linkformat = linkformat;\n\n // if using a popup menu, replace click handler for dated tiddler link\n // with handler for popup and make link text non-italic (i.e., an 'existing link' look)\n if (mode=="popup") {\n link.onclick = onClickDatePopup;\n link.style.fontStyle="normal";\n }\n\n // format the popup link to show what kind of info it contains (for use with calendar generators)\n if (!autostyle) return;\n if (hasModifieds(date))\n { link.style.fontStyle="normal"; link.style.fontWeight="bold"; }\n if (hasReminders(date))\n { link.style.textDecoration="underline"; }\n if(isToday(date))\n { link.style.border="1px solid black"; }\n\n if( (weekend!=undefined?weekend:isWeekend(date)) && (config.macros.date.weekendbg!="") )\n { place.style.background = config.macros.date.weekendbg; }\n if(isHoliday(date)&&(config.macros.date.holidaybg!=""))\n { place.style.background = config.macros.date.holidaybg; }\n if (hasModifieds(date)&&(config.macros.date.modifiedsbg!=""))\n { place.style.background = config.macros.date.modifiedsbg; }\n if (hasReminders(date)&&(config.macros.date.remindersbg!=""))\n { place.style.background = config.macros.date.remindersbg; }\n}\n//}}}\n\n//{{{\nfunction isToday(date) // returns true if date is today\n { var now=new Date(); return ((now-date>=0) && (now-date<86400000)); }\n\nfunction isWeekend(date) // returns true if date is a weekend\n { return (config.macros.date.weekend[date.getDay()]); }\n\nfunction isHoliday(date) // returns true if date is a holiday\n{\n var longHoliday = date.formatString("0MM/0DD/YYYY");\n var shortHoliday = date.formatString("0MM/0DD");\n for(var i = 0; i < config.macros.date.holidays.length; i++) {\n var holiday=config.macros.date.holidays[i];\n if (holiday==longHoliday||holiday==shortHoliday) return true;\n }\n return false;\n}\n//}}}\n\n//{{{\n// Event handler for clicking on a day popup\nfunction onClickDatePopup(e)\n{\n if (!e) var e = window.event;\n var theTarget = resolveTarget(e);\n var popup = createTiddlerPopup(this);\n if(popup) {\n // always show dated tiddler link at the top...\n createTiddlyLink(popup,this.date.formatString(this.linkformat),true);\n createTiddlyElement(popup,"hr",null,null,null);\n addModifiedsToPopup(popup,this.date,this.format);\n addRemindersToPopup(popup,this.date,this.linkformat);\n }\n scrollToTiddlerPopup(popup,false);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n\n//{{{\nfunction indexModifieds() // build list of tiddlers, hash indexed by modification date\n{\n var modifieds= { };\n var tiddlers = store.getTiddlers("title");\n for (var t = 0; t < tiddlers.length; t++) {\n var date = tiddlers[t].modified.formatString("YYYY0MM0DD")\n if (!modifieds[date])\n modifieds[date]=new Array();\n modifieds[date].push(tiddlers[t].title);\n }\n return modifieds;\n}\nfunction hasModifieds(date) // returns true if date has modified tiddlers\n{\n if (!config.macros.date.modifieds) config.macros.date.modifieds = indexModifieds();\n return (config.macros.date.modifieds[date.formatString("YYYY0MM0DD")]!=undefined);\n}\n\nfunction addModifiedsToPopup(popup,when,format)\n{\n if (!config.macros.date.modifieds) config.macros.date.modifieds = indexModifieds();\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n var mods = config.macros.date.modifieds[when.formatString("YYYY0MM0DD")];\n if (mods) {\n mods.sort();\n var e=createTiddlyElement(popup,"div",null,null,"changes:");\n for(var t=0; t<mods.length; t++) {\n var link=createTiddlyLink(popup,mods[t],false);\n link.appendChild(document.createTextNode(indent+mods[t]));\n createTiddlyElement(popup,"br",null,null,null);\n }\n }\n}\n//}}}\n\n//{{{\nfunction indexReminders() // build list of tiddlers with reminders, hash indexed by reminder date\n{\n var reminders = { };\n\n if(window.findTiddlersWithReminders==undefined) return; // reminders plugin not installed\n\n var matches = store.search("reminder",false,false,"title","excludeSearch");\n var macroPattern = "<<([^>\s\ss]+)(?:\s\ss*)([^>]*)>>";\n var macroRegExp = new RegExp(macroPattern,"mg");\n var arr = [];\n for(var t=matches.length-1; t>=0; t--)\n {\n var targetText = matches[t].text;\n do {\n // Get the next formatting match\n var formatMatch = macroRegExp.exec(targetText);\n if(formatMatch)\n {\n if (formatMatch[1] != null && formatMatch[1].toLowerCase() == "reminder")\n {\n //Find the matching date.\n var params = formatMatch[2].readMacroParams();\n var dateHash = getParamsForReminder(params);\n var date = findDateForReminder(dateHash);\n if (date != null)\n {\n var dateindex = date.formatString("YYYY0MM0DD")\n if (!reminders[dateindex])\n reminders[dateindex]=new Array();\n reminders[dateindex].pushUnique(t);\n }\n }\n }\n } while(formatMatch);\n }\n return reminders;\n}\n\nfunction hasReminders(date) // returns true if date has reminders\n{\n return false; // ELS 2005.11.03: BYPASS due to performance issues\n if (!config.macros.date.reminders) config.macros.date.reminders = indexReminders();\n return (config.macros.date.reminders[date.formatString("YYYY0MM0DD")]!=undefined);\n}\n\nfunction addRemindersToPopup(popup,when,format)\n{\n if(window.findTiddlersWithReminders == null) return; // reminder plugin not installed\n var indent = String.fromCharCode(160)+String.fromCharCode(160);\n var e=createTiddlyElement(popup,"div",null,null,"reminders:");\n var reminders=findTiddlersWithReminders(when, [0,31],null,null);\n for(var t=0; t<reminders.length; t++) {\n link = createTiddlyLink(popup,reminders[t].tiddler,false);\n var diff=reminders[t].diff;\n diff=(!diff)?"Today":((diff==1)?"Tomorrow":diff+" days");\n var txt=(reminders[t].params["title"])?reminders[t].params["title"]:reminders[t].tiddler;\n link.appendChild(document.createTextNode(indent+diff+" - "+txt));\n createTiddlyElement(popup,"br",null,null,null);\n }\n var link = createTiddlyLink(popup,indent+"new reminder...",true); createTiddlyElement(popup,"br");\n var title = when.formatString(format);\n link.title="add a reminder to '"+title+"'";\n link.onclick = function() {\n // show tiddler editor\n story.displayTiddler(null, title, 2, null, null, false, false);\n // find body 'textarea'\n var c =document.getElementById("tiddler" + title).getElementsByTagName("*");\n for (var i=0; i<c.length; i++) if ((c[i].tagName.toLowerCase()=="textarea") && (c[i].getAttribute("edit")=="text")) break;\n // append reminder macro to tiddler content\n if (i<c.length) {\n if (store.tiddlerExists(title)) c[i].value+="\sn"; else c[i].value="";\n c[i].value += "<<reminder day:"+when.getDate()+" month:"+(when.getMonth()+1)+" year:"+(when.getYear()+1900)+" title: >>";\n }\n };\n}\n//}}}
ShowReminders\n[[NEXT ACTIONS]]
//{{{\n// Enable editing so that visitors can experiment\nconfig.options.chkHttpReadOnly = false;\n//}}}\n\n
Enter Tiddler edit mode and click "delete" \n\nIf you delete a Tiddler that lives in MainMenu or DefaultTiddlers, you'll need to manually remove them from those SpecialTiddlers.\n\nSee also: RenameTiddlers
I found the [[Aardvark Firefox extension|http://www.karmatics.com/aardvark/]] indispensible in developing GTDTiddlyWiki. Browser view-source doesn't work on TiddlyWiki, so I use Aardvark to "see" the page structure.
/***\n''DisableWikiLinksPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#DisableWikiLinksPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nThis plugin allows you to disable TiddlyWiki's automatic WikiWord linking behavior, so that WikiWords embedded in tiddler content will be rendered as regular text, instead of being automatically converted to tiddler links. To create a tiddler link when automatic linking is disabled, you must enclose the link text within {{{[[}}} and {{{]]}}}.\n\n!!!!!Configuration\n<<<\nSelf-contained control panel:\n<<option chkDisableWikiLinks>> Disable automatic WikiWord tiddler links\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''DisableWikiLinksPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.02.05 [1.0.1]''\nwrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2005.12.09 [1.0.0]''\ninitial release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.disableWikiLinks= {major: 1, minor: 0, revision: 0, date: new Date(2005,12,9)};\n\nif (config.options.chkDisableWikiLinks==undefined) config.options.chkDisableWikiLinks= false;\n\n// find the formatter for wikiLink and replace handler with 'pass-thru' rendering\ninitDisableWikiLinksFormatter();\nfunction initDisableWikiLinksFormatter() {\n for (var i=0; i<config.formatters.length && config.formatters[i].name!="wikiLink"; i++);\n config.formatters[i].coreHandler=config.formatters[i].handler;\n config.formatters[i].handler=function(w) {\n // if not enabled, just do standard WikiWord link formatting\n if (!config.options.chkDisableWikiLinks) return this.coreHandler(w);\n // supress any leading "~" (if present)\n var skip=(w.matchText.substr(0,1)==config.textPrimitives.unWikiLink)?1:0;\n w.outputText(w.output,w.matchStart+skip,w.nextMatch)\n }\n}\n//}}}
Because TiddlyWiki is a single HTML file, you've actually already downloaded the entire software just by viewing this site. If you want to be able to SaveChanges, you can save your own TiddlyWiki to your local drive by right clicking on [[this link|#]] and selecting 'Save link as...' or 'Save target as...'. You can choose where to save the file, and what to call it (but keep the .HTML extension).
Try holding down the alt- or shift-key while clicking on a link to a tiddler, on the 'options' button or on the CloseButton for a tiddler. Kind of a respectful homage to Mac OS X, which does something similar for many of its system animations. (On browsers like InternetExplorer that use the shift key to open a new window, it's best to use the alt-key).
<div class='toolbar'>\n <span macro='runMacroIfTagged action MatchTagChooser !Projects "Choose a Project" "^![^ ]+$"'><span macro='runMacroIfTagged action MatchTagChooser @Contexts "Choose a Context" "^@[^ ]+$"'><span macro='MatchTagChooser GTD "Choose a GTD tag" "^([@!][^ ]+|action|context|done|next|project|somedayMaybe)$"'><span macro='runMacroIfTagged groceries MatchTagChooser $Groceries "Toggle a Grocery Type" "^\s$[^ ]+$"'><span macro='MatchTagChooser tags "Choose a non-GTD or non-Grocery tag" "^([@!$][^ ]+|action|context|done|next|project|somedayMaybe)$" not'></span></span></span></span></span>\n <span macro='toolbar +saveTiddler -cancelTiddler copyTiddler deleteTiddler'></span>\n</div>\n<div class='title' macro='view title'></div>\n<div class='editor' macro='edit title'>title:</div>\n<div class='editor' macro='edit tags'>space-separated<span macro='tagChooser'></span>: (use [[double square brackets]] if necessary)</div>\n<div class='editor' macro='edit text'></div>
You can email the creator of TiddlyWiki at jeremy (at) osmosoft (dot) com.
Questions? Comments? Bugs? Please use the GTD Tiddly Wiki GTDTWForum. It's the best way to get a response and you'll have more eyes on your issue.\n\nTo email me use my [[mail form|http://snapgrid.com/contact/]]. I can't always reply to everyone, but I do try to read all emails.\n\nTo contact the original creator of TiddlyWiki, EmailJeremy.
Edit this tiddler to see how to insert images.\n[img[http://img110.echo.cx/img110/139/gorilla8nw.jpg]]
There's now an option under InterfaceOptions to allow TiddlyWiki's animation effects to be turned off.
Check out the music of Eric Ian Walker\n* Soundscapes\n* Check out NPR echos for more details, specifically Thursday, February 9, sometime around 10:00pm during the WCBE echos broadcast
''Bold''\n==Strike==\n__Underline__\n//Italic//\n2^^3^^=8\na~~ij~~ = -a~~ji~~\n@@highlight@@\n@@color(green):green colored@@\n@@bgcolor(#ff0000):color(#ffffff):red colored@@
FireFox lets you SaveChanges in TiddlyWiki, but you will see up to three dialogs asking your permission for the local file operations. You must allow all three operations for it to work properly. Note that you can select the //Remember this decision// option to avoid seeing the dialogs in future.
Released in September 2004, the [[first version|firstversion.html]] was pretty basic, weighing in at 52KB.
/***\n|''Name:''|ForEachTiddlerPlugin|\n|''Version:''|1.0.5 (2006-02-05)|\n|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''Macros:''|[[ForEachTiddlerMacro]] v1.0.5|\n|''TiddlyWiki:''|1.2.38+, 2.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n!Description\n\nCreate customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.\n\n''Syntax:'' \n|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|\n|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|\n|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|\n|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|\n|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|\n|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|\n|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n\nSee details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].\n\n!Revision history\n* v1.0.5\n** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.\n** Support Firefox 1.5.0.1\n** Internal\n*** Make "JSLint" conform\n*** "Only install once"\n* v1.0.4 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.3 (2005-12-22)\n** Features: \n*** Write output to a file supports multi-byte environments (Thanks to Bram Chen) \n*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)\n** Enhancements:\n*** Improved error messages on InternetExplorer.\n* v1.0.2 (2005-12-10)\n** Features: \n*** context object also holds reference to store (TiddlyWiki)\n** Fixed Bugs: \n*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)\n* v1.0.1 (2005-12-08)\n** Features: \n*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".\n*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.\n*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).\n*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .\n*** Improved script evaluation (for where/sort clause and write scripts).\n* v1.0.0 (2005-11-20)\n** initial version\n\n!Code\n***/\n//{{{\n\n \n//============================================================================\n//============================================================================\n// ForEachTiddlerPlugin\n//============================================================================\n//============================================================================\n\n// Only install once\nif (!version.extensions.ForEachTiddlerPlugin) {\n\nversion.extensions.ForEachTiddlerPlugin = {major: 1, minor: 0, revision: 5, date: new Date(2006,2,5), source: "http://tiddlywiki.abego-software.de/#ForEachTiddlergPlugin"};\n\n// For backward compatibility with TW 1.2.x\n//\nif (!TiddlyWiki.prototype.forEachTiddler) {\n TiddlyWiki.prototype.forEachTiddler = function(callback) {\n for(var t in this.tiddlers) {\n callback.call(this,t,this.tiddlers[t]);\n }\n };\n}\n\n//============================================================================\n// forEachTiddler Macro\n//============================================================================\n\nversion.extensions.forEachTiddler = {major: 1, minor: 0, revision: 5, date: new Date(2006,2,5), provider: "http://tiddlywiki.abego-software.de"};\n\n// ---------------------------------------------------------------------------\n// Configurations and constants \n// ---------------------------------------------------------------------------\n\nconfig.macros.forEachTiddler = {\n // Standard Properties\n label: "forEachTiddler",\n prompt: "Perform actions on a (sorted) selection of tiddlers",\n\n // actions\n actions: {\n addToList: {},\n write: {}\n }\n};\n\n// ---------------------------------------------------------------------------\n// The forEachTiddler Macro Handler \n// ---------------------------------------------------------------------------\n\nconfig.macros.forEachTiddler.getContainingTiddler = function(e) {\n while(e && !hasClass(e,"tiddler"))\n e = e.parentNode;\n var title = e ? e.getAttribute("tiddler") : null; \n return title ? store.getTiddler(title) : null;\n};\n\nconfig.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n // config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);\n\n if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);\n // --- Parsing ------------------------------------------\n\n var i = 0; // index running over the params\n // Parse the "in" clause\n var tiddlyWikiPath = undefined;\n if ((i < params.length) && params[i] == "in") {\n i++;\n if (i >= params.length) {\n this.handleError(place, "TiddlyWiki path expected behind 'in'.");\n return;\n }\n tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");\n i++;\n }\n\n // Parse the where clause\n var whereClause ="true";\n if ((i < params.length) && params[i] == "where") {\n i++;\n whereClause = this.paramEncode((i < params.length) ? params[i] : "");\n i++;\n }\n\n // Parse the sort stuff\n var sortClause = null;\n var sortAscending = true; \n if ((i < params.length) && params[i] == "sortBy") {\n i++;\n if (i >= params.length) {\n this.handleError(place, "sortClause missing behind 'sortBy'.");\n return;\n }\n sortClause = this.paramEncode(params[i]);\n i++;\n\n if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {\n sortAscending = params[i] == "ascending";\n i++;\n }\n }\n\n // Parse the script\n var scriptText = null;\n if ((i < params.length) && params[i] == "script") {\n i++;\n scriptText = this.paramEncode((i < params.length) ? params[i] : "");\n i++;\n }\n\n // Parse the action. \n // When we are already at the end use the default action\n var actionName = "addToList";\n if (i < params.length) {\n if (!config.macros.forEachTiddler.actions[params[i]]) {\n this.handleError(place, "Unknown action '"+params[i]+"'.");\n return;\n } else {\n actionName = params[i]; \n i++;\n }\n } \n \n // Get the action parameter\n // (the parsing is done inside the individual action implementation.)\n var actionParameter = params.slice(i);\n\n\n // --- Processing ------------------------------------------\n try {\n this.performMacro({\n place: place, \n inTiddler: tiddler,\n whereClause: whereClause, \n sortClause: sortClause, \n sortAscending: sortAscending, \n actionName: actionName, \n actionParameter: actionParameter, \n scriptText: scriptText, \n tiddlyWikiPath: tiddlyWikiPath});\n\n } catch (e) {\n this.handleError(place, e);\n }\n};\n\n// Returns an object with properties "tiddlers" and "context".\n// tiddlers holds the (sorted) tiddlers selected by the parameter,\n// context the context of the execution of the macro.\n//\n// The action is not yet performed.\n//\n// @parameter see performMacro\n//\nconfig.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {\n\n var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);\n\n var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;\n context["tiddlyWiki"] = tiddlyWiki;\n \n // Get the tiddlers, as defined by the whereClause\n var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);\n context["tiddlers"] = tiddlers;\n\n // Sort the tiddlers, when sorting is required.\n if (parameter.sortClause) {\n this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);\n }\n\n return {tiddlers: tiddlers, context: context};\n};\n\n// Returns the (sorted) tiddlers selected by the parameter.\n//\n// The action is not yet performed.\n//\n// @parameter see performMacro\n//\nconfig.macros.forEachTiddler.getTiddlers = function(parameter) {\n return this.getTiddlersAndContext(parameter).tiddlers;\n};\n\n// Performs the macros with the given parameter.\n//\n// @param parameter holds the parameter of the macro as separate properties.\n// The following properties are supported:\n//\n// place\n// whereClause\n// sortClause\n// sortAscending\n// actionName\n// actionParameter\n// scriptText\n// tiddlyWikiPath\n//\n// All properties are optional. \n// For most actions the place property must be defined.\n//\nconfig.macros.forEachTiddler.performMacro = function(parameter) {\n var tiddlersAndContext = this.getTiddlersAndContext(parameter);\n\n // Perform the action\n var actionName = parameter.actionName ? parameter.actionName : "addToList";\n var action = config.macros.forEachTiddler.actions[actionName];\n if (!action) {\n this.handleError(parameter.place, "Unknown action '"+actionName+"'.");\n return;\n }\n\n var actionHandler = action.handler;\n actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);\n};\n\n// ---------------------------------------------------------------------------\n// The actions \n// ---------------------------------------------------------------------------\n\n// Internal.\n//\n// --- The addToList Action -----------------------------------------------\n//\nconfig.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {\n // Parse the parameter\n var p = 0;\n\n // Check for extra parameters\n if (parameter.length > p) {\n config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);\n return;\n }\n\n // Perform the action.\n var list = document.createElement("ul");\n place.appendChild(list);\n for (var i = 0; i < tiddlers.length; i++) {\n var tiddler = tiddlers[i];\n var listItem = document.createElement("li");\n list.appendChild(listItem);\n createTiddlyLink(listItem, tiddler.title, true);\n }\n};\n\n// Internal.\n//\n// --- The write Action ---------------------------------------------------\n//\nconfig.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {\n // Parse the parameter\n var p = 0;\n if (p >= parameter.length) {\n this.handleError(place, "Missing expression behind 'write'.");\n return;\n }\n\n var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);\n p++;\n\n // Parse the "toFile" option\n var filename = null;\n var lineSeparator = undefined;\n if ((p < parameter.length) && parameter[p] == "toFile") {\n p++;\n if (p >= parameter.length) {\n this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");\n return;\n }\n \n filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));\n p++;\n if ((p < parameter.length) && parameter[p] == "withLineSeparator") {\n p++;\n if (p >= parameter.length) {\n this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");\n return;\n }\n lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);\n p++;\n }\n }\n \n // Check for extra parameters\n if (parameter.length > p) {\n config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);\n return;\n }\n\n // Perform the action.\n var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);\n var count = tiddlers.length;\n var text = "";\n for (var i = 0; i < count; i++) {\n var tiddler = tiddlers[i];\n text += func(tiddler, context, count, i);\n }\n \n if (filename) {\n if (lineSeparator !== undefined) {\n lineSeparator = lineSeparator.replace(/\s\sn/mg, "\sn").replace(/\s\sr/mg, "\sr");\n text = text.replace(/\sn/mg,lineSeparator);\n }\n saveFile(filename, convertUnicodeToUTF8(text));\n } else {\n var wrapper = createTiddlyElement(place, "span");\n wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);\n }\n};\n\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n// Internal.\n//\nconfig.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {\n return {\n place : placeParam, \n whereClause : whereClauseParam, \n sortClause : sortClauseParam, \n sortAscending : sortAscendingParam, \n script : scriptText,\n actionName : actionNameParam, \n actionParameter : actionParameterParam,\n tiddlyWikiPath : tiddlyWikiPathParam,\n inTiddler : inTiddlerParam\n };\n};\n\n// Internal.\n//\n// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of \n// the given path.\n//\nconfig.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {\n if (!idPrefix) {\n idPrefix = "store";\n }\n var lenPrefix = idPrefix.length;\n \n // Read the content of the given file\n var content = loadFile(this.getLocalPath(path));\n if(content === null) {\n throw "TiddlyWiki '"+path+"' not found.";\n }\n \n // Locate the storeArea div's\n var posOpeningDiv = content.indexOf(startSaveArea);\n var posClosingDiv = content.lastIndexOf(endSaveArea);\n if((posOpeningDiv == -1) || (posClosingDiv == -1)) {\n throw "File '"+path+"' is not a TiddlyWiki.";\n }\n var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);\n \n // Create a "div" element that contains the storage text\n var myStorageDiv = document.createElement("div");\n myStorageDiv.innerHTML = storageText;\n myStorageDiv.normalize();\n \n // Create all tiddlers in a new TiddlyWiki\n // (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)\n var tiddlyWiki = new TiddlyWiki();\n var store = myStorageDiv.childNodes;\n for(var t = 0; t < store.length; t++) {\n var e = store[t];\n var title = null;\n if(e.getAttribute)\n title = e.getAttribute("tiddler");\n if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)\n title = e.id.substr(lenPrefix);\n if(title && title !== "") {\n var tiddler = tiddlyWiki.createTiddler(title);\n tiddler.loadFromDiv(e,title);\n }\n }\n tiddlyWiki.dirty = false;\n\n return tiddlyWiki;\n};\n\n\n \n// Internal.\n//\n// Returns a function that has a function body returning the given javaScriptExpression.\n// The function has the parameters:\n// \n// (tiddler, context, count, index)\n//\nconfig.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {\n var script = context["script"];\n var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";\n var fullText = (script ? script+";" : "")+functionText+";theFunction;";\n return eval(fullText);\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {\n var result = [];\n var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);\n tiddlyWiki.forEachTiddler(function(title,tiddler) {\n if (func(tiddler, context, undefined, undefined)) {\n result.push(tiddler);\n }\n });\n return result;\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {\n var message = "Extra parameter behind '"+actionName+"':";\n for (var i = firstUnusedIndex; i < parameter.length; i++) {\n message += " "+parameter[i];\n }\n this.handleError(place, message);\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {\n var result = \n (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) \n ? 0\n : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)\n ? -1 \n : +1; \n return result;\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {\n var result = \n (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) \n ? 0\n : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)\n ? +1 \n : -1; \n return result;\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {\n // To avoid evaluating the sortClause whenever two items are compared \n // we pre-calculate the sortValue for every item in the array and store it in a \n // temporary property ("forEachTiddlerSortValue") of the tiddlers.\n var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);\n var count = tiddlers.length;\n var i;\n for (i = 0; i < count; i++) {\n var tiddler = tiddlers[i];\n tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);\n }\n\n // Do the sorting\n tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);\n\n // Delete the temporary property that holds the sortValue. \n for (i = 0; i < tiddlers.length; i++) {\n delete tiddlers[i].forEachTiddlerSortValue;\n }\n};\n\n\n// Internal.\n//\nconfig.macros.forEachTiddler.trace = function(message) {\n displayMessage(message);\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {\n var message ="<<"+macroName;\n for (var i = 0; i < params.length; i++) {\n message += " "+params[i];\n }\n message += ">>";\n displayMessage(message);\n};\n\n\n// Internal.\n//\n// Creates an element that holds an error message\n// \nconfig.macros.forEachTiddler.createErrorElement = function(place, exception) {\n var message = (exception.description) ? exception.description : exception.toString();\n return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);\n};\n\n// Internal.\n//\n// @param place [may be null]\n//\nconfig.macros.forEachTiddler.handleError = function(place, exception) {\n if (place) {\n this.createErrorElement(place, exception);\n } else {\n throw exception;\n }\n};\n\n// Internal.\n//\n// Encodes the given string.\n//\n// Replaces \n// "$))" to ">>"\n// "$)" to ">"\n//\nconfig.macros.forEachTiddler.paramEncode = function(s) {\n var reGTGT = new RegExp("\s\s$\s\s)\s\s)","mg");\n var reGT = new RegExp("\s\s$\s\s)","mg");\n return s.replace(reGTGT, ">>").replace(reGT, ">");\n};\n\n// Internal.\n//\n// Returns the given original path (that is a file path, starting with "file:")\n// as a path to a local file, in the systems native file format.\n//\n// Location information in the originalPath (i.e. the "#" and stuff following)\n// is stripped.\n// \nconfig.macros.forEachTiddler.getLocalPath = function(originalPath) {\n // Remove any location part of the URL\n var hashPos = originalPath.indexOf("#");\n if(hashPos != -1)\n originalPath = originalPath.substr(0,hashPos);\n // Convert to a native file format assuming\n // "file:///x:/path/path/path..." - pc local file --> "x:\spath\spath\spath..."\n // "file://///server/share/path/path/path..." - FireFox pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n // "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."\n // "file://server/share/path/path/path..." - pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n var localPath;\n if(originalPath.charAt(9) == ":") // pc local file\n localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file:///") === 0) // mac/unix local file\n localPath = unescape(originalPath.substr(7));\n else if(originalPath.indexOf("file:/") === 0) // mac/unix local file\n localPath = unescape(originalPath.substr(5));\n else // pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\s\s"); \n return localPath;\n};\n\n// ---------------------------------------------------------------------------\n// Stylesheet Extensions (may be overridden by local StyleSheet)\n// ---------------------------------------------------------------------------\n//\nsetStylesheet(\n ".forEachTiddlerError{color: #ffffff;background-color: #880000;}",\n "forEachTiddler");\n\n//============================================================================\n// End of forEachTiddler Macro\n//============================================================================\n\n\n//============================================================================\n// String.startsWith Function\n//============================================================================\n//\n// Returns true if the string starts with the given prefix, false otherwise.\n//\nversion.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nString.prototype.startsWith = function(prefix) {\n var n = prefix.length;\n return (this.length >= n) && (this.slice(0, n) == prefix);\n};\n\n\n\n//============================================================================\n// String.endsWith Function\n//============================================================================\n//\n// Returns true if the string ends with the given suffix, false otherwise.\n//\nversion.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nString.prototype.endsWith = function(suffix) {\n var n = suffix.length;\n return (this.length >= n) && (this.right(n) == suffix);\n};\n\n\n//============================================================================\n// String.contains Function\n//============================================================================\n//\n// Returns true when the string contains the given substring, false otherwise.\n//\nversion.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nString.prototype.contains = function(substring) {\n return this.indexOf(substring) >= 0;\n};\n\n//============================================================================\n// Array.indexOf Function\n//============================================================================\n//\n// Returns the index of the first occurance of the given item in the array or \n// -1 when no such item exists.\n//\n// @param item [may be null]\n//\nversion.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.indexOf = function(item) {\n for (var i = 0; i < this.length; i++) {\n if (this[i] == item) {\n return i;\n }\n }\n return -1;\n};\n\n//============================================================================\n// Array.contains Function\n//============================================================================\n//\n// Returns true when the array contains the given item, otherwise false. \n//\n// @param item [may be null]\n//\nversion.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.contains = function(item) {\n return (this.indexOf(item) >= 0);\n};\n\n//============================================================================\n// Array.containsAny Function\n//============================================================================\n//\n// Returns true when the array contains at least one of the elements \n// of the item. Otherwise (or when items contains no elements) false is returned.\n//\nversion.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.containsAny = function(items) {\n for(var i = 0; i < items.length; i++) {\n if (this.contains(items[i])) {\n return true;\n }\n }\n return false;\n};\n\n\n//============================================================================\n// Array.containsAll Function\n//============================================================================\n//\n// Returns true when the array contains all the items, otherwise false.\n// \n// When items is null false is returned (even if the array contains a null).\n//\n// @param items [may be null] \n//\nversion.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.containsAll = function(items) {\n for(var i = 0; i < items.length; i++) {\n if (!this.contains(items[i])) {\n return false;\n }\n }\n return true;\n};\n\n\n} // of "install only once"\n\n// Used Globals (for JSLint) ==============\n// ... DOM\n/*global document */\n// ... TiddlyWiki Core\n/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink, \n displayMessage, endSaveArea, hasClass, loadFile, saveFile, \n startSaveArea, store, wikify */\n//}}}\n\n\n/***\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/
StyleSheetLayout\nStyleSheetColors\nSideBarTabs\n\n[[internal link(not existing)]]\n[[internal link(exists)|StyleSheet]]\n[[external link|http://www.tiddlywiki.com]]\n[[a pretty link that doesn't exist|blahBlueBlah]]\n\n<<newTiddler>>\n\n!Header 1\n!!Header 2\n!!!Header 3\n!!!!Header 4\n!!!!!Header 5\n\n''Bold''\n==Strike==\n__Underline__\n//Italic//\n2^^3^^=8\na~~ij~~ = -a~~ji~~\n@@highlight@@\n@@color(green):green colored@@\n@@bgcolor(#ff0000):color(#ffffff):red colored@@\n\n[img[Selectutorial|http://css.maxdesign.com.au/selectutorial/images/header.gif][http://css.maxdesign.com.au/selectutorial/]]\n\n{{{\n Preformated text\n}}}\n\nI think this is {{{rendered as code}}}.\n\nTo make quoted bits of text stand out, you can use BlockQuotes within your [[tiddler]]s, like this:\n\nJeremyRuston said:\n<<<\nA TiddlyWiki is like a blog because it's divided up into neat little chunks, but it encourages you to read it by hyperlinking rather than sequentially: if you like, a non-linear blog analogue that binds the individual microcontent items into a cohesive whole.\n<<<\n\nLike BulletPoints and NumberedBulletPoints, you can have three different levels of BlockQuotes. Just [[edit]] this tiddler to see how it's done.\n\n>level 1\n>level 1\n>>level 2\n>>level 2\n>>>level 3\n>>>level 3\n>>level 2\n>level 1\n\nCreating BulletPoints is simple.\n* Just add an asterisk\n* at the beginning of a line.\n** If you want to create sub-bullets\n** start the line with two asterisks\n*** And if you want yet another level\n*** use three asterisks\n* Edit this tiddler to see how it's done\n* You can also do NumberedBulletPoints\n\nIt's easy to create NumberedBulletPoints.\n# Use a single '#' at the start of each line\n# and the tiddler will automatically\n# start numbering your list.\n## If you want a sub-list\n## within any bullets\n## add two '#'s at the start of the lines.\n# When you go back to a single '#'\n# the main numbered list will start up\n# where it left off.\nIt's just as simple to do normal BulletPoints.\n\nEdit this tiddler to see how to insert images.\n[img[Fractal vegetable|fractalveg.jpg]]\n(This curious vegetable is called 'Romanesque broccoli' and is one of [[my photos|http://www.flickr.com/photos/jermy/]])\n\nYou can divide a tiddler into\n----\nsections by typing four dashes on a line by themselves\n\n*sample:\n|!th1111111111|!th2222222222|\n|>| colspan |\n| rowspan |left|\n|~| right|\n|bgcolor(#a0ffa0):colored| center |\n|caption|c\n\n*sample (changed caption and table headers):\n|caption|c\n|th1111111111|th2222222222|h\n|>| colspan |\n| rowspan |left|\n|~| right|\n|bgcolor(#a0ffa0):colored| center |\n\n|Standard Periodic Table (ref. Wikipedia)|c\n|| !1 | !2 |!| !3 | !4 | !5 | !6 | !7 | !8 | !9 | !10 | !11 | !12 | !13 | !14 | !15 | !16 | !17 | !18 |\n|!1|bgcolor(#a0ffa0): @@color(red):H@@ |>|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>||bgcolor(#c0ffff): @@color(red):He@@ |\n|!2|bgcolor(#ff6666): Li |bgcolor(#ffdead): Be |>|>|>|>|>|>|>|>|>|>||bgcolor(#cccc99): B |bgcolor(#a0ffa0): C |bgcolor(#a0ffa0): @@color(red):N@@ |bgcolor(#a0ffa0): @@color(red):O@@ |bgcolor(#ffff99): @@color(red):F@@ |bgcolor(#c0ffff): @@color(red):Ne@@ |\n|!3|bgcolor(#ff6666): Na |bgcolor(#ffdead): Mg |>|>|>|>|>|>|>|>|>|>||bgcolor(#cccccc): Al |bgcolor(#cccc99): Si |bgcolor(#a0ffa0): P |bgcolor(#a0ffa0): S |bgcolor(#ffff99): @@color(red):Cl@@ |bgcolor(#c0ffff): @@color(red):Ar@@ |\n|!4|bgcolor(#ff6666): K |bgcolor(#ffdead): Ca ||bgcolor(#ffc0c0): Sc |bgcolor(#ffc0c0): Ti |bgcolor(#ffc0c0): V |bgcolor(#ffc0c0): Cr |bgcolor(#ffc0c0): Mn |bgcolor(#ffc0c0): Fe |bgcolor(#ffc0c0): Co |bgcolor(#ffc0c0): Ni |bgcolor(#ffc0c0): Cu |bgcolor(#ffc0c0): Zn |bgcolor(#cccccc): Ga |bgcolor(#cccc99): Ge |bgcolor(#cccc99): As |bgcolor(#a0ffa0): Se |bgcolor(#ffff99): @@color(green):Br@@ |bgcolor(#c0ffff): @@color(red):Kr@@ |\n|!5|bgcolor(#ff6666): Rb |bgcolor(#ffdead): Sr ||bgcolor(#ffc0c0): Y |bgcolor(#ffc0c0): Zr |bgcolor(#ffc0c0): Nb |bgcolor(#ffc0c0): Mo |bgcolor(#ffc0c0): Tc |bgcolor(#ffc0c0): Ru |bgcolor(#ffc0c0): Rh |bgcolor(#ffc0c0): Pd |bgcolor(#ffc0c0): Ag |bgcolor(#ffc0c0): Cd |bgcolor(#cccccc): In |bgcolor(#cccccc): Sn |bgcolor(#cccc99): Sb |bgcolor(#cccc99): Te |bgcolor(#ffff99): I |bgcolor(#c0ffff): @@color(red):Xe@@ |\n|!6|bgcolor(#ff6666): Cs |bgcolor(#ffdead): Ba |bgcolor(#ffbfff):^^*1^^|bgcolor(#ffc0c0): Lu |bgcolor(#ffc0c0): Hf |bgcolor(#ffc0c0): Ta |bgcolor(#ffc0c0): W |bgcolor(#ffc0c0): Re |bgcolor(#ffc0c0): Os |bgcolor(#ffc0c0): Ir |bgcolor(#ffc0c0): Pt |bgcolor(#ffc0c0): Au |bgcolor(#ffc0c0): @@color(green):Hg@@ |bgcolor(#cccccc): Tl |bgcolor(#cccccc): Pb |bgcolor(#cccccc): Bi |bgcolor(#cccc99): Po |bgcolor(#ffff99): At |bgcolor(#c0ffff): @@color(red):Rn@@ |\n|!7|bgcolor(#ff6666): Fr |bgcolor(#ffdead): Ra |bgcolor(#ff99cc):^^*2^^|bgcolor(#ffc0c0): Lr |bgcolor(#ffc0c0): Rf |bgcolor(#ffc0c0): Db |bgcolor(#ffc0c0): Sq |bgcolor(#ffc0c0): Bh |bgcolor(#ffc0c0): Hs |bgcolor(#ffc0c0): Mt |bgcolor(#ffc0c0): Ds |bgcolor(#ffc0c0): Rg |bgcolor(#ffc0c0): @@color(green):Uub@@ |bgcolor(#cccccc): Uut |bgcolor(#cccccc): Uuq |bgcolor(#cccccc): Uup |bgcolor(#cccccc): Uuh |bgcolor(#fcfecc): @@color(#cccccc):Uus@@ |bgcolor(#ecfefc): @@color(#cccccc):Uuo@@ |\n\n| !Lanthanides^^*1^^|bgcolor(#ffbfff): La |bgcolor(#ffbfff): Ce |bgcolor(#ffbfff): Pr |bgcolor(#ffbfff): Nd |bgcolor(#ffbfff): Pm |bgcolor(#ffbfff): Sm |bgcolor(#ffbfff): Eu |bgcolor(#ffbfff): Gd |bgcolor(#ffbfff): Tb |bgcolor(#ffbfff): Dy |bgcolor(#ffbfff): Ho |bgcolor(#ffbfff): Er |bgcolor(#ffbfff): Tm |bgcolor(#ffbfff): Yb |\n| !Actinides^^*2^^|bgcolor(#ff99cc): Ac |bgcolor(#ff99cc): Th |bgcolor(#ff99cc): Pa |bgcolor(#ff99cc): U |bgcolor(#ff99cc): Np |bgcolor(#ff99cc): Pu |bgcolor(#ff99cc): Am |bgcolor(#ff99cc): Cm |bgcolor(#ff99cc): Bk |bgcolor(#ff99cc): Cf |bgcolor(#ff99cc): Es |bgcolor(#ff99cc): Fm |bgcolor(#ff99cc): Md |bgcolor(#ff99cc): No |\n\n*Chemical Series of the Periodic Table\n**@@bgcolor(#ff6666): Alkali metals@@\n**@@bgcolor(#ffdead): Alkaline earth metals@@\n**@@bgcolor(#ffbfff): Lanthanides@@\n**@@bgcolor(#ff99cc): Actinides@@\n**@@bgcolor(#ffc0c0): Transition metals@@\n**@@bgcolor(#cccccc): Poor metals@@\n**@@bgcolor(#cccc99): Metalloids@@\n**@@bgcolor(#a0ffa0): Nonmetals@@\n**@@bgcolor(#ffff99): Halogens@@\n**@@bgcolor(#c0ffff): Noble gases@@\n\n*State at standard temperature and pressure\n**those in @@color(red):red@@ are gases\n**those in @@color(green):green@@ are liquids\n**those in black are solids
TiddlyWiki uses Wiki style markup, a way of lightly "tagging" plain text so it can be transformed into HTML. Edit this Tiddler to see samples.\n\n! Header Samples\n!Header 1\n!!Header 2\n!!!Header 3\n!!!!Header 4\n!!!!!Header 5\n\n! Unordered Lists:\n* Lists are where it's at\n* Just use an asterisk and you're set\n** To nest lists just add more asterisks...\n***...like this\n* The circle makes a great bullet because once you've printed a list you can mark off completed items\n* You can also nest mixed list types\n## Like this\n\n! Ordered Lists\n# Ordered lists are pretty neat too\n# If you're handy with HTML and CSS you could customize the [[numbering scheme|http://www.w3schools.com/css/pr_list-style-type.asp]]\n## To nest, just add more octothorpes (pound signs)...\n### Like this\n* You can also\n** Mix list types\n*** like this\n# Pretty neat don't you think?\n\n! Tiddler links\nTo create a Tiddler link, just use mixed-case WikiWord, or use [[brackets]] for NonWikiWordLinks. This is how the GTD style [[@Action]] lists are created. \n\nNote that existing Tiddlers are in bold and empty Tiddlers are in italics. See CreatingTiddlers for details.\n\n! External Links\nYou can link to [[external sites|http://google.com]] with brackets. You can also LinkToFolders on your machine or network shares.\n\n! Images\nEdit this tiddler to see how it's done.\n[img[http://img110.echo.cx/img110/139/gorilla8nw.jpg]]\n\n!Tables\n|!th1111111111|!th2222222222|\n|>| colspan |\n| rowspan |left|\n|~| right|\n|colored| center |\n|caption|c\n\nFor a complex table example, see PeriodicTable.\n\n! Horizontal Rules\nYou can divide a tiddler into\n----\nsections by typing four dashes on a line by themselves.\n\n! Blockquotes\n<<<\nThis is how you do an extended, wrapped blockquote so you don't have to put angle quotes on every line.\n<<<\n>level 1\n>level 1\n>>level 2\n>>level 2\n>>>level 3\n>>>level 3\n>>level 2\n>level 1\n\n! Other Formatting\n''Bold''\n==Strike==\n__Underline__\n//Italic//\nSuperscript: 2^^3^^=8\nSubscript: a~~ij~~ = -a~~ji~~\n@@highlight@@\n@@color(green):green colored@@\n@@bgcolor(#ff0000):color(#ffffff):red colored@@\n
''$2''\n\nTag: <<tag $1>>\n\n! Pending Actions\n<<forEachTiddler\n where\n "tiddler.tags.containsAll(['$1','action','next']) && ! tiddler.tags.contains('done') && ! tiddler.tags.contains('somedayMaybe')"\n sortBy \n"getSortedTagsText(tiddler,['$1','action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;}'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['$1','action']) ? ' (' + getSortedTagsText(tiddler, ['$1','action']) + ')' : '' ) + '\sn'"\n>><<forEachTiddler\n where\n "tiddler.tags.containsAll(['$1','action']) && ! tiddler.tags.contains('next') && ! tiddler.tags.contains('done') && ! tiddler.tags.contains('somedayMaybe')"\n sortBy \n"getSortedTagsText(tiddler,['$1','action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;}'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['$1','action']) ? ' (' + getSortedTagsText(tiddler, ['$1','action']) + ')' : '' ) + '\sn'"\n>>\n! Someday Maybe Actions\n<<forEachTiddler\n where\n "tiddler.tags.containsAll(['$1','somedayMaybe','action']) && ! tiddler.tags.contains('done')"\n sortBy \n"getSortedTagsText(tiddler,['$1','somedayMaybe','action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;}'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['$1','somedayMaybe','action']) ? ' (' + getSortedTagsText(tiddler, ['$1','somedayMaybe','action']) + ')' : '' ) + '\sn'"\n>>\n! Done Actions\n<<forEachTiddler\n where\n "tiddler.tags.containsAll(['$1','done','action'])"\n sortBy \n"getSortedTagsText(tiddler,['$1','done','action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;}'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['$1','done','action']) ? ' (' + getSortedTagsText(tiddler, ['$1','done','action']) + ')' : '' ) + '\sn'"\n>>
* $2\n<<forEachTiddler\n where\n "tiddler.tags.containsAll(['@agenda','$1']) && ! tiddler.tags.contains('done') && ! tiddler.tags.contains('context')"\n sortBy \n"getSortedTagsText(tiddler,['@agenda','$1'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;}'\n write\n "'** [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['@agenda','$1']) ? ' (' + getSortedTagsText(tiddler, ['@agenda','$1']) + ')' : '' ) + '\sn'"\n>>
<<tiddler GTDActionListTemplate with: $1 "$2">>
<<tiddler GTDActionListTemplate with: $1 "$2">>
[[Forum for discussion of GTDTW|http://shared.snapgrid.com/gtd-forum/]]. Supercedes the GoogleGroup. Anyone can read posts, but a simple registration is required for posting (privacy guaranteed).
See [[About GTD TiddlyWiki]].
Getting Things Done is a simple and effective personal productivity method by David Allen. You can [[get the book from Amazon|http://www.amazon.com/exec/obidos/tg/detail/-/0142000280/qid=1115360158/sr=8-1/ref=pd_csp_1/002-8782437-3718417?v=glance&s=books&n=507846]].\n\nAlso check out the GTD community at the 43Folders [[website|http://www.43folders.com/]], [[wiki|http://wiki.43folders.com/index.php/Main_Page]], and [[newsgroup|http://groups-beta.google.com/group/43Folders/]].\n\n----\n"Getting Things Done" is © David Allen at [[Davidco|http://davidco.com]]. Davidco has no affiliation with TiddlyWiki or GTDTiddlyWiki.
The [[Google Group|http://groups-beta.google.com/group/GTD-TiddlyWiki?hl=en]] has been superceded by the GTDTWForum
<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\s<\s<forEachTiddler where \s'tiddler.tags.contains(\s"' + tiddler.title + '\s") && tiddler.title != \s"' + tiddler.title + '\s"\s' write \s"\s'*[[\s' + tiddler.title + \s']]\s\sn\s'\s" \s>\s>\sn'">>
/***\n''HTML Formatting Plugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#HTMLFormattingPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nThe shorthand Wiki-style formatting syntax of ~TiddlyWiki is very convenient and enables most content to be reasonably well presented. However, there are times when tried-and-true HTML formatting syntax allows more more precise control of the content display.\n\nWhen HTML formatting syntax is embedded within a tiddler (in between {{{<}}}{{{html>}}} and {{{<}}}{{{/html>}}} markers) TiddlyWiki passes this content to the browser for processing as 'native' HTML. However, TiddlyWiki does not also process the HTML source content for any embedded wiki-formatting syntax it may contain. This means that while you can use HTML formatted content, you cannot mix wiki-formatted content within the HTML formatting.\n!!!!!Usage\n<<<\nThe ~HTMLFormatting plugin allows you to freely ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.\n\nWhen a tiddler is about to be displayed, ~TiddlyWiki looks for tiddler content contained within ''<{{{html}}}>'' and ''<{{{/html}}}>'' HTML tags. This content (if any) is passed directly to the browser's internal "rendering engine" to process as ~HTML-formatted content. Once the HTML formatting has been processed, all the pieces of text occuring in between the HTML formatting are then processed by the ~TiddlyWiki rendering engine, one piece at a time, so that normal wiki-style formatting can be applied to the individual text pieces.\n<<<\n!!!!!Line breaks\n<<<\nOne major difference between Wiki formatting and HTML formatting is how "line breaks" are processed. Wiki formatting treats all line breaks as literal content to be displayed //as-is//. However, because HTML normally ignores line breaks and actually processes them as simple "word separators" instead, many people who write HTML include extra line breaks in their documents, just to make the "source code" easier to read.\n\nEven though you can use HTML tags within your tiddler content, the default treatment for line breaks still follows the Wiki-style rule (i.e., all new lines are displayed as-is). When adding HTML content to a tiddler (especially if you cut-and-paste it from another web page), you should take care to avoid adding extra line breaks to the text.\n\nIf removing all the extra line breaks from your HTML content would be a big hassle, you can quickly //override the default Wiki-style line break rule// so that the line breaks use the standard HTML rules instead. Placing a ''<{{{hide linebreaks}}}>'' tag within the tiddler's HTML content changes all line breaks to spaces before rendering the content, so that the literal line breaks will be processed as simple word-breaks instead.\n\nNote: this does //not// alter the actual tiddler content that is stored in the document, just the manner in which it is displayed. Any line breaks contained in the tiddler will still be there when you edit its content. Also, to include a literal line break when the ''<{{{hide linebreaks}}}>'' tag is present, you will need to use a ''<{{{br}}}>'' or ''<{{{p}}}>'' HTML tag instead of simply typing a line break.\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''HTMLFormattingPlugin'' (tagged with <<tag systemConfig>>)\n^^documentation and javascript for HTMLFormatting handling^^\n<<<\n!!!!!Revision History\n<<<\n''2006.02.19 [2.1.2]''\nin wikifyTextNodes(), put SPAN element into tiddler DOM (replacing text node), BEFORE wikifying the text content. This ensures that the 'place' passed to any macros is correctly defined when the macro is evaluated, so that calls to story.findContainingTiddler(place) will work as expected. (Thanks for bug report from GeoffSlocock)\n''2006.02.05 [2.1.1]''\nwrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2005.12.01 [2.1.0]''\ndon't wikify #TEXT nodes inside SELECT and TEXTAREA elements\n''2005.11.06 [2.0.1]''\ncode cleanup\n''2005.10.31 [2.0.0]''\nreplaced hijack wikify() with hijack config.formatters["html"] and simplified recursive WikifyTextNodes() code\n''2005.10.09 [1.0.2]''\ncombined documentation and code into a single tiddler\n''2005.08.05 [1.0.1]''\nmoved HTML and CSS definitions into plugin code instead of using separate tiddlers\n''2005.07.26 [1.0.1]''\nRe-released as a plugin.\nAdded <{{{html}}}>...</{{{nohtml}}}> and <{{{hide newlines}}}> handling\n''2005.07.20 [1.0.0]''\nInitial Release (as code adaptation)\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.HTMLFormatting = {major: 2, minor: 1, revision: 2, date: new Date(2006,2,19)};\n\n// find the formatter for HTML and replace the handler\ninitHTMLFormatter();\nfunction initHTMLFormatter()\n{\n for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);\n if (i<config.formatters.length) config.formatters[i].handler=function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {\n var html=lookaheadMatch[1];\n // optionally suppress wiki-style literal handling of newlines\n // strip any carriage returns added by Internet Explorer's textarea edit field\n // encode newlines as \sn so Internet Explorer's HTML parser won't eat them\n // encode macro brackets (<< and >>) so HTML parser won't eat them\n if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(regexpNewLine,' ');\n html=html.replace(regexpCarriageReturn,'');\n html=html.replace(regexpNewLine,'\s\sn');\n html=html.replace(/<</g,'%%(').replace(/>>/g,')%%');\n // create span to hold HTML\n // parse HTML and normalize the results\n // walk node tree and call wikify() on each text node\n var e = createTiddlyElement(w.output,"span");\n e.innerHTML=html;\n e.normalize(); \n wikifyTextNodes(e);\n // advance to next parse position\n w.nextMatch=lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n}\n\n// wikify text nodes remaining after HTML content is processed (pre-order recursion)\nfunction wikifyTextNodes(theNode)\n{\n for (var i=0;i<theNode.childNodes.length;i++) {\n var theChild=theNode.childNodes.item(i);\n if (theChild.nodeName.toLowerCase()=='option') continue;\n if (theChild.nodeName.toLowerCase()=='select') continue;\n wikifyTextNodes(theChild);\n if (theChild.nodeName=='#text') {\n var txt=theChild.nodeValue;\n // decode macro brackets and newlines\n txt=txt.replace(/\s%%\s(/g,'<<').replace(/\s)\s%%/g,'>>').replace(regexpBackSlashEn,'\sn');\n // replace text node with wikified() span\n var newNode=createTiddlyElement(null,"span");\n theNode.replaceChild(newNode,theChild);\n wikify(txt,newNode);\n }\n }\n}\n//}}}\n
Edit this to see how to create Headers\n\n!Header 1\n!!Header 2\n!!!Header 3\n!!!!Header 4\n!!!!!Header 5\n
Welcome to the GTDTiddlyWiki, an experimental MicroContent WikiWikiWeb originally built by JeremyRuston and adapted for GTD use by NathanBowers. It's written in HTML, CSS and JavaScript to run on any modern browser without needing any ServerSide logic. It allows anyone to create personal SelfContained hypertext documents that can be posted to any web server, sent by email or kept on a USB thumb drive to make a WikiOnAStick.
/***\nFor use in ViewTemplate \n***/\n//{{{\n\nconfig.macros.hideWhen = {};\nconfig.macros.hideWhen.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n if (eval(params[0]))\n place.style["display"] = 'none';\n}\n\nconfig.macros.hideUnless = {};\nconfig.macros.hideUnless.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n if (!eval(params[0]))\n place.style["display"] = 'none';\n}\n\n\n//}}}
AKA: "Personal Analog Assistant"\n\nA fun term for running your GTD lists from index cards. See [[43Folders|http://merlin.blogs.com/43folders/2004/09/introducing_the.html]] for the full rundown (be sure to check the trackbacks. Also check out [[Adam Gurno's|http://gurno.com/adam/j2/index.php?p=44]] ideas for printing your own special cards.
When GTDTiddlyWiki is updated with enhancements and fixes, here's how to upgrade while keeping your data.\n\n* Just to be safe, create a backup of your current file and archive it somewhere.\n\nOkay then:\n* Open your TiddlyWiki file (say it's called "mystuff.html") in a browser.\n* Without closing that page, right-click on [[this link|#]], select 'Save target' or 'Save link' and save it as "mystuff.html", replacing your existing file\n* Now go back to the previously opened copy of "mystuff.html" in your browser and click "save changes" in the sidebar.\n* Refresh the page in the browser to verify that the upgrade has worked
To upload a TiddlyWiki on your web server :\n\n#Import all tiddlers tagged with Upload from http://TiddlyWiki.bidix.info/#Upload\n#Install UploadPlugin //as usual//\n#Configure and upload [[store.php]] on your webserver\n#set a {{{<<upload>>}}} button for example in your SideBarOptions\n#Set UploadOptions in conformity with [[store.php]]\n#click on <<upload>> button\n
*sample:\n|!th1111111111|!th2222222222|\n|>| colspan |\n| rowspan |left|\n|~| right|\n|bgcolor(#a0ffa0):colored| center |\n|caption|c\n*another sample: see PeriodicTable.\n
<<importTiddlers inline>>
/***\n''Import Tiddlers Plugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#ImportTiddlersPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nWhen many people share and edit copies of the same TiddlyWiki document, the ability to quickly collect all these changes back into a single, updated document that can then be redistributed to the entire group is very important. This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. It can also be very useful when moving your own tiddlers from document to document (e.g., when upgrading to the latest version of TiddlyWiki, or 'pre-loading' your favorite stylesheets into a new 'empty' TiddlyWiki document.)\n\n!!!!!Inline interface (live)\n<<<\n<<importTiddlers inline>>\n<<<\n!!!!!Macro Syntax\n<<<\n{{{<<importTiddlers>>}}}\ncreates "import tiddlers" link. click to show/hide import control panel\n\n{{{<<importTiddlers inline>>}}}\ncreates import control panel directly in tiddler content\n\n{{{<<importTiddlers filter source quiet ask>>}}}\nnon-interactive 'automatic' import.\n''filter'' determines which tiddlers will be automatically selected for importing. Use one of the following keywords:\n>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler\n>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)\n>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.\n''source'' is the location of the imported document. It can be either a local document or an URL:\n>filename is any local path/file, in whatever format your system requires\n>URL is any remote web location that starts with "http://" or "https://"\n''"quiet"'' (optional)\n>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc). Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified. This ensures that changes to your document cannot occur without any visible indication at all.\n''"ask"'' (optional)\n>adds interactive confirmation. A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.\n\n''Special tag values: importReplace and importPublic''\n\nBy adding these special tags to an existing tiddler, you can precisely control whether or not to allow updates to that tiddler as well as decide which tiddlers in your document can be automatically imported by others.\n*''For maximum safety, the default action is to prevent existing tiddlers from being unintentionally overwritten by incoming tiddlers.'' To allow an existing tiddler to be overwritten by an imported tiddler, you must tag the existing tiddler with ''<<tag importReplace>>''\n*''For maximum privacy, the default action for //outgoing// tiddlers is to NOT automatically share your tiddlers with others.'' To allow a tiddler in your document to be shared via auto-import actions by others, you must tag it with ''<<tag importPublic>>''\n//Note: these tags are only applied when using the auto-import processing. When using the interactive control panel, all tiddlers in the imported document are available in the listbox, regardless of their tag values.//\n<<<\n!!!!!Interactive Usage\n<<<\nWhen used interactively, a control panel is displayed consisting of an "import source document" filename input (text field plus a ''[Browse...]'' button), a listbox of available tiddlers, a "differences only" checkbox, an "add tags" input field and four push buttons: ''[open]'', ''[select all]'', ''[import]'' and ''[close]''.\n\nPress ''[browse]'' to select a TiddlyWiki document file to import. You can also type in the path/filename or a remote document URL (starting with http://)and press ''[open]''. //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//\n\nSelect one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items). You can press ''[select all]'' to quickly highlight all tiddler titles in the list. Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time. When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.\n\n''select: all, new, changes, or differences''\n\nYou can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:\n>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document\n>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)\n\n''Import Tagging:''\n\nTiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document. New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.\n\n''Skip, Rename, Merge, or Replace:''\n\nWhen importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.\n\nTo bypass importing this tiddler, press ''[skip]''. To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''. Press ''[merge]'' to combine the content from both tiddlers into a single tiddler. Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.\n\n//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//\n\n''Import Report History''\n\nWhen tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.\n\nWhen the import process is completed, the ImportedTiddlers report is automatically displayed for your review. If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.\n\nIf a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.\n\nNote: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.\n\n<<<\n!!!!!Installation\n<<<\ncopy/paste the following tiddlers into your document:\n''ImportTiddlersPlugin'' (tagged with <<tag systemConfig>>)\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add "< < ImportTiddlers > >" macro^^\n\n''Quick Installation Tip #1:''\nIf you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.\n<<<\n!!!!!Revision History\n<<<\n''2006.02.17 [2.6.0]''\nRemoved "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.\n''2006.02.16 [2.5.4]''\nadded checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.\n''2006.02.14 [2.5.3]''\nFF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()\n''2006.02.10 [2.5.2]''\ncorrected unintended global variable in importReport().\n''2006.02.05 [2.5.1]''\nmoved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2006.01.18 [2.5.0]''\nadded checkbox for "create a report". Default is to create/update the ImportedTiddlers report. Clear the checkbox to skip this step.\n''2006.01.15 [2.4.1]''\nadded "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic\n''2006.01.15 [2.4.0]''\nAdded support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax. Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.\n''2006.01.15 [2.3.2]''\nAdded "ask" parameter to confirm each tiddler before importing (for use with auto-importing)\n''2006.01.15 [2.3.1]''\nStrip TW core scripts from import source content and load just the storeArea into the hidden IFRAME. Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins). Seems to resolve the "Found 0 tiddlers" problem. Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.\n''2006.01.12 [2.3.0]''\nReorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest. Let's processing continue while waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source. Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.\n''2006.01.11 [2.2.0]''\nAdded "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck\n''2006.01.09 [2.1.1]''\nWhen a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button. This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit. I removed the onChange handling for file input field. To open a file (local or URL), you must now explicitly press the "open" button in the control panel.\n''2006.01.08 [2.1.0]''\nIMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.\n''2006.01.06 [2.0.2]''\nWhen refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.\n''2006.01.04 [2.0.1]''\nWhen "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.\n''2005.12.27 [2.0.0]''\nUpdate for TW2.0\nDefer initial panel creation and only register a notification function when panel first is created\n''2005.12.22 [1.3.1]''\ntweak formatting in importReport() and add 'discard report' link to output\n''2005.12.03 [1.3.0]''\nDynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)\n''2005.11.29 [1.2.1]''\nfixed formatting of 'detail info' in importReport()\n''2005.11.11 [1.2.0]''\nadded 'inline' param to embed controls in a tiddler\n''2005.11.09 [1.1.0]''\nonly load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.\n''2005.10.25 [1.0.5]''\nfixed typo in importReport() that prevented reports from being generated\n''2005.10.09 [1.0.4]''\ncombined documentation with plugin code instead of using separate tiddlers\n''2005.08.05 [1.0.3]''\nmoved CSS and HTML definitions into plugin code instead of using separate tiddlers\n''2005.07.27 [1.0.2]''\ncore update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()\n''2005.07.23 [1.0.1]''\nadded parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]''\nInitial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n\n// // Version\n//{{{\nversion.extensions.importTiddlers = {major: 2, minor: 6, revision: 0, date: new Date(2006,2,17)};\n//}}}\n\n// // 1.2.x compatibility\n//{{{\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n// // IE needs explicit global scoping for functions/vars called from browser events\n//{{{\nwindow.onClickImportButton=onClickImportButton;\nwindow.loadImportFile=loadImportFile;\nwindow.refreshImportList=refreshImportList;\n//}}}\n\n// // default cookie/option values\n//{{{\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n//}}}\n\n\n// // ''MACRO DEFINITION''\n\n//{{{\nconfig.macros.importTiddlers = { };\nconfig.macros.importTiddlers = {\n label: "import tiddlers",\n prompt: "Copy tiddlers from another document",\n countMsg: "%0 tiddlers selected for import",\n src: "", // path/filename or URL of document to import\n inbound: null, // hash-indexed array of tiddlers from other document\n newTags: "", // text of tags added to imported tiddlers\n addTags: true, // add new tags to imported tiddlers\n listsize: 8, // # of lines to show in imported tiddler list\n importTags: true, // include tags from remote source document when importing a tiddler\n keepTags: true, // retain existing tags when replacing a tiddler\n index: 0, // current processing index in import list\n sort: "" // sort order for imported tiddler listbox\n};\n\nconfig.macros.importTiddlers.handler = function(place,macroName,params) {\n // LINK WITH FLOATING PANEL\n if (!params[0]) {\n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n return;\n }\n // INLINE TIDDLER CONTENT\n if (params[0]=="inline") {\n createImportPanel(place);\n document.getElementById("importPanel").style.position="static";\n document.getElementById("importPanel").style.display="block";\n return;\n }\n // NON-INTERACTIVE BATCH MODE\n switch (params[0]) {\n case 'all':\n case 'new':\n case 'changes':\n case 'updates':\n var filter=params.shift();\n break;\n default:\n var filter="updates";\n break;\n } \n if (!params[0]||!params[0].length) return; // filename is required\n config.macros.importTiddlers.src=params.shift();\n var quiet=(params[0]=="quiet"); if (quiet) params.shift();\n var ask=(params[0]=="ask"); if (ask) params.shift();\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n // load storeArea from a hidden IFRAME, then apply import rules and add/replace tiddlers\n loadImportFile(config.macros.importTiddlers.src,filter,quiet,ask,autoImportTiddlers);\n}\n//}}}\n\n// // ''READ TIDDLERS FROM ANOTHER DOCUMENT''\n\n//{{{\nfunction loadImportFile(src,filter,quiet,ask,callback) {\n if (!quiet) clearMessage();\n // LOCAL FILE\n if ((src.substr(0,7)!="http://")&&(src.substr(0,8)!="https://")) {\n if (!quiet) displayMessage("Opening local document: "+ src);\n var txt=loadFile(src);\n if(!txt) { if (!quiet) displayMessage("Could not open local document: "+src); }\n else {\n var s="<html><body>"+txt.substr(txt.indexOf('<div id="storeArea">'));\n if (!quiet) displayMessage(txt.length+" bytes in document. ("+s.length+" bytes used for tiddler storage)");\n config.macros.importTiddlers.inbound = readImportedTiddlers(convertUTF8ToUnicode(s));\n var count=config.macros.importTiddlers.inbound?config.macros.importTiddlers.inbound.length:0;\n if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);\n if (callback) callback(src,filter,quiet,ask);\n }\n return;\n }\n // REMOTE FILE\n var x; // XML object\n try {x = new XMLHttpRequest()}\n catch(e) {\n try {x = new ActiveXObject("Msxml2.XMLHTTP")}\n catch (e) {\n try {x = new ActiveXObject("Microsoft.XMLHTTP")}\n catch (e) { return }\n }\n }\n x.onreadystatechange = function() {\n if (x.readyState == 4) {\n if (x.status == 200) {\n var sa="<html><body>"+x.responseText.substr(x.responseText.indexOf('<div id="storeArea">'));\n if (!quiet) displayMessage(x.responseText.length+" bytes in document. ("+sa.length+" bytes used for tiddler storage)");\n config.macros.importTiddlers.inbound = readImportedTiddlers(sa);\n var count=config.macros.importTiddlers.inbound?config.macros.importTiddlers.inbound.length:0;\n if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);\n if (callback) callback(src,filter,quiet,ask);\n }\n else\n if (!quiet) displayMessage("Could not open remote document:"+ src+" (error="+x.status+")");\n }\n }\n if (document.location.protocol=="file:") { // UniversalBrowserRead only works from a local file context\n try {netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead')}\n catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }\n }\n if (!quiet) displayMessage("Opening remote document: "+ src);\n try {\n var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();\n x.open("GET",url,true);\n x.overrideMimeType('text/html');\n x.send(null);\n }\n catch (e) {\n if (!quiet) {\n displayMessage("Could not open remote document: "+src);\n displayMessage(e.description?e.description:e.toString());\n }\n }\n}\n\nfunction readImportedTiddlers(txt)\n{\n var importedTiddlers = [];\n // create frame\n var f=document.getElementById("importFrame");\n if (f) document.body.removeChild(f);\n f=document.createElement("iframe");\n f.id="importFrame";\n f.style.width="0px"; f.style.height="0px"; f.style.border="0px";\n document.body.appendChild(f);\n // get document\n var d=f.document;\n if (f.contentDocument) d=f.contentDocument; // For NS6\n else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6\n // load source into document\n d.open(); d.writeln(txt); d.close();\n // read tiddler DIVs from storeArea DOM element \n var importStore = [];\n var importStoreArea = d.getElementById("storeArea");\n if (!importStoreArea || !(importStore=importStoreArea.childNodes) || (importStore.length==0)) { return null; }\n importStoreArea.normalize();\n for(var t = 0; t < importStore.length; t++) {\n var e = importStore[t];\n var title = null;\n if(e.getAttribute)\n title = e.getAttribute("tiddler");\n if(!title && e.id && (e.id.substr(0,5) == "store"))\n title = e.id.substr(5);\n if(title && title != "") {\n var theImported = new Tiddler();\n theImported.loadFromDiv(e,title);\n importedTiddlers.push(theImported);\n }\n }\n return importedTiddlers;\n}\n//}}}\n\n// // ''NON-INTERACTIVE IMPORT''\n\n// // import all/new/changed tiddlers into store, replacing or adding tiddlers as needed\n//{{{\nfunction autoImportTiddlers(src,filter,quiet,ask)\n{\n var count=0;\n if (config.macros.importTiddlers.inbound) for (var t=0;t<config.macros.importTiddlers.inbound.length;t++) {\n var theImported = config.macros.importTiddlers.inbound[t];\n var theExisting = store.getTiddler(theImported.title);\n\n // only import tiddlers if tagged with "importPublic"\n if (theImported.tags && theImported.tags.find("importPublic")==null)\n { config.macros.importTiddlers.inbound[t].status=""; continue; } // status=="" means don't show in report\n\n // never import the "ImportedTiddlers" history from the other document...\n if (theImported.title=='ImportedTiddlers')\n { config.macros.importTiddlers.inbound[t].status=""; continue; } // status=="" means don't show in report\n\n // check existing tiddler for importReplace, or systemConfig tags\n config.macros.importTiddlers.inbound[t].status="added"; // default - add any tiddlers not filtered out\n if (store.tiddlerExists(theImported.title)) {\n config.macros.importTiddlers.inbound[t].status="replaced";\n if (!theExisting.tags||(theExisting.tags.find("importReplace")==null))\n { config.macros.importTiddlers.inbound[t].status="not imported - tiddler already exists (use importReplace to allow changes)"; continue; }\n if ((theExisting.tags.find("systemConfig")!=null)||(theImported.tags.find("systemConfig")!=null))\n config.macros.importTiddlers.inbound[t].status+=" - WARNING: an active systemConfig plugin has been added or updated";\n }\n\n // apply the all/new/changes/updates filter \n if (filter!="all") {\n if ((filter=="new") && store.tiddlerExists(theImported.title))\n { config.macros.importTiddlers.inbound[t].status="not imported - tiddler already exists"; continue; }\n if ((filter=="changes") && !store.tiddlerExists(theImported.title))\n { config.macros.importTiddlers.inbound[t].status="not imported - new tiddler"; continue; }\n if (store.tiddlerExists(theImported.title) && ((theExisting.modified.getTime()-theImported.modified.getTime())>=0))\n { config.macros.importTiddlers.inbound[t].status="not imported - tiddler is unchanged"; continue; }\n }\n\n // get confirmation if required\n if (ask && !confirm("Import "+(theExisting?"updated":"new")+" tiddler '"+theImported.title+"'\snfrom "+src))\n { config.macros.importTiddlers.inbound[t].status="skipped - cancelled by user"; continue; }\n\n // DO THE IMPORT!!\n store.addTiddler(theImported); count++;\n }\n importReport(quiet); // generate a report (as needed) and display it if not 'quiet'\n if (count) store.setDirty(true); \n // always show final message when tiddlers were actually imported\n if (!quiet||count) displayMessage("Imported "+count+" tiddler"+(count!=1?"s":"")+" from "+src);\n}\n//}}}\n\n// // ''REPORT GENERATOR''\n\n//{{{\nfunction importReport(quiet)\n{\n if (!config.macros.importTiddlers.inbound) return;\n // DEBUG alert('importReport: start');\n\n // if import was not completed, the Ask panel will still be open... close it now.\n var askpanel=document.getElementById('importAskPanel'); if (askpanel) askpanel.style.display='none'; \n // get the alphasorted list of tiddlers\n var tiddlers = config.macros.importTiddlers.inbound;\n tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });\n // gather the statistics\n var count=tiddlers.length;\n var added=0; var replaced=0; var renamed=0; var skipped=0; var merged=0;\n for (var t=0; t<count; t++)\n if (tiddlers[t].status)\n {\n if (tiddlers[t].status=='added') added++;\n if (tiddlers[t].status.substr(0,7)=='skipped') skipped++;\n if (tiddlers[t].status.substr(0,6)=='rename') renamed++;\n if (tiddlers[t].status.substr(0,7)=='replace') replaced++;\n if (tiddlers[t].status.substr(0,6)=='merged') merged++;\n }\n var omitted=count-(added+replaced+renamed+skipped+merged);\n // DEBUG alert('stats done: '+count+' total, '+added+' added, '+skipped+' skipped, '+renamed+' renamed, '+replaced+' replaced, '+merged+' merged');\n // skip the report if nothing was imported\n if (added+replaced+renamed+merged==0) return;\n // skip the report if not desired by user\n if (!config.options.chkImportReport) {\n // reset status flags\n for (var t=0; t<count; t++) config.macros.importTiddlers.inbound[t].status="";\n // refresh display since tiddlers have been imported\n store.notifyAll();\n // quick message area summary report\n var msg=(added+replaced+renamed+merged)+' of '+count+' tiddler'+((count!=1)?'s':"");\n msg+=' imported from '+config.macros.importTiddlers.src.replace(/\s\s/g,'/')\n displayMessage(msg);\n return;\n }\n // create the report tiddler (if not already present)\n var tiddler = store.getTiddler('ImportedTiddlers');\n if (!tiddler) // create new report tiddler if it doesn't exist\n {\n tiddler = new Tiddler();\n tiddler.title = 'ImportedTiddlers';\n tiddler.text = "";\n }\n // format the report header\n var now = new Date();\n var newText = "";\n newText += "On "+now.toLocaleString()+", "+config.options.txtUserName+" imported tiddlers from\sn";\n newText += "[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\sn";\n newText += "<"+"<"+"<\sn";\n newText += "Out of "+count+" tiddler"+((count!=1)?"s ":" ")+" in {{{"+config.macros.importTiddlers.src.replace(/\s\s/g,'/')+"}}}:\sn";\n if (added+renamed>0)\n newText += (added+renamed)+" new tiddler"+(((added+renamed)!=1)?"s were":" was")+" added to your document.\sn";\n if (merged>0)\n newText += merged+" tiddler"+((merged!=1)?"s were":" was")+" merged with "+((merged!=1)?"":"an ")+"existing tiddler"+((merged!=1)?"s":"")+".\sn"; \n if (replaced>0)\n newText += replaced+" existing tiddler"+((replaced!=1)?"s were":" was")+" replaced.\sn"; \n if (skipped>0)\n newText += skipped+" tiddler"+((skipped!=1)?"s were":" was")+" skipped after asking.\sn"; \n if (omitted>0)\n newText += omitted+" tiddler"+((omitted!=1)?"s":"")+((omitted!=1)?" were":" was")+" not imported.\sn";\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newText += "imported tiddlers were tagged with: \s""+config.macros.importTiddlers.newTags+"\s"\sn";\n // output the tiddler detail and reset status flags\n for (var t=0; t<count; t++)\n if (tiddlers[t].status!="")\n {\n newText += "#["+"["+tiddlers[t].title+"]"+"]";\n newText += ((tiddlers[t].status!="added")?("^^\sn"+tiddlers[t].status+"^^"):"")+"\sn";\n config.macros.importTiddlers.inbound[t].status="";\n }\n newText += "<"+"<"+"<\sn";\n // output 'discard report' link\n newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n newText += "onclick=\s"story.closeTiddler('"+tiddler.title+"'); store.deleteTiddler('"+tiddler.title+"');\s" ";\n newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n tiddler.text = newText+((tiddler.text!="")?'\sn----\sn':"")+tiddler.text;\n tiddler.modifier = config.options.txtUserName;\n tiddler.modified = new Date();\n store.addTiddler(tiddler);\n if (!quiet) story.displayTiddler(null,"ImportedTiddlers",1,null,null,false);\n story.refreshTiddler("ImportedTiddlers",1,true);\n // refresh the display\n store.notifyAll();\n}\n//}}}\n\n// // ''INTERFACE DEFINITION''\n\n// // Handle link click to create/show/hide control panel\n//{{{\nfunction onClickImportMenu(e)\n{\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("importPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=createImportPanel(parent);\n var isOpen = panel.style.display=="block";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n panel.style.display = isOpen ? "none" : "block" ;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n\n// // Create control panel: HTML, CSS, register for notification\n//{{{\nfunction createImportPanel(place) {\n var panel=document.getElementById("importPanel");\n if (panel) { panel.parentNode.removeChild(panel); }\n setStylesheet(config.macros.importTiddlers.css,"importTiddlers");\n panel=createTiddlyElement(place,"span","importPanel",null,null)\n panel.innerHTML=config.macros.importTiddlers.html;\n store.addNotification(null,refreshImportList); // refresh listbox after every tiddler change\n refreshImportList();\n return panel;\n}\n//}}}\n\n// // CSS\n//{{{\nconfig.macros.importTiddlers.css = '\s\n#importPanel {\s\n display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\s\n padding: 0.5em; margin:0em; text-align:left; font-size: 8pt;\s\n background-color: #eee; color:#000000; \s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px; -moz-border-radius:1em;\s\n}\s\n#importPanel a { color:#009; }\s\n#importPanel input { width: 98%; margin: 1px; font-size:8pt; }\s\n#importPanel select { width: 98%; margin: 1px; font-size:8pt; }\s\n#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\s\n#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\s\n#importAskPanel { display:none; margin:0.5em 0em 0em 0em; }\s\n';\n//}}}\n\n// // HTML\n//{{{\nconfig.macros.importTiddlers.html = '\s\n<span style="float:left; padding:1px; white-space:nowrap">\s\n import from source document\s\n</span>\s\n<span style="float:right; padding:1px; white-space:nowrap">\s\n <input type=checkbox id="chkImportReport" checked style="height:1em; width:auto"\s\n onClick="config.options[\s'chkImportReport\s']=this.checked;">create a report\s\n</span>\s\n<input type="file" id="fileImportSource" size=56\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n<span style="float:left; padding:1px; white-space:nowrap">\s\n select:\s\n <a href="JavaScript:;" id="importSelectAll"\s\n onclick="onClickImportButton(this)" title="select all tiddlers">\s\n &nbsp;all&nbsp;</a>\s\n <a href="JavaScript:;" id="importSelectNew"\s\n onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\s\n &nbsp;added&nbsp;</a> \s\n <a href="JavaScript:;" id="importSelectChanges"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\s\n &nbsp;changes&nbsp;</a> \s\n <a href="JavaScript:;" id="importSelectDifferences"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\s\n &nbsp;differences&nbsp;</a> \s\n <a href="JavaScript:;" id="importToggleFilter"\s\n onclick="onClickImportButton(this)" title="show/hide selection filter">\s\n &nbsp;filter&nbsp;</a> \s\n</span>\s\n<span style="float:right; padding:1px; white-space:nowrap">\s\n <a href="JavaScript:;" id="importListSmaller"\s\n onclick="onClickImportButton(this)" title="reduce list size">\s\n &nbsp;&#150;&nbsp;</a>\s\n <a href="JavaScript:;" id="importListLarger"\s\n onclick="onClickImportButton(this)" title="increase list size">\s\n &nbsp;+&nbsp;</a>\s\n <a href="JavaScript:;" id="importListMaximize"\s\n onclick="onClickImportButton(this)" title="maximize/restore list size">\s\n &nbsp;=&nbsp;</a>\s\n</span>\s\n<select id="importList" size=8 multiple\s\n onchange="setTimeout(\s'refreshImportList(\s'+this.selectedIndex+\s')\s',1)">\s\n <!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\s\n</select>\s\n<input type=checkbox id="chkAddTags" checked style="height:1em; width:auto"\s\n onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags &nbsp;\s\n<input type=checkbox id="chkImportTags" checked style="height:1em; width:auto"\s\n onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags &nbsp;\s\n<input type=checkbox id="chkKeepTags" checked style="height:1em; width:auto"\s\n onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags\s\n<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\s\n<div align=center>\s\n <input type=button id="importOpen" class="importButton" style="width:32%" value="open"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importStart" class="importButton" style="width:32%" value="import"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importClose" class="importButton" style="width:32%" value="close"\s\n onclick="onClickImportButton(this)">\s\n</div>\s\n<div id="importAskPanel">\s\n tiddler already exists:\s\n <input type=text id="importNewTitle" size=15 autocomplete=off">\s\n <div align=center>\s\n <input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importRename" class="importButton" style="width:23%" value="rename"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\s\n onclick="onClickImportButton(this)">\s\n </div>\s\n</div>\s\n';\n//}}}\n\n// // refresh listbox\n//{{{\nfunction refreshImportList(selectedIndex)\n{\n var theList = document.getElementById("importList");\n if (!theList) return;\n // if nothing to show, reset list content and size\n if (!config.macros.importTiddlers.inbound) \n {\n while (theList.length > 0) { theList.options[0] = null; }\n theList.options[0]=new Option('please open a document...',"",false,false);\n theList.size=config.macros.importTiddlers.listsize;\n return;\n }\n // get the sort order\n if (!selectedIndex) selectedIndex=0;\n if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading\n if (selectedIndex==1) config.macros.importTiddlers.sort='title';\n if (selectedIndex==2) config.macros.importTiddlers.sort='modified';\n if (selectedIndex==3) config.macros.importTiddlers.sort='tags';\n if (selectedIndex>3) {\n // display selected tiddler count\n for (var t=0,count=0; t < theList.options.length; t++) count+=(theList.options[t].selected&&theList.options[t].value!="")?1:0;\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n return; // no refresh needed\n }\n\n // get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)\n var tiddlers=config.macros.importTiddlers.inbound;\n tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n // add heading and control items to list\n var i=0;\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n theList.options[i++]=new Option(tiddlers.length+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);\n // output the tiddler list\n switch(config.macros.importTiddlers.sort)\n {\n case "title":\n for(var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);\n break;\n case "modified":\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });\n var lastSection = "";\n for(var t = 0; t < tiddlers.length; t++) {\n var tiddler = tiddlers[t];\n var theSection = tiddler.modified.toLocaleDateString();\n if (theSection != lastSection) {\n theList.options[i++] = new Option(theSection,"",false,false);\n lastSection = theSection;\n }\n theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);\n }\n break;\n case "tags":\n var theTitles = {}; // all tiddler titles, hash indexed by tag value\n var theTags = new Array();\n for(var t=0; t<tiddlers.length; t++) {\n var title=tiddlers[t].title;\n var tags=tiddlers[t].tags;\n for(var s=0; s<tags.length; s++) {\n if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }\n theTitles[tags[s]].push(title);\n }\n }\n theTags.sort();\n for(var tagindex=0; tagindex<theTags.length; tagindex++) {\n var theTag=theTags[tagindex];\n theList.options[i++]=new Option(theTag,"",false,false);\n for(var t=0; t<theTitles[theTag].length; t++)\n theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);\n }\n break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;\n if (theList.size>theList.options.length) theList.size=theList.options.length;\n}\n//}}}\n\n// // Control interactions\n//{{{\nfunction onClickImportButton(which)\n{\n // DEBUG alert(which.id);\n var theList = document.getElementById('importList');\n if (!theList) return;\n var thePanel = document.getElementById('importPanel');\n var theAskPanel = document.getElementById('importAskPanel');\n var theNewTitle = document.getElementById('importNewTitle');\n var count=0;\n switch (which.id)\n {\n case 'fileImportSource':\n case 'importOpen': // load import source into hidden frame\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n if (config.macros.importTiddlers.src=="") break;\n // Load document into hidden iframe so we can read it's DOM and fill the list\n loadImportFile(config.macros.importTiddlers.src,"all",null,null,function(src,filter,quiet,ask){window.refreshImportList(0);});\n break;\n case 'importSelectAll': // select all tiddler list items (i.e., not headings)\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=true;\n count++;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectNew': // select tiddlers not in current document\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importToggleFilter': // show/hide filter\n case 'importFilter': // apply filter\n alert("coming soon!");\n break;\n case 'importStart': // initiate the import processing\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.index=0;\n config.macros.importTiddlers.index=importTiddlers(0);\n importStopped();\n break;\n case 'importClose': // unload imported tiddlers or hide the import control panel\n // if imported tiddlers not loaded, close the import control panel\n if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n break;\n case 'importSkip': // don't import the tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status='skipped after asking'; // mark item as skipped\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item\n importStopped();\n break;\n case 'importRename': // change name of imported tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status = 'renamed from '+theImported.title; // mark item as renamed\n theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title\n theItem.value = theNewTitle.value; // change the listbox item text\n theItem.text = theNewTitle.value; // change the listbox item text\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importMerge': // join existing and imported tiddler content\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n var theText = theExisting.text+'\sn----\sn^^merged from: [['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\sn^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\sn'+theImported.text;\n var theDate = new Date();\n var theTags = theExisting.getTags()+' '+theImported.getTags();\n theImported.set(null,theText,null,theDate,theTags);\n theImported.status = 'merged with '+theExisting.title; // mark item as merged\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY hh:mm:ss");\n theImported.status += ' by '+theExisting.modifier;\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item\n importStopped();\n break;\n case 'importReplace': // substitute imported tiddler for existing tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n theImported.status = 'replaces '+theExisting.title; // mark item for replace\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY hh:mm:ss");\n theImported.status += ' by '+theExisting.modifier;\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importListSmaller': // decrease current listbox size, minimum=5\n if (theList.options.length==1) break;\n theList.size-=(theList.size>5)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListLarger': // increase current listbox size, maximum=number of items in list\n if (theList.options.length==1) break;\n theList.size+=(theList.size<theList.options.length)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListMaximize': // toggle listbox size between current and maximum\n if (theList.options.length==1) break;\n theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;\n break;\n }\n}\n//}}}\n\n// // re-entrant processing for handling import with interactive collision prompting\n//{{{\nfunction importTiddlers(startIndex)\n{\n if (!config.macros.importTiddlers.inbound) return -1;\n\n var theList = document.getElementById('importList');\n if (!theList) return;\n var t;\n // if starting new import, reset import status flags\n if (startIndex==0)\n for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)\n config.macros.importTiddlers.inbound[t].status="";\n for (var i=startIndex; i<theList.options.length; i++)\n {\n // if list item is not selected or is a heading (i.e., has no value), skip it\n if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))\n continue;\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==t) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theImported.title);\n // avoid redundant import for tiddlers that are listed multiple times (when 'by tags')\n if (theImported.status=="added")\n continue;\n // don't import the "ImportedTiddlers" history from the other document...\n if (theImported.title=='ImportedTiddlers')\n continue;\n // if tiddler exists and import not marked for replace or merge, stop importing\n if (theExisting && (theImported.status.substr(0,7)!="replace") && (theImported.status.substr(0,5)!="merge"))\n return i;\n // assemble tags (remote + existing + added)\n var newTags = "";\n if (config.macros.importTiddlers.importTags)\n newTags+=theImported.getTags() // import remote tags\n if (config.macros.importTiddlers.keepTags && theExisting)\n newTags+=" "+theExisting.getTags(); // keep existing tags\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newTags+=" "+config.macros.importTiddlers.newTags; // add new tags\n theImported.set(null,null,null,null,newTags.trim());\n // set the status to 'added' (if not already set by the 'ask the user' UI)\n theImported.status=(theImported.status=="")?'added':theImported.status;\n // do the import!\n store.addTiddler(theImported);\n store.setDirty(true);\n }\n return(-1); // signals that we really finished the entire list\n}\n//}}}\n\n//{{{\nfunction importStopped()\n{\n var theList = document.getElementById('importList');\n var theNewTitle = document.getElementById('importNewTitle');\n if (!theList) return;\n if (config.macros.importTiddlers.index==-1)\n importReport(); // import finished... generate the report\n else\n {\n // DEBUG alert('import stopped at: '+config.macros.importTiddlers.index);\n // import collision... show the ask panel and set the title edit field\n document.getElementById('importAskPanel').style.display='block';\n theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;\n }\n}\n//}}}\n
When you type more than three characters in the search box at the upper right, any matching tiddlers are automatically displayed with the text highlighted. There's a couple of minor issues: the highlights don't get removed when you clear the search, and occasionally, on some browsers, keystrokes get missed if you type quickly so you may need to click the 'search' button to manually trigger the search.
/***\n''InlineJavascriptPlugin for ~TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#InlineJavascriptPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nInsert Javascript executable code directly into your tiddler content. Lets you ''call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.\n!!!!!Usage\n<<<\nWhen installed, this plugin adds new wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be treated as embedded javascript and executed each time the tiddler is rendered.\n\n''Deferred execution from an 'onClick' link''\nBy including a label="..." parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered.\n\n''External script source files:''\nYou can also load javascript from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.\n\n''Defining javascript functions and libraries:''\nAlthough the external javascript file is loaded while the tiddler content is being rendered, any functions it defines will not be available for use until //after// the rendering has been completed. Thus, you cannot load a library and //immediately// use it's functions within the same tiddler. However, once that tiddler has been loaded, the library functions can be freely used in any tiddler (even the one in which it was initially loaded).\n\nTo ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that will be rendered as soon as your TiddlyWiki document is opened. For example, you could put your {{{<script src="..."></script>}}} syntax into a tiddler called LoadScripts, and then add {{{<<tiddler LoadScripts>>}}} in your MainMenu tiddler.\n\nSince the MainMenu is always rendered immediately upon opening your document, the library will always be loaded before any other tiddlers that rely upon the functions it defines. Loading an external javascript library does not produce any direct output in the tiddler, so these definitions should have no impact on the appearance of your MainMenu.\n\n''Creating dynamic tiddler content''\nAn important difference between this implementation of embedded scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document:\n* In a typical web document, you use the document.write() function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.\n* However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and completely replaces the entire ~TiddlyWiki document in your browser window.\n* To allow these scripts to work unmodified, the plugin automatically converts all occurences of document.write() so that the output is inserted into the tiddler content instead of replacing the entire ~TiddlyWiki document.\n\nIf your script does not use document.write() to create dynamically embedded content within a tiddler, your javascript can, as an alternative, explicitly return a text value that the plugin can then pass through the wikify() rendering engine to insert into the tiddler display. For example, using {{{return "thistext"}}} will produce the same output as {{{document.write("thistext")}}}.\n\n//Note: your script code is automatically 'wrapped' inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.//\n\n''Accessing the ~TiddlyWiki DOM''\nThe plugin provides one pre-defined variable, 'place', that is passed in to your javascript code so that it can have direct access to the containing DOM element into which the tiddler output is currently being rendered.\n\nAccess to this DOM element allows you to create scripts that can:\n* vary their actions based upon the specific location in which they are embedded\n* access 'tiddler-relative' information (use findContainingTiddler(place))\n* perform direct DOM manipulations (when returning wikified text is not enough)\n<<<\n!!!!!Examples\n<<<\nan "alert" message box:\n{{{\n<script>alert('InlineJavascriptPlugin: this is a demonstration message');</script>\n}}}\n<script>alert('InlineJavascriptPlugin: this is a demonstration message');</script>\n\ndynamic output:\n{{{\n<script>return (new Date()).toString();</script>\n}}}\n<script>return (new Date()).toString();</script>\n\nwikified dynamic output:\n{{{\n<script>return "link to current user: [["+config.options.txtUserName+"]]";</script>\n}}}\n<script>return "link to current user: [["+config.options.txtUserName+"]]";</script>\n\ndynamic output using 'place' to get size information for current tiddler\n{{{\n<script>\n if (!window.story) window.story=window;\n var title=story.findContainingTiddler(place).id.substr(7);\n return title+" is using "+store.getTiddlerText(title).length+" bytes";\n</script>\n}}}\n<script>\n if (!window.story) window.story=window;\n var title=story.findContainingTiddler(place).id.substr(7);\n return title+" is using "+store.getTiddlerText(title).length+" bytes";\n</script>\n\ncreating an 'onclick' button/link that runs a script\n{{{\n<script label="click here">\n if (!window.story) window.story=window;\n alert("Hello World!\snlinktext='"+place.firstChild.data+"'\sntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");\n</script>\n}}}\n<script label="click here">\n if (!window.story) window.story=window;\n alert("Hello World!\snlinktext='"+place.firstChild.data+"'\sntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");\n</script>\n\nloading a script from a source url\n{{{\n<script src="demo.js">return "loading demo.js..."</script>\n<script label="click to execute demo() function">demo()</script>\n}}}\nwhere http://www.TiddlyTools.com/demo.js contains:\n>function demo() { alert('this output is from demo(), defined in demo.js') }\n>alert('InlineJavascriptPlugin: demo.js has been loaded');\n<script src="demo.js">return "loading demo.js..."</script>\n<script label="click to execute demo() function">demo()</script>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''InlineJavascriptPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.01.05 [1.4.0]''\nadded support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.\n''2005.12.13 [1.3.1]''\nwhen catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski\n''2005.11.09 [1.3.0]''\nfor 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content\nBased on a suggestion by BradleyMeck\n''2005.11.08 [1.2.0]''\nhandle loading of javascript from an external URL via src="..." syntax\n''2005.11.08 [1.1.0]''\npass 'place' param into scripts to provide direct DOM access \n''2005.11.08 [1.0.0]''\ninitial release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.inlineJavascript= {major: 1, minor: 4, revision: 0, date: new Date(2006,1,5)};\n\nconfig.formatters.push( {\n name: "inlineJavascript",\n match: "\s\s<script",\n lookahead: "\s\s<script(?: src=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?(?: label=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?\s\s>((?:.|\s\sn)*?)\s\s</script\s\s>",\n\n handler: function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {\n if (lookaheadMatch[1]) { // load a script library\n // make script tag, set src, add to body to execute, then remove for cleanup\n var script = document.createElement("script"); script.src = lookaheadMatch[1];\n document.body.appendChild(script); document.body.removeChild(script);\n }\n if (lookaheadMatch[2] && lookaheadMatch[3]) { // create a link to an 'onclick' script\n // add a link, define click handler, save code in link (pass 'place'), set link attributes\n var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",lookaheadMatch[2]);\n link.onclick=function(){try{return(eval(this.code))}catch(e){alert(e.description?e.description:e.toString())}}\n link.code="function _out(place){"+lookaheadMatch[3]+"};_out(this);"\n link.setAttribute("href","javascript:;"); link.setAttribute("title",""); link.style.cursor="pointer";\n }\n else if (lookaheadMatch[3]) { // run inline script code\n var code="function _out(place){"+lookaheadMatch[3]+"};_out(w.output);"\n code=code.replace(/document.write\s(/gi,'place.innerHTML+=(');\n try { var out = eval(code); } catch(e) { out = e.description?e.description:e.toString(); }\n if (out && out.length) wikify(out,w.output);\n }\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n} )\n//}}}\n
InterfaceOptions are displayed when you click the 'options' button on the right. They are saved in a cookie on your browser, making them sticky between visits. RegExpSearch allows more complex search expressions; CaseSensitiveSearch does as it's name implies. The user name for edits should be set //before// starting to edit things (ouch. another bug).
InternetExplorer on Windows allows you to SaveChanges in TiddlyWiki. It will give you an ActiveX warning, and ask for your permission to proceed each time. It should work from version 4, but I have only extensively tested against version 6. I have found some annoying difficulties with XpServicePack2, but there's always FireFox.
The creator of TiddlyWiki and a technologist based in London. He does consultancy work through his company [[Osmosoft|http://www.osmosoft.com]], as well as pursuing some independent projects like TiddlyWiki.
* Name: Kevin Passino\n* Tags: <<tag passino>>
* All your action lists live in one HTML file, ideal for portability and simplicity.\n* [[Print3x5]] cards for your HipsterPDA right from your browser.\n* Runs locally, no network connection needed.\n* User defined CustomStyleSheet\n* Built with HTML, CSS, and Javascript, so it's easy to modify.\n* Really good incremental and regular expression search.\n* Your updates are date and name stamped (hover over the Timeline entries).\n* Your most recent version is automatically backed up when you SaveChanges (You can edit the Javascript to do incremental time-stamped backups. See the RevisionHistory for details).\n* Presumably, TiddlyWiki could run on a capable handheld device, but this is untested.
* Double click on a Tidder entry to edit it.\n* [Control + Enter] accepts your changes and switches out of editing mode\n* [Escape] abandons your changes and reverts the tiddler to it's previous state
!Bugs\n* ==StyleSheet suffers from a bug that truncates long entries with many non-alphanumeric characters, so if you try to put the entire set of styles in there, it probably won't work.==\n* =="Highlighted" and Hexidecimal colored text formatting is broken==\n* When printing WIN/IE 6 inserts one blank page because it does not recognize the :first-child CSS psuedo element.\n* ==WIN/IE 6 messes up list items when you edit a Tiddler with multiple headings.==\n\n!Annoyances\n* You have to do alot to customize your browser print settings to remove the page URL, pagination, timestamp, and ensure that the output is sized and paged correctly.\n* Firefox/Mac has no "page properties" interface for removing the page URL, page numbers, etc... from printed pages. This is pretty lame. Try entering about:config in Firefox's URL bar and look for "print" to configure it the hard way. Ask the Firefox development team to fix this.\n\n!Help out\n* If you you encounter new bugs, can help fix bugs, or can help make this usable in other browsers, or handhelds, go to the GTDTWForum. Thanks!
The format for PrettyLinks allows for links that open local or network folders. Depending on your browser and operating system, the folders are opened in Windows Explorer, the OS X Finder, or the browser itself.\n\nEdit this tiddler to see [[this link to a Windows network share|file://server/share/folder/path/name]], [[this link to a Windows drive-mapped folder|file:///c:/folder/path/name]] and [[this link to a Unix-style folder|file:///folder/path/name]].
*[[Actions List|Actions]]\n*[[Actions List with Labels|ActionsWithLabels]]\n\n*[[NEXT ACTIONS]]\n<part ContextList>\n<<forEachTiddler where 'tiddler.tags.contains("context") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title.toLowerCase() ascending write "'*[[' + tiddler.title + ']]\sn'">></part>\n*[[PROJECT LIST]]\n\n+++![Calendar]\n<<calendar thismonth>>\n===\n\n*<<newFromTemplatePopup label:"New... <arrow>" tooltip:"Create a new tiddler from a template." templateTag:"TiddlerTemplates">>\n\n*<<upload http://www.yoursite.com/gtdtw/store.php ugtdtw.htm twBackups>>\n*FormattingInstructions\n*DefaultTiddlers\n*MainMenu\n*ImportTiddlers
<<tiddler GTDProjectTemplate with: !gtdtw "Install and Maintain GTD Tiddly Wiki">>
/***\n| ''Name'' |Match Tag Chooser|\n| ''Version'' |0.1|\n| ''Source'' ||\n| ''Author'' |[[TedPavlic|ted@tedpavlic.com]]|\n| ''Type'' |Macro (for EditTemplate)|\n| ''Required'' |TiddlyWiki 2.0+|\n| ''License'' ||\n\n!Revision History\n|20060125|0.1|First release - very rough. I havent tested much.|\n\n\n!Description\nThis is a hack of SelectiveTagChooserMacro. It uses a regular expression to match listed tags. When you select a tag, it will tag the current tiddler with that tag.\n\nThis is intened to be used in EditTemplates, just as the existing tag chooser is.\n\n!Installation\nImport (or copy the contents of) this Tiddler into your Wiki.\nTag it with systemConfg, Save and Refresh.\n\n!Syntax\n|{{{<<MatchTagChooser [button label] [button tooltip] [regular expression] [optional "not"]>>}}}| It will list all tags matching the expression you give it (the expression is negated if the optional fourth parameter is "not". You will then be able to tag your current tiddler with a tag off the list.|\n\n!Examples\n{{{<<MatchTagChooser "Projects" "Tag this tiddler with a Project" "^![^ ]+$">>}}}\n<<MatchTagChooser "Projects" "Tag this tiddler with a Project" "^![^ ]+$">>\n{{{<<MatchTagChooser "GTD" "Tag this tiddler with a GTD-tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)">>}}}\n<<MatchTagChooser "GTD" "Tag this tiddler with a GTD-tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)">>\n{{{<<MatchTagChooser "non-GTD tags" "Tag this tiddler with a GTD tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)" not>>}}}\n<<MatchTagChooser "non-GTD tags" "Tag this tiddler with a non-GTD tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)" not>>\n\n!Credits\n[[Rich Carrillo|http://www.kultofbubb.net/tiddlywiki/]]\n\n!Roadmap - ToDo list\n\n!Code\n***/\n//{{{\n// default settings\nconfig.macros.MatchTagChooser = { }\n\nconfig.macros.MatchTagChooser.handler = function(place,macroName,params,wikifier,paramString,tiddler)\n{\n if(tiddler instanceof Tiddler)\n {\n var title = tiddler.title;\n var lingo = config.views.editor.tagChooser;\n var buttonLabel=params[0];\n var buttonTooltip=params[1];\n// start my stuff\n var allTags = store.getTags();\n var matchedTags = [];\n var tagRegExp = params[2];\n var notTagRegExp = ( params[3] && params[3] == "not" );\n\n var li,r;\n for(r=0;r<allTags.length;r++)\n {\n if( (notTagRegExp && ! allTags[r][0].match(tagRegExp)) || (!notTagRegExp && allTags[r][0].match(tagRegExp)) )\n {\n matchedTags.push(allTags[r][0]);\n }\n }\n matchedTags.sort();\n// end my stuff\n var ontagclick = function(e) {\n if (!e) var e = window.event;\n var tag = this.getAttribute("tag");\n story.setTiddlerTag(title,tag,0);\n return(false);\n };\n var onclick = function(e) {\n if (!e) var e = window.event;\n var popup = Popup.create(this);\n// start my stuff\n var tags = matchedTags;\n // var tags = store.getTags();\n// end my stuff\n if(tags.length == 0)\ncreateTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone);\n\n for (var t=0; t<tags.length; t++)\n {\n// start my stuff\n var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t],lingo.tagTooltip.format([tags[t]]),ontagclick);\n theTag.setAttribute("tag",tags[t]);\n\n // var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),ontagclick);\n // theTag.setAttribute("tag",tags[t][0]);\n// end my stuff\n }\n Popup.show(popup,false);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n };\n createTiddlyButton(place,buttonLabel,buttonTooltip,onclick);\n }\n}\n\n//}}}\n
/***\n| ''Name'' |Match Toggle Tag|\n| ''Version'' |0.1|\n| ''Source'' ||\n| ''Author'' |[[TedPavlic|ted@tedpavlic.com]]|\n| ''Type'' |Macro (for ViewTemplate)|\n| ''Required'' |TiddlyWiki 2.0+|\n| ''License'' ||\n\n!Revision History\n|20060125|0.1|First release - very rough. I havent tested much.|\n\n\n!Description\nThis is a hack of SelectiveTagChooserMacro with much code taken from ToggleTagMacro. It uses a regular expression to match listed tags. When you select a tag, it will toggle that tag on the current tiddler.\n\nThis is intened to be used in ViewTemplates.\n\n!Installation\nImport (or copy the contents of) this Tiddler into your Wiki.\nTag it with systemConfg, Save and Refresh.\n\n!Syntax\n|{{{<<MatchToggleTag [button label] [button tooltip] [regular expression] [optional "not"]>>}}}| It will list all tags matching the expression you give it (the expression is negated if the optional fourth parameter is "not"). You will then be able to tag your current tiddler with a tag off the list.|\n\n!Examples\n{{{<<MatchToggleTag "Projects" "Tag this tiddler with a Project" "^![^ ]+$">>}}}\n<<MatchToggleTag "Projects" "Tag this tiddler with a Project" "^![^ ]+$">>\n{{{<<MatchToggleTag "GTD" "Tag this tiddler with a GTD-tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)">>}}}\n<<MatchToggleTag "GTD" "Tag this tiddler with a GTD-tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)">>\n{{{<<MatchToggleTag "non-GTD tags" "Tag this tiddler with a GTD tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)" not>>}}}\n<<MatchToggleTag "non-GTD tags" "Tag this tiddler with a non-GTD tag" "^([!@][^ ]+$|action|context|done|next|project|somedayMaybe)" not>>\n\n!Credits\n[[Rich Carrillo|http://www.kultofbubb.net/tiddlywiki/]]\nToggleTagMacro\n\n!Roadmap - ToDo list\n\n!Code\n***/\n//{{{\n\n// This function contributed by Eric Shulman\nfunction toggleTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)==null) t.tags.push(tag)\n else t.tags.splice(t.tags.find(tag),1)\n}\n\n// default settings\nconfig.macros.MatchToggleTag = { }\n\nconfig.macros.MatchToggleTag.handler = function(place,macroName,params,wikifier,paramString,tiddler)\n{\n if(tiddler instanceof Tiddler)\n {\n var title = tiddler.title;\n var lingo = config.views.editor.tagChooser;\n var buttonLabel=params[0];\n var buttonTooltip=params[1];\n// start my stuff\n var allTags = store.getTags();\n var matchedTags = [];\n var tagRegExp = params[2];\n var notTagRegExp = ( params[3] && params[3] == "not" );\n\n var li,r;\n for(r=0;r<allTags.length;r++)\n {\n if( (notTagRegExp && ! allTags[r][0].match(tagRegExp)) || (!notTagRegExp && allTags[r][0].match(tagRegExp)) )\n {\n matchedTags.push(allTags[r][0]);\n }\n }\n matchedTags.sort();\n// end my stuff\n var ontagclick = function(e) {\n if (!e) var e = window.event;\n var tag = this.getAttribute("tag");\n toggleTag(title,tag);\n store.setDirty(true); // so TW knows it has to save now\n story.forEachTiddler(function(title,element) {\n story.refreshTiddler(title,false,true)\n });\n\n return false;\n };\n var onclick = function(e) {\n if (!e) var e = window.event;\n var popup = Popup.create(this);\n// start my stuff\n var tags = matchedTags;\n // var tags = store.getTags();\n// end my stuff\n if(tags.length == 0)\ncreateTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone);\n\n for (var t=0; t<tags.length; t++)\n {\n// start my stuff\n var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t],lingo.tagTooltip.format([tags[t]]),ontagclick);\n theTag.setAttribute("tag",tags[t]);\n\n // var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),ontagclick);\n // theTag.setAttribute("tag",tags[t][0]);\n// end my stuff\n }\n Popup.show(popup,false);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n };\n createTiddlyButton(place,buttonLabel,buttonTooltip,onclick);\n }\n}\n\n//}}}\n
* Time: \n* Participants: \n\n* Agenda: \n** \n\n* Meeting Notes:\n\n<<reminder year: month: day: title:"">>\n/% Tag with tag names of meeting participants so that the meeting\n shows up in the agenda under their names.\n\n Also consider tagging with a project tag to have a record of\n this meeting under any associated project.\n\n Edit [[Meeting]] TiddlerTemplate to get rid of this message. %/
* Time: 11:20AM \n* Participants: TedPavlic, KevinPassino\n\n* Agenda: \n** Discuss new simulations of speed-accuracy prey model\n\n* Meeting Notes:\n\n<<reminder year:2006 month:2 day:13 title:"Passino meeting">>
MicroContent being a fashionable word for self-contained fragments of content that are typically smaller than entire pages. Often MicroContent is presented via some kind of aggregation that reduces the perceptual shock and resource cost of context switching (eg Blogs aggregating several entries onto a page or Flickr presenting photos in an album). This TiddlyWiki aggregates MicroContent items that I call 'tiddlers' into pages that are loaded in one gulp and progressively displayed as the user clicks hypertext links to read them.
Some milk
<<forEachTiddler\n where\n "tiddler.tags.containsAll(['next','action']) && ! tiddler.tags.contains('done') && ! tiddler.tags.contains('TiddlerTemplates')"\n sortBy \n"getSortedTagsText(tiddler,['next','action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;}'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['next','action']) ? ' (' + getSortedTagsText(tiddler, ['next','action']) + ')' : '' ) + '\sn'"\n>>
Nathan is a web developer based in Los Angeles. His website is [[Snapgrid.com|http://snapgrid.com]]. Have questions, comments, or suggestions? Visit the GTDTWForum.
/***\n''NestedSlidersPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman\nsource: http://www.TiddlyTools.com/#NestedSlidersPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nQuickly make any tiddler content into an expandable 'slider' panel, without needing to create a separate tiddler to contain the slider content. Optional syntax allows ''default to open'', ''custom button label/tooltip'' and ''automatic blockquote formatting.''\n\nYou can also 'nest' these sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created. This is most useful when converting existing in-line text content to create in-line annotations, footnotes, context-sensitive help, or other subordinate information displays.\n\nFor more details, please click on a section headline below:\n++++!!!!![Configuration]>\nDebugging messages for 'lazy sliders' deferred rendering:\n<<option chkDebugLazySliderDefer>> show debugging alert when deferring slider rendering\n<<option chkDebugLazySliderRender>> show debugging alert when deferred slider is actually rendered\n===\n++++!!!!![Usage]>\nWhen installed, this plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content. Use {{{+++}}} and {{{===}}} to delimit the slider content. Additional optional syntax elements let you specify\n*default to open\n*cookiename\n*heading level\n*floater\n*rollover\n*custom label/tooltip\n*automatic blockquote\n*deferred rendering\nThe complete syntax, using all options, is:\n//{{{\n++++(cookiename)!!!!!^*[label|tooltip]>...\ncontent goes here\n===\n//}}}\nwhere:\n* {{{+++}}} (or {{{++++}}}) and {{{===}}}^^\nmarks the start and end of the slider definition, respectively. When the extra {{{+}}} is used, the slider will be open when initially displayed.^^\n* {{{(cookiename)}}}^^\nsaves the slider opened/closed state, and restores this state whenever the slider is re-rendered.^^\n* {{{!}}} through {{{!!!!!}}}^^\ndisplays the slider label using a formatted headline (Hn) style instead of a button/link style^^\n* {{{"^"}}} //(without the quotes)//^^\nmakes the slider 'float' on top of other content rather than shifting that content downward^^\n* {{{"*"}}} //(without the quotes)//^^\nautomatically opens/closes slider on "rollover" as well as when clicked^^\n* {{{[label]}}} or {{{[label|tooltip]}}}^^\nuses custom label/tooltip. (defaults are: ">" (more) and "<" (less)^^\n* {{{">"}}} //(without the quotes)//^^\nautomatically adds blockquote formatting to slider content^^\n* {{{"..."}}} //(without the quotes)//^^\ndefers rendering of closed sliders until the first time they are opened. //Note: deferred rendering may produce unexpected results in some cases. Use with care.//^^\n\n//Note: to make slider definitions easier to read and recognize when editing a tiddler, newlines immediately following the {{{+++}}} 'start slider' or preceding the {{{===}}} 'end slider' sequence are automatically supressed so that excess whitespace is eliminated from the output.//\n===\n++++!!!!![Examples]>\nsimple in-line slider: \n{{{\n+++\n content\n===\n}}}\n+++\n content\n===\n----\nuse a custom label and tooltip: \n{{{\n+++[label|tooltip]\n content\n===\n}}}\n+++[label|tooltip]\n content\n===\n----\ncontent automatically blockquoted: \n{{{\n+++>\n content\n===\n}}}\n+++>\n content\n===\n----\nall options combined //(default open, cookie, heading, floater, rollover, label/tooltip, blockquoted, deferred)//\n{{{\n++++(testcookie)!!!^*[label|tooltip]>...\n content\n===\n}}}\n++++(testcookie)!!!^*[label|tooltip]>...\n content\n===\n----\ncomplex nesting example:\n{{{\n+++^[get info...|click for information]\n put some general information here, plus a floating slider with more specific info:\n +++^[view details...|click for details]\n put some detail here, which could include a rollover with a +++^*[glossary definition]explaining technical terms===\n ===\n===\n}}}\n+++^[get info...|click for information]\n put some general information here, plus a floating slider with more specific info:\n +++^[view details...|click for details]\n put some detail here, which could include a rollover with a +++^*[glossary definition]explaining technical terms===\n ===\n===\n----\nnested floaters\n>menu: <<tiddler NestedSlidersExample>>\n(see [[NestedSlidersExample]] for definition)\n----\n===\n+++!!!!![Installation]>\nimport (or copy/paste) the following tiddlers into your document:\n''NestedSlidersPlugin'' (tagged with <<tag systemConfig>>)\n===\n+++!!!!![Revision History]>\n\n++++[2006.02.04 - 1.7.5]\nadd 'var' to unintended global variable declarations to avoid FireFox 1.5.0.1 crash bug when assigning to globals\n===\n\n++++[2006.01.18 - 1.7.4]\nonly define adjustSliderPos() function if it has not already been provided by another plugin. This lets other plugins 'hijack' the function even when they are loaded first.\n===\n\n++++[2006.01.16 - 1.7.3]\nadded adjustSliderPos(place,btn,panel,panelClass) function to permit specialized logic for placement of floating panels. While it provides improved placement for many uses of floating panels, it exhibits a relative offset positioning error when used within *nested* floating panels. Short-term workaround is to only adjust the position for 'top-level' floaters.\n===\n\n++++[2006.01.16 - 1.7.2]\nadded button property to slider panel elements so that slider panel can tell which button it belongs to. Also, re-activated and corrected animation handling so that nested sliders aren't clipped by hijacking Slider.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends\n===\n\n++++[2006.01.14 - 1.7.1]\nadded optional "^" syntax for floating panels. Defines new CSS class, ".floatingPanel", as an alternative for standard in-line ".sliderPanel" styles.\n===\n\n++++[2006.01.14 - 1.7.0]\nadded optional "*" syntax for rollover handling to show/hide slider without requiring a click (Based on a suggestion by tw4efl)\n===\n\n+++[2006.01.03 - 1.6.2]\nWhen using optional "!" heading style, instead of creating a clickable "Hn" element, create an "A" element inside the "Hn" element. (allows click-through in SlideShowPlugin, which captures nearly all click events, except for hyperlinks)\n===\n\n+++[2005.12.15 - 1.6.1]\nadded optional "..." syntax to invoke deferred ('lazy') rendering for initially hidden sliders\nremoved checkbox option for 'global' application of lazy sliders\n===\n\n+++[2005.11.25 - 1.6.0]\nadded optional handling for 'lazy sliders' (deferred rendering for initially hidden sliders)\n===\n\n+++[2005.11.21 - 1.5.1]\nrevised regular expressions: if present, a single newline //preceding// and/or //following// a slider definition will be suppressed so start/end syntax can be place on separate lines in the tiddler 'source' for improved readability. Similarly, any whitespace (newlines, tabs, spaces, etc.) trailing the 'start slider' syntax or preceding the 'end slider' syntax is also suppressed.\n===\n\n+++[2005.11.20 - 1.5.0]\n added (cookiename) syntax for optional tracking and restoring of slider open/close state\n===\n\n+++[2005.11.11 - 1.4.0]\n added !!!!! syntax to render slider label as a header (Hn) style instead of a button/link style\n===\n\n+++[2005.11.07 - 1.3.0]\n removed alternative syntax {{{(((}}} and {{{)))}}} (so they can be used by other\n formatting extensions) and simplified/improved regular expressions to trim multiple excess newlines\n===\n\n+++[2005.11.05 - 1.2.1]\n changed name to NestedSlidersPlugin\n more documentation\n===\n\n+++[2005.11.04 - 1.2.0]\n added alternative character-mode syntax {{{(((}}} and {{{)))}}}\n tweaked "eat newlines" logic for line-mode {{{+++}}} and {{{===}}} syntax\n===\n\n+++[2005.11.03 - 1.1.1]\n fixed toggling of default tooltips ("more..." and "less...") when a non-default button label is used\n code cleanup, added documentation\n===\n\n+++[2005.11.03 - 1.1.0]\n changed delimiter syntax from {{{(((}}} and {{{)))}}} to {{{+++}}} and {{{===}}}\n changed name to EasySlidersPlugin\n===\n\n+++[2005.11.03 - 1.0.0]\n initial public release\n===\n\n===\n+++!!!!![Credits]>\nThis feature was implemented by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]] with research, programming and suggestions from RodneyGomes, GeoffSlocock, and PaulPetterson\n===\n***/\n// //+++!!!!![Code]\n//{{{\nversion.extensions.nestedSliders = {major: 1, minor: 7, revision: 5, date: new Date(2006,2,4)};\n//}}}\n\n//{{{\n// options for deferred rendering of sliders that are not initially displayed\nif (config.options.chkDebugLazySliderDefer==undefined) config.options.chkDebugLazySliderDefer=false;\nif (config.options.chkDebugLazySliderRender==undefined) config.options.chkDebugLazySliderRender=false;\n\n// default styles for 'floating' class\nsetStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \s\n background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");\n//}}}\n\n//{{{\nconfig.formatters.push( {\n name: "nestedSliders",\n match: "\s\sn?\s\s+{3}",\n terminator: "\s\ss*\s\s={3}\s\sn?",\n lookahead: "\s\sn?\s\s+{3}(\s\s+)?(\s\s([^\s\s)]*\s\s))?(\s\s!*)?(\s\s^)?(\s\s*)?(\s\s[[^\s\s]]*\s\s])?(\s\s>)?(\s\s.\s\s.\s\s.)?\s\ss*",\n handler: function(w)\n {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n // location for rendering button and panel\n var place=w.output;\n\n // default to closed, no cookie\n var show="none"; var title=">"; var tooltip="show"; var cookie="";\n\n // extra "+", default to open\n if (lookaheadMatch[1])\n { show="block"; title="<"; tooltip="hide"; }\n\n // cookie, use saved open/closed state\n if (lookaheadMatch[2]) {\n cookie=lookaheadMatch[2].trim().substr(1,lookaheadMatch[2].length-2);\n cookie="chkSlider"+cookie;\n if (config.options[cookie]==undefined)\n { config.options[cookie] = (show=="block") }\n if (config.options[cookie])\n { show="block"; title="<"; tooltip="hide"; }\n else\n { show="none"; title=">"; tooltip="show"; }\n }\n\n // custom label/tooltip\n if (lookaheadMatch[6]) {\n title = lookaheadMatch[6].trim().substr(1,lookaheadMatch[6].length-2);\n var pos=title.indexOf("|");\n if (pos!=-1)\n { tooltip = title.substr(pos+1,title.length); title = title.substr(0,pos); }\n else\n { tooltip += " "+title; }\n }\n\n // create the button\n if (lookaheadMatch[3]) { // use "Hn" header format instead of button/link\n var lvl=(lookaheadMatch[3].length>6)?6:lookaheadMatch[3].length;\n var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,null,title);\n btn.onclick=onClickNestedSlider;\n btn.setAttribute("href","javascript:;");\n btn.setAttribute("title",tooltip);\n }\n else\n var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider);\n btn.sliderCookie = cookie; // save the cookiename (if any) in the button object\n\n // "non-click" MouseOver open/close slider\n if (lookaheadMatch[5]) btn.onmouseover=onClickNestedSlider;\n\n // create slider panel\n var panelClass=lookaheadMatch[4]?"floatingPanel":"sliderPanel";\n var panel=createTiddlyElement(place,"div",null,panelClass,null);\n panel.style.display = show;\n panel.button = btn; // so the slider panel know which button it belongs to\n btn.sliderPanel=panel;\n\n // render slider (or defer until shown) \n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n if (lookaheadMatch[1]||!lookaheadMatch[8]) {\n // render now if "++++" (init open) or NOT "..." (deferred render)\n w.subWikify(lookaheadMatch[7]?createTiddlyElement(panel,"blockquote"):panel,this.terminator);\n // align slider/floater position with button\n adjustSliderPos(place,btn,panel,panelClass);\n }\n else {\n var src = w.source.substr(w.nextMatch);\n var endpos=findMatchingDelimiter(src,"+++","===");\n panel.setAttribute("raw",src.substr(0,endpos));\n panel.setAttribute("blockquote",lookaheadMatch[7]?"true":"false");\n panel.setAttribute("rendered","false");\n w.nextMatch += endpos+3;\n if (w.source.substr(w.nextMatch,1)=="\sn") w.nextMatch++;\n if (config.options.chkDebugLazySliderDefer) alert("deferred '"+title+"':\sn\sn"+panel.getAttribute("raw"));\n }\n }\n }\n }\n)\n\n// TBD: ignore 'quoted' delimiters (e.g., "{{{+++foo===}}}" isn't really a slider)\nfunction findMatchingDelimiter(src,starttext,endtext) {\n var startpos = 0;\n var endpos = src.indexOf(endtext);\n // check for nested delimiters\n while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {\n // count number of nested 'starts'\n var startcount=0;\n var temp = src.substring(startpos,endpos-1);\n var pos=temp.indexOf(starttext);\n while (pos!=-1) { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }\n // set up to check for additional 'starts' after adjusting endpos\n startpos=endpos+endtext.length;\n // find endpos for corresponding number of matching 'ends'\n while (startcount && endpos!=-1) {\n endpos = src.indexOf(endtext,endpos+endtext.length);\n startcount--;\n }\n }\n return (endpos==-1)?src.length:endpos;\n}\n//}}}\n\n//{{{\nfunction onClickNestedSlider(e)\n{\n if (!e) var e = window.event;\n var theTarget = resolveTarget(e);\n var theLabel = theTarget.firstChild.data;\n var theSlider = theTarget.sliderPanel\n var isOpen = theSlider.style.display!="none";\n // if using default button labels, toggle labels\n if (theLabel==">") theTarget.firstChild.data = "<";\n else if (theLabel=="<") theTarget.firstChild.data = ">";\n // if using default tooltips, toggle tooltips\n if (theTarget.getAttribute("title")=="show")\n theTarget.setAttribute("title","hide");\n else if (theTarget.getAttribute("title")=="hide")\n theTarget.setAttribute("title","show");\n if (theTarget.getAttribute("title")=="show "+theLabel)\n theTarget.setAttribute("title","hide "+theLabel);\n else if (theTarget.getAttribute("title")=="hide "+theLabel)\n theTarget.setAttribute("title","show "+theLabel);\n // deferred rendering (if needed)\n if (theSlider.getAttribute("rendered")=="false") {\n if (config.options.chkDebugLazySliderRender)\n alert("rendering '"+theLabel+"':\sn\sn"+theSlider.getAttribute("raw"));\n var place=theSlider;\n if (theSlider.getAttribute("blockquote")=="true")\n place=createTiddlyElement(place,"blockquote");\n wikify(theSlider.getAttribute("raw"),place);\n theSlider.setAttribute("rendered","true");\n }\n // show/hide the slider\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n theSlider.style.display = isOpen ? "none" : "block";\n if (this.sliderCookie && this.sliderCookie.length)\n { config.options[this.sliderCookie]=!isOpen; saveOptionCookie(this.sliderCookie); }\n // align slider/floater position with target button\n adjustSliderPos(theSlider.parentNode,theTarget,theSlider,theSlider.className);\n return false;\n}\n\n// hijack animation handler 'stop' handler so overflow is visible after animation has completed\nSlider.prototype.coreStop = Slider.prototype.stop;\nSlider.prototype.stop = function() { this.coreStop(); this.element.style.overflow = "visible"; }\n\n// adjust panel position based on button position\nif (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel,panelClass) {\n ///////////////////////////////////////////////////////////////////////////////\n /// EXPERIMENTAL HACK - WORKS IN SOME CASES, NOT IN OTHERS\n ///////////////////////////////////////////////////////////////////////////////\n // "if this panel is floating and the parent is not also a floating panel"...\n if (panelClass=="floatingPanel" && place.className!="floatingPanel") {\n var left=0; var top=btn.offsetHeight;\n if (place.style.position!="relative") { left+=findPosX(btn); top+=findPosY(btn); }\n panel.style.left=left+"px"; panel.style.top=top+"px";\n }\n}\n//}}}\n// //===
/***\n''NewDocumentPlugin for TiddlyWiki version 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#NewDocumentPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nQuickly create new TiddlyWiki documents from your existing document, with just one click! Use the {{{<<newDocument>>}}} macro to place a "new document" link into your sidebar/mainmenu/any tiddler (wherever you like). Select this command to automatically create a "new.html" document containing a specific set of tagged tiddlers. Optional parameters let you specify an alternate path/filename for the new file, or different combinations of tags to match (using AND, OR, NOT and parentheses to form complex matches). You can also indicate "ask" for either parameter, which will trigger a prompt for input when the command is selected.\n\n!!!!!Usage\n<<<\n{{{<<newDocument filename tags>>}}}\n where:\n* ''filename'' is any local path-and-filename. If no parameters are provided, the default is to create the file "new.htm" in the current directory. If a filename is provided without a path (i.e., there is no "/" in the input), then the current directory is also assumed. Otherwise, this parameter is expected to contain the complete path and filename needed to write the file to your local hard disk.\n* ''tags'' an //expression// that can be a single tag value, a space-separated list of tags, or a logical formula using AND, OR, NOT and parentheses to create complex matches. The default tag expression includes only tiddlers tagged with <<tag includeNew>>or<<tag systemTiddlers>>. If the special keyword "ask" is used in place of either parameter then, when the command link is selected, a browser prompt() message box will be automatically displayed so you can input the parameter value(s) "on-the-fly".\n\n<<<\n!!!!!Examples:\n<<<\n{{{<<newDocument>>}}}\nequivalent to {{{<<newDocument new.htm includeNew systemTiddlers>>}}}\ncreates default "new.htm" containing tiddlers tagged with either<<tag includeNew>>or<<tag systemTiddlers>>\ntry it: <<newDocument>>\n\n{{{<<newDocument empty.html systemTiddlers>>}}}\ncreates "empty.html" containing only tiddlers tagged with<<tag systemTiddlers>>\n//(reproduces old-style (pre 2.0.2) empty file)//\ntry it: <<newDocument empty.html systemTiddlers>>\n\n{{{<<newDocument ask ask>>}}}\nprompts for path/file, prompts for tags to match\ntry it: <<newDocument ask ask>>\n<<<\n!!!!!Installation\n<<<\nImport (or copy/paste) the following tiddlers into your document:\n''NewDocumentPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.02.24 [1.1.2]''\nFix incompatiblity with TW 2.0.5 by removing custom definition of getLocalPath() (which is now part of TW core)\n''2006.02.03 [1.1.1]''\nconcatentate 'extra' params so that tag expressions don't have to be quoted\nmoved all text to 'formatted' string definitions for easier translation.\neven better documentation and some minor code cleanup\n''2006.02.03 [1.1.0]''\nadded support for tag EXPRESSIONS\nplus improved documentation and code cleanup\n''2006.02.03 [1.0.0]''\nCreated.\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.newDocument = {major: 1, minor: 1, revision: 2, date: new Date(2006,2,24)};\n\nconfig.macros.newDocument = {\n label: "new document",\n prompt: "create a new TiddlyWiki 'starter' document",\n newtag: "includeNew OR systemTiddlers",\n newfile: "new.htm",\n fileprompt: "Enter a new filename",\n tagprompt: "Enter tag(s) to match (use AND, OR, NOT)",\n okmsg: "%0 tiddlers written to %1",\n failmsg: "An error occurred while creating '%0'",\n tagerrmsg: "Error in tag filter '%0'"\n};\n\nconfig.macros.newDocument.handler = function(place,macroName,params) {\n var btn=createTiddlyButton(place,this.label,this.prompt,onClickNewDocument);\n btn.newfile=config.macros.newDocument.newfile;\n if (params[0]) btn.newfile=params.shift();\n btn.newtag=config.macros.newDocument.newtag;\n if (params[0]) btn.newtag=params.join(" ");\n}\n\n// IE needs explicit global scoping for functions called by browser events\nwindow.onClickNewDocument=function(e)\n{\n if (!e) var e = window.event;\n\n // get the TiddlyWiki core code source\n var sourcefile=getLocalPath(document.location.toString());\n var source=loadFile(sourcefile);\n if(source==null) { alert(config.messages.cantSaveError); return null; }\n var posOpeningDiv=source.indexOf(startSaveArea);\n var posClosingDiv=source.lastIndexOf(endSaveArea);\n if((posOpeningDiv==-1)||(posClosingDiv==-1)) { alert(config.messages.invalidFileError.format([sourcefile])); return; }\n\n // get output path/filename\n var newfile=resolveTarget(e).newfile;\n if (newfile=="ask") newfile=prompt(config.macros.newDocument.fileprompt, config.macros.newDocument.newfile);\n if (!newfile) return; // cancelled by user\n // if specified file does not include a path, assemble fully qualified path and filename\n var slashpos=newfile.lastIndexOf("/"); if (slashpos==-1) slashpos=newfile.lastIndexOf("\s\s");\n if (slashpos==-1) {\n var path=getLocalPath(document.location.toString());\n var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\s\s"); \n if (slashpos!=-1) path = path.substr(0,slashpos); // remove filename from path\n newfile=path+(config.browser.isWindows?"\s\s":"/")+newfile;\n }\n\n // get the tiddler divs\n var match=resolveTarget(e).newtag;\n if (match=="ask")\n match=prompt(config.macros.newDocument.tagprompt,config.macros.newDocument.newtag);\n if (!match) return; // cancelled by user\n var storeAreaDivs=[];\n var tiddlers=store.getTiddlers('title');\n for (var i=0; i<tiddlers.length; i++)\n if (matchTags(tiddlers[i],match))\n storeAreaDivs.push(tiddlers[i].saveToDiv());\n\n // construct and write the file output\n var out=source.substr(0,posOpeningDiv+startSaveArea.length)+storeAreaDivs.join("\sn")+"\sn\st\st"+source.substr(posClosingDiv);\n if (saveFile(newfile,out))\n var msg=config.macros.newDocument.okmsg.format([storeAreaDivs.length,newfile]);\n else\n var msg=config.macros.newDocument.failmsg.format([newfile]);\n clearMessage(); displayMessage(msg);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n\n//{{{\nif (!window.matchTags) window.matchTags=function(tiddler,cond)\n{\n if (!cond||!cond.trim().length) return false;\n\n // build a regex of all tags as a big-old regex that \n // OR's the tags together (tag1|tag2|tag3...) in length order\n var tgs = store.getTags();\n if ( tgs.length == 0 ) return results ;\n tags = tgs.sort( function(a,b){return (a[0].length<b[0].length)-(a[0].length>b[0].length);});\n var exp = "(" + tags.join("|") + ")" ;\n exp = exp.replace( /(,[\sd]+)/g, "" ) ;\n var regex = new RegExp( exp, "ig" );\n\n // build a string such that an expression that looks like this: tag1 AND tag2 OR NOT tag3\n // turns into : /tag1/.test(...) && /tag2/.test(...) || ! /tag2/.test(...)\n cond = cond.replace( regex, "/$1\s\s|/.test(tiddlerTags)" );\n cond = cond.replace( /\ssand\ss/ig, " && " ) ;\n cond = cond.replace( /\ssor\ss/ig, " || " ) ;\n cond = cond.replace( /\ss?not\ss/ig, " ! " ) ;\n\n // if a boolean uses a tag that doesn't exist - it will get left alone \n // (we only turn existing tags into actual tests).\n // replace anything that wasn't found as a tag, AND, OR, or NOT with the string "false"\n // if the tag doesn't exist then /tag/.test(...) will always return false.\n cond = cond.replace( /(\ss|^)+[^\s/\s|&!][^\ss]*/g, "false" ) ;\n\n // make a string of the tags in the tiddler and eval the 'cond' string against that string \n // if it's TRUE then the tiddler qualifies!\n var tiddlerTags = (tiddler.tags?tiddler.tags.join("|"):"")+"|" ;\n try { if ( eval( cond ) ) return true; }\n catch( e ) { displayMessage(config.macros.newDocument.tagerrmsg.format([e])); }\n return false;\n}\n//}}}
This ThirdVersion of TiddlyWiki adds:\n* the ability to easily SaveChanges on FireFox and InternetExplorer\n* a new liquid CSS layout that fills the width of the browser window\n* InterfaceOptions revealed by clicking the new 'options' button on the right\n* some BugFixes\n* KeyboardShortcuts so you can finish editing a tiddler with Control-Enter or abandon it with Escape\n* a more flexible OpenSourceLicense\n* a bunch of features from IsaoSonobe's [[adaptation|http://www-gauge.scphys.kyoto-u.ac.jp/~sonobe/OgreKit/OgreKitWiki.html]] of TiddlyWiki including ExtendedFormatting, NonWikiWordLinks, PrettyLinks, [[Headings]], BulletPoints, NumberedLists, HtmlTables, BlockQuotes, HorizontalRules and...\n* ...EmbeddedImages:\n[img[http://img110.echo.cx/img110/139/gorilla8nw.jpg]]
/***\n|Name|NewHereCommand|\n|Source|http://simonbaird.com/mptw/#NewHereCommand|\n|Version|1.0|\n\nCode originally by ArphenLin. Small tweak by SimonBaird\nhttp://aiddlywiki.sourceforge.net/NewHere_demo.html#NewHereCommand\nTo use this you must edit your ViewTemplate and add newHere to the toolbar div, eg\n{{{<div class='toolbar' macro='toolbar ... newHere'></div>}}}\n***/\n\n//{{{\n\nconfig.commands.newHere = {\n text: 'new here',\n tooltip: 'Create a new tiddler tagged as this tiddler',\n handler: function(e,src,title) {\n if (!readOnly) {\n clearMessage();\n var t=document.getElementById('tiddler'+title);\n story.displayTiddler(t,config.macros.newTiddler.title,DEFAULT_EDIT_TEMPLATE);\n story.setTiddlerTag(config.macros.newTiddler.title, title, 0);\n story.focusTiddler(config.macros.newTiddler.title,"title");\n return false;\n }\n }\n};\n\n//}}}
TiddlyWiki is a spare time project that I'm making available under an OpenSourceLicense. Accordingly, there's no warranty on it, and you can only use it at your own risk. To report bugs go to the GTDTWForum.
To make a tiddler that doesn't have a WikiWord as it's name, you can enclose the name in [[double square brackets]] - edit this tiddler to see an example. After saving the tiddler you can then click on the link to create the new tiddler. NonWikiWordLinks permits tiddlers to be created with names that are made from character sets that don't have upper and lower case.
start\n#item1\n#item2\n##item2.1\n##item2.2\n##item2.3\n#item3\n##item3.1\n###item3.1.1\n###item3.1.2\n\nend
TiddlyWiki is published under a BSD OpenSourceLicense that gives you the freedom to use it pretty much however you want, including for commercial purposes, as long as you keep my copyright notice. I'd appreciate a link back to http://www.tiddlywiki.com as well.
<part OpenProjects>\n! Open Projects\n<<forEachTiddler where 'tiddler.tags.contains("project") && ! tiddler.tags.contains("done") && ! tiddler.tags.contains("somedayMaybe") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title ascending write "'*[[' + tiddler.title + ']]\sn'">>\n</part>\n<part DoneProjects>\n! Done Projects\n<<forEachTiddler where 'tiddler.tags.containsAll(["project","done"]) && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title ascending write "'*[[' + tiddler.title + ']]\sn'">>\n</part>\n<part SomedayMaybeProjects>\n! Someday Maybe Projects\n<<forEachTiddler where 'tiddler.tags.containsAll(["project","somedayMaybe"]) && ! tiddler.tags.contains("done") && ! tiddler.tags.contains("TiddlerTemplates")' sortBy tiddler.title ascending write "'*[[' + tiddler.title + ']]\sn'">></part>
<div id='header'>\n<div id='titleLine'>\n<span id='siteTitle' refresh='content' tiddler='SiteTitle'></span>\n<span id='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n</div>\n<div id='sidebar'>\n<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>\n<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div><div id="licensePanel">\n<a rel="license" href="http://shared.snapgrid.com/gtd_tiddlywiki.html#RevisionHistory" target="_new">GTDTW Version <span macro="version"></span></a>\n<a rel="license" href="http://www.tiddlywiki.com" target="_new">\nTiddlyWiki is published by Jeremy Ruston at Osmosoft under a BSD open source license</a>\n<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>\n<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>\n<div id='displayArea'>\n<div id='messageArea'></div>\n<div id='tiddlerDisplay'></div>
/***\n|<html><a name="Top"/></html>''Name:''|PartTiddlerPlugin|\n|''Version:''|1.0.3 (2006-02-26)|\n|''Source:''|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|2.0|\n|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|\n!Table of Content<html><a name="TOC"/></html>\n* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Description',null, event)">Description, Syntax</a></html>\n* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Applications',null, event)">Applications</a></html>\n** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('LongTiddler',null, event)">Refering to Paragraphs of a Longer Tiddler</a></html>\n** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Citation',null, event)">Citation Index</a></html>\n** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('TableCells',null, event)">Creating "multi-line" Table Cells</a></html>\n** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Tabs',null, event)">Creating Tabs</a></html>\n** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Sliders',null, event)">Using Sliders</a></html>\n* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Revisions',null, event)">Revision History</a></html>\n* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Code',null, event)">Code</a></html>\n!Description<html><a name="Description"/></html>\nWith the {{{<part aPartName> ... </part>}}} feature you can structure your tiddler text into separate (named) parts. \nEach part can be referenced as a "normal" tiddler, using the "//tiddlerName//''/''//partName//" syntax (e.g. "About/Features"). E.g. you may create links to the parts, use it in {{{<<tiddler...>>}}} or {{{<<tabs...>>}}} macros etc.\n\n''Syntax:'' \n|>|''<part'' //partName// [''hidden''] ''>'' //any tiddler content// ''</part>''|\n|//partName//|The name of the part. You may reference a part tiddler with the combined tiddler name "//nameOfContainerTidder//''/''//partName//.|\n|''hidden''|When defined the content of the part is not displayed in the container tiddler. But when the part is explicitly referenced (e.g. in a {{{<<tiddler...>>}}} macro or in a link) the part's content is displayed.|\n|<html><i>any&nbsp;tiddler&nbsp;content</i></html>|<html>The content of the part.<br>A part can have any content that a "normal" tiddler may have, e.g. you may use all the formattings and macros defined.</html>|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!Applications<html><a name="Applications"/></html>\n!!Refering to Paragraphs of a Longer Tiddler<html><a name="LongTiddler"/></html>\nAssume you have written a long description in a tiddler and now you want to refer to the content of a certain paragraph in that tiddler (e.g. some definition.) Just wrap the text with a ''part'' block, give it a nice name, create a "pretty link" (like {{{[[Discussion Groups|Introduction/DiscussionGroups]]}}}) and you are done.\n\nNotice this complements the approach to first writing a lot of small tiddlers and combine these tiddlers to one larger tiddler in a second step (e.g. using the {{{<<tiddler...>>}}} macro). Using the ''part'' feature you can first write a "classic" (longer) text that can be read "from top to bottom" and later "reuse" parts of this text for some more "non-linear" reading.\n\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!!Citation Index<html><a name="Citation"/></html>\nCreate a tiddler "Citations" that contains your "citations". \nWrap every citation with a part and a proper name. \n\n''Example''\n{{{\n<part BAX98>Baxter, Ira D. et al: //Clone Detection Using Abstract Syntax Trees.// \nin //Proc. ICSM//, 1998.</part>\n\n<part BEL02>Bellon, Stefan: //Vergleich von Techniken zur Erkennung duplizierten Quellcodes.// \nThesis, Uni Stuttgart, 2002.</part>\n\n<part DUC99>Ducasse, Stéfane et al: //A Language Independent Approach for Detecting Duplicated Code.// \nin //Proc. ICSM//, 1999.</part>\n}}}\n\nYou may now "cite" them just by using a pretty link like {{{[[Citations/BAX98]]}}} or even more pretty, like this {{{[[BAX98|Citations/BAX98]]}}}.\n\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!!Creating "multi-line" Table Cells<html><a name="TableCells"/></html>\nYou may have noticed that it is hard to create table cells with "multi-line" content. E.g. if you want to create a bullet list inside a table cell you cannot just write the bullet list\n{{{\n* Item 1\n* Item 2\n* Item 3\n}}}\ninto a table cell (i.e. between the | ... | bars) because every bullet item must start in a new line but all cells of a table row must be in one line.\n\nUsing the ''part'' feature this problem can be solved. Just create a hidden part that contains the cells content and use a {{{<<tiddler >>}}} macro to include its content in the table's cell.\n\n''Example''\n{{{\n|!Subject|!Items|\n|subject1|<<tiddler ./Cell1>>|\n|subject2|<<tiddler ./Cell2>>|\n\n<part Cell1 hidden>\n* Item 1\n* Item 2\n* Item 3\n</part>\n...\n}}}\n\nNotice that inside the {{{<<tiddler ...>>}}} macro you may refer to the "current tiddler" using the ".".\n\nBTW: The same approach can be used to create bullet lists with items that contain more than one line.\n\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!!Creating Tabs<html><a name="Tabs"/></html>\nThe build-in {{{<<tabs ...>>}}} macro requires that you defined an additional tiddler for every tab it displays. When you want to have "nested" tabs you need to define a tiddler for the "main tab" and one for every tab it contains. I.e. the definition of a set of tabs that is visually displayed at one place is distributed across multiple tiddlers.\n\nWith the ''part'' feature you can put the complete definition in one tiddler, making it easier to keep an overview and maintain the tab sets.\n\n''Example''\nThe standard tabs at the sidebar are defined by the following eight tiddlers:\n* SideBarTabs\n* TabAll\n* TabMore\n* TabMoreMissing\n* TabMoreOrphans\n* TabMoreShadowed\n* TabTags\n* TabTimeline\n\nInstead of these eight tiddlers one could define the following SideBarTabs tiddler that uses the ''part'' feature:\n{{{\n<<tabs txtMainTab \n Timeline Timeline SideBarTabs/Timeline \n All 'All tiddlers' SideBarTabs/All \n Tags 'All tags' SideBarTabs/Tags \n More 'More lists' SideBarTabs/More>>\n<part Timeline hidden><<timeline>></part>\n<part All hidden><<list all>></part>\n<part Tags hidden><<allTags>></part>\n<part More hidden><<tabs txtMoreTab \n Missing 'Missing tiddlers' SideBarTabs/Missing \n Orphans 'Orphaned tiddlers' SideBarTabs/Orphans \n Shadowed 'Shadowed tiddlers' SideBarTabs/Shadowed>></part>\n<part Missing hidden><<list missing>></part>\n<part Orphans hidden><<list orphans>></part>\n<part Shadowed hidden><<list shadowed>></part>\n}}}\n\nNotice that you can easily "overwrite" individual parts in separate tiddlers that have the full name of the part.\n\nE.g. if you don't like the classic timeline tab but only want to see the 100 most recent tiddlers you could create a tiddler "~SideBarTabs/Timeline" with the following content:\n{{{\n<<forEachTiddler \n sortBy 'tiddler.modified' descending \n write '(index < 100) ? "* [["+tiddler.title+"]]\sn":""'>>\n}}}\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!!Using Sliders<html><a name="Sliders"/></html>\nVery similar to the build-in {{{<<tabs ...>>}}} macro (see above) the {{{<<slider ...>>}}} macro requires that you defined an additional tiddler that holds the content "to be slid". You can avoid creating this extra tiddler by using the ''part'' feature\n\n''Example''\nIn a tiddler "About" we may use the slider to show some details that are documented in the tiddler's "Details" part.\n{{{\n...\n<<slider chkAboutDetails About/Details details "Click here to see more details">>\n<part Details hidden>\nTo give you a better overview ...\n</part>\n...\n}}}\n\nNotice that putting the content of the slider into the slider's tiddler also has an extra benefit: When you decide you need to edit the content of the slider you can just doubleclick the content, the tiddler opens for editing and you can directly start editing the content (in the part section). In the "old" approach you would doubleclick the tiddler, see that the slider is using tiddler X, have to look for the tiddler X and can finally open it for editing. So using the ''part'' approach results in a much short workflow.\n\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!Revision history<html><a name="Revisions"/></html>\n* v1.0.3 (2006-02-26)\n** Adapt code to newly introduced Tiddler.prototype.isReadOnly() function (in TW 2.0.6). Thanks to Paulo Soares for reporting the problem.\n* v1.0.2 (2006-02-05)\n** Also allow other macros than the "tiddler" macro use the "." in the part reference (to refer to "this" tiddler)\n* v1.0.1 (2006-01-27)\n** Added Table of Content for plugin documentation. Thanks to RichCarrillo for suggesting.\n** Bugfix: newReminder plugin does not work when PartTiddler is installed. Thanks to PauloSoares for reporting.\n* v1.0.0 (2006-01-25)\n** initial version\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!Code<html><a name="Code"/></html>\n<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n***/\n//{{{\n//============================================================================\n// PartTiddlerPlugin\n\n// Ensure that the PartTiddler Plugin is only installed once.\n//\nif (!version.extensions.PartTiddlerPlugin) {\n\n\n\nversion.extensions.PartTiddlerPlugin = {\n major: 1, minor: 0, revision: 3,\n date: new Date(2006, 2, 26), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#PartTiddlerPlugin"\n};\n\nif (!window.abego) window.abego = {};\nif (version.major < 2) alertAndThrow("PartTiddlerPlugin requires TiddlyWiki 2.0 or newer.");\n\n//============================================================================\n// Common Helpers\n\n// Looks for the next newline, starting at the index-th char of text. \n//\n// If there are only whitespaces between index and the newline \n// the index behind the newline is returned, \n// otherwise (or when no newline is found) index is returned.\n//\nvar skipEmptyEndOfLine = function(text, index) {\n var re = /(\sn|[^\ss])/g;\n re.lastIndex = index;\n var result = re.exec(text);\n return (result && text.charAt(result.index) == '\sn') \n ? result.index+1\n : index;\n}\n\n\n//============================================================================\n// Constants\n\nvar partEndOrStartTagRE = /(<\s/part>)|(<part(?:\ss+)((?:[^>])+)>)/mg;\nvar partEndTagREString = "<\s\s/part>";\nvar partEndTagString = "</part>";\n\n//============================================================================\n// Plugin Specific Helpers\n\n// Parse the parameters inside a <part ...> tag and return the result.\n//\n// @return [may be null] {partName: ..., isHidden: ...}\n//\nvar parseStartTagParams = function(paramText) {\n var params = paramText.readMacroParams();\n if (params.length == 0 || params[0].length == 0) return null;\n \n var name = params[0];\n var paramsIndex = 1;\n var hidden = false;\n if (paramsIndex < params.length) {\n hidden = params[paramsIndex] == "hidden";\n paramsIndex++;\n }\n \n return {\n partName: name, \n isHidden: hidden\n };\n}\n\n// Returns the match to the next (end or start) part tag in the text, \n// starting the search at startIndex.\n// \n// When no such tag is found null is returned, otherwise a "Match" is returned:\n// [0]: full match\n// [1]: matched "end" tag (or null when no end tag match)\n// [2]: matched "start" tag (or null when no start tag match)\n// [3]: content of start tag (or null if no start tag match)\n//\nvar findNextPartEndOrStartTagMatch = function(text, startIndex) {\n var re = new RegExp(partEndOrStartTagRE);\n re.lastIndex = startIndex;\n var match = re.exec(text);\n return match;\n}\n\n//============================================================================\n// Formatter\n\n// Process the <part ...> ... </part> starting at (w.source, w.matchStart) for formatting.\n//\n// @return true if a complete part section (including the end tag) could be processed, false otherwise.\n//\nvar handlePartSection = function(w) {\n var tagMatch = findNextPartEndOrStartTagMatch(w.source, w.matchStart);\n if (!tagMatch) return false;\n if (tagMatch.index != w.matchStart || !tagMatch[2]) return false;\n\n // Parse the start tag parameters\n var arguments = parseStartTagParams(tagMatch[3]);\n if (!arguments) return false;\n \n // Continue processing\n var startTagEndIndex = skipEmptyEndOfLine(w.source, tagMatch.index + tagMatch[0].length);\n var endMatch = findNextPartEndOrStartTagMatch(w.source, startTagEndIndex);\n if (endMatch && endMatch[1]) {\n if (!arguments.isHidden) {\n w.nextMatch = startTagEndIndex;\n w.subWikify(w.output,partEndTagREString);\n }\n w.nextMatch = skipEmptyEndOfLine(w.source, endMatch.index + endMatch[0].length);\n \n return true;\n }\n return false;\n}\n\nconfig.formatters.push( {\n name: "part",\n match: "<part\s\ss+[^>]+>",\n \n handler: function(w) {\n if (!handlePartSection(w)) {\n w.outputText(w.output,w.matchStart,w.matchStart+w.matchLength);\n }\n }\n} )\n\n//============================================================================\n// Extend "fetchTiddler" functionality to also recognize "part"s of tiddlers \n// as tiddlers.\n\nvar currentParent = null; // used for the "." parent (e.g. in the "tiddler" macro)\n\n// Return the match to the first <part ...> tag of the text that has the\n// requrest partName.\n//\n// @return [may be null]\n//\nvar findPartStartTagByName = function(text, partName) {\n var i = 0;\n \n while (true) {\n var tagMatch = findNextPartEndOrStartTagMatch(text, i);\n if (!tagMatch) return null;\n\n if (tagMatch[2]) {\n // Is start tag\n \n // Check the name\n var arguments = parseStartTagParams(tagMatch[3]);\n if (arguments && arguments.partName == partName) {\n return tagMatch;\n }\n }\n i += tagMatch[0].length;\n }\n}\n\n// Return the part "partName" of the given parentTiddler as a "readOnly" Tiddler \n// object, using fullName as the Tiddler's title. \n//\n// All remaining properties of the new Tiddler (tags etc.) are inherited from \n// the parentTiddler.\n// \n// @return [may be null]\n//\nvar getPart = function(parentTiddler, partName, fullName) {\n var text = parentTiddler.text;\n var startTag = findPartStartTagByName(text, partName);\n if (!startTag) return null;\n \n var endIndexOfStartTag = skipEmptyEndOfLine(text, startTag.index+startTag[0].length);\n var indexOfEndTag = text.indexOf(partEndTagString, endIndexOfStartTag);\n\n if (indexOfEndTag >= 0) {\n var partTiddlerText = text.substring(endIndexOfStartTag,indexOfEndTag);\n var partTiddler = new Tiddler();\n partTiddler.set(\n fullName,\n partTiddlerText,\n parentTiddler.modifier,\n parentTiddler.modified,\n parentTiddler.tags,\n parentTiddler.created);\n partTiddler.hasReadOnlyFlag = true;\n return partTiddler;\n }\n \n return null;\n}\n\n// Hijack the store.fetchTiddler to recognize the "part" addresses.\n//\n\nvar oldFetchTiddler = store.fetchTiddler ;\nstore.fetchTiddler = function(title) {\n var result = oldFetchTiddler.apply(this, arguments);\n if (!result && title) {\n var i = title.lastIndexOf('/');\n if (i > 0) {\n var parentName = title.substring(0, i);\n var partName = title.substring(i+1);\n var parent = (parentName == ".") \n ? currentParent \n : oldFetchTiddler.apply(this, [parentName]);\n if (parent) {\n return getPart(parent, partName, parent.title+"/"+partName);\n }\n }\n }\n return result; \n};\n\n\n// The user must not edit a readOnly/partTiddler\n//\n\nconfig.commands.editTiddler.oldIsReadOnlyFunction = Tiddler.prototype.isReadOnly;\n\nTiddler.prototype.isReadOnly = function() {\n // Tiddler.isReadOnly was introduced with TW 2.0.6.\n // For older version we explicitly check the global readOnly flag\n if (config.commands.editTiddler.oldIsReadOnlyFunction) {\n if (config.commands.editTiddler.oldIsReadOnlyFunction.apply(this, arguments)) return true;\n } else {\n if (readOnly) return true;\n }\n\n return this.hasReadOnlyFlag;\n}\n\nconfig.commands.editTiddler.handler = function(event,src,title)\n{\n var t = store.getTiddler(title);\n if(t && !t.isReadOnly())\n {\n clearMessage();\n story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(title,"text");\n return false;\n }\n}\n\n// To allow the "./partName" syntax in macros we need to hijack \n// the invokeMacro to define the "currentParent" while it is running.\n// \nvar oldInvokeMacro = invokeMacro;\nfunction invokeMacro(place,macro,params,wikifier,tiddler) {\n var oldCurrentParent = currentParent;\n if (tiddler) currentParent = tiddler;\n try {\n oldInvokeMacro.apply(this, arguments);\n } finally {\n currentParent = oldCurrentParent;\n }\n}\n\n// Scroll the anchor anchorName in the viewer of the given tiddler visible.\n// When no tiddler is defined use the tiddler of the target given event is used.\nwindow.scrollAnchorVisible = function(anchorName, tiddler, evt) {\n var tiddlerElem = null;\n if (tiddler) {\n tiddlerElem = document.getElementById(story.idPrefix + tiddler);\n }\n if (!tiddlerElem && evt) {\n var target = resolveTarget(evt);\n tiddlerElem = story.findContainingTiddler(target);\n }\n if (!tiddlerElem) return;\n\n var children = tiddlerElem.getElementsByTagName("a");\n for (var i = 0; i < children.length; i++) {\n var child = children[i];\n var name = child.getAttribute("name");\n if (name == anchorName) {\n var y = findPosY(child);\n window.scrollTo(0,y);\n return;\n }\n }\n}\n\n} // of "install only once"\n//}}}\n\n/***\n<html><sub><a href="javascript:;" onclick="scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2006 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n\n<html><sub><a href="javascript:;" onclick="scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>\n***/\n
|Standard Periodic Table (ref. Wikipedia)|c\n|| !1 | !2 |!| !3 | !4 | !5 | !6 | !7 | !8 | !9 | !10 | !11 | !12 | !13 | !14 | !15 | !16 | !17 | !18 |\n|!1|bgcolor(#a0ffa0): @@color(red):H@@ |>|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>||bgcolor(#c0ffff): @@color(red):He@@ |\n|!2|bgcolor(#ff6666): Li |bgcolor(#ffdead): Be |>|>|>|>|>|>|>|>|>|>||bgcolor(#cccc99): B |bgcolor(#a0ffa0): C |bgcolor(#a0ffa0): @@color(red):N@@ |bgcolor(#a0ffa0): @@color(red):O@@ |bgcolor(#ffff99): @@color(red):F@@ |bgcolor(#c0ffff): @@color(red):Ne@@ |\n|!3|bgcolor(#ff6666): Na |bgcolor(#ffdead): Mg |>|>|>|>|>|>|>|>|>|>||bgcolor(#cccccc): Al |bgcolor(#cccc99): Si |bgcolor(#a0ffa0): P |bgcolor(#a0ffa0): S |bgcolor(#ffff99): @@color(red):Cl@@ |bgcolor(#c0ffff): @@color(red):Ar@@ |\n|!4|bgcolor(#ff6666): K |bgcolor(#ffdead): Ca ||bgcolor(#ffc0c0): Sc |bgcolor(#ffc0c0): Ti |bgcolor(#ffc0c0): V |bgcolor(#ffc0c0): Cr |bgcolor(#ffc0c0): Mn |bgcolor(#ffc0c0): Fe |bgcolor(#ffc0c0): Co |bgcolor(#ffc0c0): Ni |bgcolor(#ffc0c0): Cu |bgcolor(#ffc0c0): Zn |bgcolor(#cccccc): Ga |bgcolor(#cccc99): Ge |bgcolor(#cccc99): As |bgcolor(#a0ffa0): Se |bgcolor(#ffff99): @@color(green):Br@@ |bgcolor(#c0ffff): @@color(red):Kr@@ |\n|!5|bgcolor(#ff6666): Rb |bgcolor(#ffdead): Sr ||bgcolor(#ffc0c0): Y |bgcolor(#ffc0c0): Zr |bgcolor(#ffc0c0): Nb |bgcolor(#ffc0c0): Mo |bgcolor(#ffc0c0): Tc |bgcolor(#ffc0c0): Ru |bgcolor(#ffc0c0): Rh |bgcolor(#ffc0c0): Pd |bgcolor(#ffc0c0): Ag |bgcolor(#ffc0c0): Cd |bgcolor(#cccccc): In |bgcolor(#cccccc): Sn |bgcolor(#cccc99): Sb |bgcolor(#cccc99): Te |bgcolor(#ffff99): I |bgcolor(#c0ffff): @@color(red):Xe@@ |\n|!6|bgcolor(#ff6666): Cs |bgcolor(#ffdead): Ba |bgcolor(#ffbfff):^^*1^^|bgcolor(#ffc0c0): Lu |bgcolor(#ffc0c0): Hf |bgcolor(#ffc0c0): Ta |bgcolor(#ffc0c0): W |bgcolor(#ffc0c0): Re |bgcolor(#ffc0c0): Os |bgcolor(#ffc0c0): Ir |bgcolor(#ffc0c0): Pt |bgcolor(#ffc0c0): Au |bgcolor(#ffc0c0): @@color(green):Hg@@ |bgcolor(#cccccc): Tl |bgcolor(#cccccc): Pb |bgcolor(#cccccc): Bi |bgcolor(#cccc99): Po |bgcolor(#ffff99): At |bgcolor(#c0ffff): @@color(red):Rn@@ |\n|!7|bgcolor(#ff6666): Fr |bgcolor(#ffdead): Ra |bgcolor(#ff99cc):^^*2^^|bgcolor(#ffc0c0): Lr |bgcolor(#ffc0c0): Rf |bgcolor(#ffc0c0): Db |bgcolor(#ffc0c0): Sq |bgcolor(#ffc0c0): Bh |bgcolor(#ffc0c0): Hs |bgcolor(#ffc0c0): Mt |bgcolor(#ffc0c0): Ds |bgcolor(#ffc0c0): Rg |bgcolor(#ffc0c0): @@color(green):Uub@@ |bgcolor(#cccccc): Uut |bgcolor(#cccccc): Uuq |bgcolor(#cccccc): Uup |bgcolor(#cccccc): Uuh |bgcolor(#fcfecc): @@color(#cccccc):Uus@@ |bgcolor(#ecfefc): @@color(#cccccc):Uuo@@ |\n\n| !Lanthanides^^*1^^|bgcolor(#ffbfff): La |bgcolor(#ffbfff): Ce |bgcolor(#ffbfff): Pr |bgcolor(#ffbfff): Nd |bgcolor(#ffbfff): Pm |bgcolor(#ffbfff): Sm |bgcolor(#ffbfff): Eu |bgcolor(#ffbfff): Gd |bgcolor(#ffbfff): Tb |bgcolor(#ffbfff): Dy |bgcolor(#ffbfff): Ho |bgcolor(#ffbfff): Er |bgcolor(#ffbfff): Tm |bgcolor(#ffbfff): Yb |\n| !Actinides^^*2^^|bgcolor(#ff99cc): Ac |bgcolor(#ff99cc): Th |bgcolor(#ff99cc): Pa |bgcolor(#ff99cc): U |bgcolor(#ff99cc): Np |bgcolor(#ff99cc): Pu |bgcolor(#ff99cc): Am |bgcolor(#ff99cc): Cm |bgcolor(#ff99cc): Bk |bgcolor(#ff99cc): Cf |bgcolor(#ff99cc): Es |bgcolor(#ff99cc): Fm |bgcolor(#ff99cc): Md |bgcolor(#ff99cc): No |\n\n*Chemical Series of the Periodic Table\n**@@bgcolor(#ff6666): Alkali metals@@\n**@@bgcolor(#ffdead): Alkaline earth metals@@\n**@@bgcolor(#ffbfff): Lanthanides@@\n**@@bgcolor(#ff99cc): Actinides@@\n**@@bgcolor(#ffc0c0): Transition metals@@\n**@@bgcolor(#cccccc): Poor metals@@\n**@@bgcolor(#cccc99): Metalloids@@\n**@@bgcolor(#a0ffa0): Nonmetals@@\n**@@bgcolor(#ffff99): Halogens@@\n**@@bgcolor(#c0ffff): Noble gases@@\n\n*State at standard temperature and pressure\n**those in @@color(red):red@@ are gases\n**those in @@color(green):green@@ are liquids\n**those in black are solids
I think this feature from the SecondVersion of TiddlyWiki is quite original. It's a button in the right-hand sidebar that sets the browser address bar to a URL embodying all the currently open tiddlers in the order that they are currently shown. To use it, arrange the open tiddlers that you want, click the permaview button, copy the URL from the browser address bar, and then paste it into an email, web page or whatever.
<<tiddler GTDProjectTemplate with: !music "Personal: Music to check out">>
/***\n| ''Name'' |plugin name|\n| ''Version'' ||\n| ''Source'' |[[source_name|http://where.you.are]]|\n| ''Author'' |[[author_name|mailto:you@from.where]]|\n| ''Type'' |plugin macro extension|\n| ''Required'' |TiddlyWiki |\n!Revision\n\n!Description\n\n!Installation\n\n!Syntax\n\n!Example\n\n!Credits\n\n!Code\n***/\n//{{{\n\n/* your code here */\n\n//}}}
You can now link to [[external sites|http://www.osmosoft.com]] with ordinary words, without the messiness of the full URL appearing. Edit this tiddler to see how.\n\nYou can also LinkToFolders.
The GTD Tiddly Wiki has been designed to print "HipsterPDA" 3x5 index cards. All you have to do is use your browser's "Print" button or shortcut key.\n\n!Print Features:\n* Print directly to 3x5 from your browser. There is no "printer friendly" link.\n* Pagination: Each Tiddler (or GTD list) will print on it's own sheet. You could have all your lists open and print them all at once.\n* If you know any CSS, you can completely customize the print output.\n* List bullets are circles to help you mark off completed tasks in your HipsterPDA.\n\n[img[http://img15.echo.cx/img15/57/lists2jb.jpg]]\n\n!How to customize print style, typeface, or font size:\n* Edit the StyleSheet Tiddler (it helps to know a little CSS).\n\n!KnownBugs with print:\n* Firefox/Mac has no "page properties" interface for removing the page URL, page numbers, etc... from printed pages. This is pretty lame. Try entering about:config in Firefox's URL bar and look for "print" to configure it the hard way.\n* WIN/IE 6 inserts one blank page because it does not recognize the :first-child CSS psuedo element.\n* You'll probably need to tweak your browser print settings to remove the page URL, pagination, timestamp, and ensure that the output is sized and paged correctly.\n* Your mileage may vary because of platform, font, browser, and printer differences. If you find something that's broken or needs help, visit the GTDTWForum.
The rules governing where a tiddler is displayed sound complicated written down. When you click on a tiddler link within another tiddler, the new one is opened immediately below the current one. If the target tiddler is already open, TiddlyWiki just uses SmoothScrolling to bring it into view. More or less the same thing happens when clicking on a tiddler link within the menu or sidebar, except that the tiddler opens at the top of the page if it is not already open.
RegExpSearch uses JavaScript's [[RegExp syntax|http://www.programmershelp.co.uk/docs/javascript/regexp.html#1193188]] to allow flexible searches.
/***\n|''Name:''|ReminderPlugin|\n|''Version:''|2.3.5.TP.2 (Feb 23, 2006)|\n|''Source:''|http://www.geocities.com/allredfaq/reminderMacros.html|\n|''Author:''|Jeremy Sheeley(pop1280 [at] excite [dot] com)|\n|''Licence:''|[[BSD open source license]]|\n|''Macros:''|reminder, showreminders, displayTiddlersWithReminders, newReminder|\n|''TiddlyWiki:''|2.0+|\n|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|\n\n!Description\nThis plugin provides macros for tagging a date with a reminder. Use the {{{reminder}}} macro to do this. The {{{showReminders}}} and {{{displayTiddlersWithReminder}}} macros automatically search through all available tiddlers looking for upcoming reminders.\n\n!Installation\n* Create a new tiddler in your tiddlywiki titled ReminderPlugin and give it the {{{systemConfig}}} tag. The tag is important because it tells TW that this is executable code.\n* Double click this tiddler, and copy all the text from the tiddler's body.\n* Paste the text into the body of the new tiddler in your TW.\n* Save and reload your TW.\n* You can copy some examples into your TW as well. See [[Simple examples]], [[Holidays]], [[showReminders]] and [[Personal Reminders]]\n\n!Syntax:\n|>|See [[ReminderSyntax]] and [[showRemindersSyntax]]|\n\n!Revision history\n* v2.3.5.TP.2 (Feb 23, 2006)\n**Unofficial edit by TedPavlic: Added TIDDLERNAME tag, which is a version of TIDDLER without brackets around it. Also changed replace calls so that they are global.\n* v2.3.5.TP.1 (Feb 16, 2006)\n**Unofficial edit by TedPavlic: Added newline after "There are no upcoming events" prompt to mimic wikify behavior when there are upcoming events.\n* v2.3.5 (Feb 8, 2006)\n**Bug fix: Sped up reminders lots. Added a caching mechanism for reminders that have already been matched.\n* v2.3.4 (Feb 7, 2006)\n**Bug fix: Cleaned up code to hopefully prevent the Firefox 1.5.0.1 crash that was causing lots of plugins \nto crash Firefox. Thanks to http://www.jslint.com\n* v2.3.3 (Feb 2, 2006)\n**Feature: newReminder now has drop down lists instead of text boxes.\n**Bug fix: A trailing space in a title would trigger an infinite loop.\n**Bug fix: using tag:"birthday !reminder" would filter differently than tag:"!reminder birthday"\n* v2.3.2 (Jan 21, 2006)\n**Feature: newReminder macro, which will let you easily add a reminder to a tiddler. Thanks to Eric Shulman (http://www.elsdesign.com) for the code to do this.\n** Bug fix: offsetday was not working sometimes\n** Bug fix: when upgrading to 2.0, I included a bit to exclude tiddlers tagged with excludeSearch. I've reverted back to searching through all tiddlers\n* v2.3.1 (Jan 7, 2006)\n**Feature: 2.0 compatibility\n**Feature AlanH sent some code to make sure that showReminders prints a message if no reminders are found.\n* v2.3.0 (Jan 3, 2006)\n** Bug Fix: Using "Last Sunday (-0)" as a offsetdayofweek wasn't working.\n** Bug Fix: Daylight Savings time broke offset based reminders (for example year:2005 month:8 day:23 recurdays:7 would match Monday instead of Tuesday during DST.\n\n!Code\n***/\n//{{{\n\n//============================================================================\n//============================================================================\n// ReminderPlugin\n//============================================================================\n//============================================================================\n\nversion.extensions.ReminderPlugin = {major: 2, minor: 3, revision: 4, date: new Date(2006,2,7), source: "http://www.geocities.com/allredfaq/reminderMacros.html"};\n\n//============================================================================\n// Configuration\n// Modify this section to change the defaults for \n// leadtime and display strings\n//============================================================================\n\nconfig.macros.reminders = {};\nconfig.macros["reminder"] = {};\nconfig.macros["newReminder"] = {};\nconfig.macros["showReminders"] = {};\nconfig.macros["displayTiddlersWithReminders"] = {};\n\nconfig.macros.reminders["defaultLeadTime"] = [0,6000];\nconfig.macros.reminders["defaultReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY";\nconfig.macros.reminders["defaultShowReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY -- TIDDLER";\nconfig.macros.reminders["defaultAnniversaryMessage"] = "(DIFF)";\nconfig.macros.reminders["untitledReminder"] = "Untitled Reminder";\nconfig.macros.reminders["noReminderFound"] = "Couldn't find a match for TITLE in the next LEADTIMEUPPER days."\nconfig.macros.reminders["todayString"] = "Today";\nconfig.macros.reminders["tomorrowString"] = "Tomorrow";\nconfig.macros.reminders["ndaysString"] = "DIFF days";\nconfig.macros.reminders["emtpyShowRemindersString"] = "There are no upcoming events\sn";\n\n\n//============================================================================\n// Code\n// You should not need to edit anything \n// below this. Make sure to edit this tiddler and copy \n// the code from the text box, to make sure that \n// tiddler rendering doesn't interfere with the copy \n// and paste.\n//============================================================================\n\n// This line is to preserve 1.2 compatibility\n if (!story) var story=window; \n//this object will hold the cache of reminders, so that we don't\n//recompute the same reminder over again.\nvar reminderCache = {};\n\nconfig.macros.showReminders.handler = function showReminders(place,macroName,params)\n{\n var now = new Date().getMidnight();\n var paramHash = {};\n var leadtime = [0,14];\n paramHash = getParamsForReminder(params);\n var bProvidedDate = (paramHash["year"] != null) || \n (paramHash["month"] != null) || \n (paramHash["day"] != null) || \n (paramHash["dayofweek"] != null);\n if (paramHash["leadtime"] != null)\n {\n leadtime = paramHash["leadtime"];\n if (bProvidedDate)\n {\n //If they've entered a day, we need to make \n //sure to find it. We'll reset the \n //leadtime a few lines down.\n paramHash["leadtime"] = [-10000, 10000];\n }\n }\n var matchedDate = now;\n if (bProvidedDate)\n {\n matchedDate = findDateForReminder(paramHash); \n }\n\n var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);\n var elem = createTiddlyElement(place,"span",null,null, null);\n var mess = "";\n if (arr.length == 0)\n {\n mess += config.macros.reminders.emtpyShowRemindersString; \n }\n for (var j = 0; j < arr.length; j++)\n {\n if (paramHash["format"] != null)\n {\n arr[j]["params"]["format"] = paramHash["format"];\n }\n else\n {\n arr[j]["params"]["format"] = config.macros.reminders["defaultShowReminderMessage"];\n }\n mess += getReminderMessageForDisplay(arr[j]["diff"], arr[j]["params"], arr[j]["matchedDate"], arr[j]["tiddler"]);\n mess += "\sn";\n }\n wikify(mess, elem, null, null);\n};\n\n\nconfig.macros.displayTiddlersWithReminders.handler = function displayTiddlersWithReminders(place,macroName,params)\n{\n var now = new Date().getMidnight();\n var paramHash = {};\n var leadtime = [0,14];\n paramHash = getParamsForReminder(params);\n var bProvidedDate = (paramHash["year"] != null) || \n (paramHash["month"] != null) || \n (paramHash["day"] != null) || \n (paramHash["dayofweek"] != null);\n if (paramHash["leadtime"] != null)\n {\n leadtime = paramHash["leadtime"];\n if (bProvidedDate)\n {\n //If they've entered a day, we need to make \n //sure to find it. We'll reset the leadtime \n //a few lines down.\n paramHash["leadtime"] = [-10000,10000];\n }\n }\n var matchedDate = now;\n if (bProvidedDate)\n {\n matchedDate = findDateForReminder(paramHash); \n }\n var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);\n for (var j = 0; j < arr.length; j++)\n {\n displayTiddler(null, arr[j]["tiddler"], 0, null, false, false, false);\n }\n};\n\nconfig.macros.reminder.handler = function reminder(place,macroName,params)\n{\n var dateHash = getParamsForReminder(params);\n if (dateHash["hidden"] != null)\n {\n return;\n }\n var matchedDate = findDateForReminder(dateHash);\n var leadTime = dateHash["leadtime"];\n if (leadTime == null)\n {\n leadTime = config.macros.reminders["defaultLeadTime"]; \n }\n\n if (matchedDate != null)\n {\n var diff = matchedDate.getDifferenceInDays(new Date());\n var elem = createTiddlyElement(place,"span",null,null, null);\n var mess = getReminderMessageForDisplay(diff, dateHash, matchedDate);\n wikify(mess, elem, null, null);\n }\n else\n {\n createTiddlyElement(place,"span",null,null, config.macros.reminders["noReminderFound"].replace("TITLE", dateHash["title"]).replace("LEADTIMEUPPER", leadTime[1]).replace("LEADTIMELOWER", leadTime[0]) );\n }\n};\n\nconfig.macros.newReminder.handler = function newReminder(place,macroName,params)\n{\n var today=new Date();\n var formstring = '<html><form>Year: <select name="year"><option value="">Every year</option>';\n for (var i = 0; i < 5; i++)\n {\n formstring += '<option' + ((i == 0) ? ' selected' : '') + '>' + (today.getFullYear() + i) + '</option>';\n }\n formstring += '</select>&nbsp;&nbsp;Month:<select name="month"><option value="">Every month</option>';\n for (i = 0; i < 12; i++)\n {\n formstring += '<option' + ((i == today.getMonth()) ? ' selected' : '') + ' value="' + (i+1) + '">' + config.messages.dates.months[i] + '</option>';\n }\n formstring += '</select>&nbsp;&nbsp;Day:<select name="day"><option value="">Every day</option>';\n for (i = 1; i < 32; i++)\n {\n formstring += '<option' + ((i == (today.getDate() )) ? ' selected' : '') + '>' + i + '</option>';\n }\n\nformstring += '</select>&nbsp;&nbsp;Reminder Title:<input type="text" size="40" name="title" value="please enter a title" onfocus="this.select();"><input type="button" value="ok" onclick="addReminderToTiddler(this.form)"></form></html>';\n\n var panel = config.macros.slider.createSlider(place,null,"New Reminder","Open a form to add a new reminder to this tiddler");\n wikify(formstring ,panel,null,store.getTiddler(params[1]));\n};\n\n// onclick: process input and insert reminder at 'marker'\nwindow.addReminderToTiddler = function(form) {\n if (!window.story) \n {\n window.story=window; \n }\n if (!store.getTiddler) \n {\n store.getTiddler=function(title) {return this.tiddlers[title];};\n }\n var title = story.findContainingTiddler(form).id.substr(7);\n var tiddler=store.getTiddler(title);\n var txt='\sn<<reminder year:'+form.year.value+' month:'+form.month.value+' day:'+form.day.value+' title:"'+form.title.value+'">>';\n tiddler.set(null,tiddler.text + txt);\n story.refreshTiddler(title,1,true);\n store.setDirty(true);\n};\n\nfunction hasTag(tiddlerTags, tagFilters)\n{\n //Make sure we respond well to empty tiddlerTaglists or tagFilterlists\n if (tagFilters.length==0 || tiddlerTags.length==0)\n {\n return true;\n }\n\n var bHasTag = false;\n \n /*bNoPos says: "'till now there has been no check using a positive filter"\n Imagine a filterlist consisting of 1 negative filter:\n If the filter isn't matched, we want hasTag to be true.\n Yet bHasTag is still false ('cause only positive filters cause bHasTag to change)\n \n If no positive filters are present bNoPos is true, and no negative filters are matched so we have not returned false\n Thus: hasTag returns true.\n \n If at any time a positive filter is encountered, we want at least one of the tags to match it, so we turn bNoPos to false, which\n means bHasTag must be true for hasTag to return true*/\n var bNoPos=true;\n \nfor (var t3 = 0; t3 < tagFilters.length; t3++)\n {\n for(var t2=0; t2<tiddlerTags.length; t2++)\n {\n if (tagFilters[t3].length > 1 && tagFilters[t3].charAt(0) == '!') \n {\n if (tiddlerTags[t2] == tagFilters[t3].substring(1))\n {\n //If at any time a negative filter is matched, we return false\n return false;\n }\n }\n else \n {\n if (bNoPos)\n {\n //We encountered the first positive filter\n bNoPos=false;\n }\n if (tiddlerTags[t2] == tagFilters[t3])\n {\n //A positive filter is matched. As long as no negative filter is matched, hasTag will return true\n bHasTag=true;\n }\n }\n }\n }\n return (bNoPos || bHasTag);\n};\n\n//This function searches all tiddlers for the reminder //macro. It is intended that other plugins (like //calendar) will use this function to query for \n//upcoming reminders.\n//The arguments to this function filter out reminders //based on when they will fire.\n//\n//ARGUMENTS:\n//baseDate is the date that is used as "now". \n//leadtime is a two element int array, with leadtime[0] \n// as the lower bound and leadtime[1] as the\n// upper bound. A reasonable default is [0,14]\n//tags is a space-separated list of tags to use to filter \n// tiddlers. If a tag name begins with an !, then \n// only tiddlers which do not have that tag will \n// be considered. For example "examples holidays" \n// will search for reminders in any tiddlers that \n// are tagged with examples or holidays and \n// "!examples !holidays" will search for reminders \n// in any tiddlers that are not tagged with \n// examples or holidays. Pass in null to search \n// all tiddlers.\n//limit. If limit is null, individual reminders can \n// override the leadtime specified earlier. \n// Pass in 1 in order to override that behavior.\n\nfunction findTiddlersWithReminders(baseDate, leadtime, tags, limit)\n{\n//function(searchRegExp,sortField,excludeTag)\n// var macroPattern = "<<([^>\s\s]+)(?:\s\s*)([^>]*)>>";\n var macroPattern = "<<(reminder)(.*)>>";\n var macroRegExp = new RegExp(macroPattern,"mg");\n var matches = store.search(macroRegExp,"title","");\n var arr = [];\n var tagsArray = null;\n if (tags != null)\n {\n tagsArray = tags.split(" ");\n }\n for(var t=matches.length-1; t>=0; t--)\n {\n if (tagsArray != null)\n {\n //If they specified tags to filter on, and this tiddler doesn't \n //match, skip it entirely.\n if ( ! hasTag(matches[t].tags, tagsArray))\n {\n continue;\n }\n }\n\n var targetText = matches[t].text;\n do {\n // Get the next formatting match\n var formatMatch = macroRegExp.exec(targetText);\n if(formatMatch && formatMatch[1] != null && formatMatch[1].toLowerCase() == "reminder")\n {\n //Find the matching date.\n \n var params = formatMatch[2] != null ? formatMatch[2].readMacroParams() : {};\n var dateHash = getParamsForReminder(params);\n if (limit != null || dateHash["leadtime"] == null)\n {\n dateHash["leadtime"] = leadtime;\n }\n\n var matchedDate = findDateForReminder(dateHash, baseDate);\n if (matchedDate != null)\n {\n var hash = {};\n hash["diff"] = matchedDate.getDifferenceInDays(baseDate);\n hash["matchedDate"] = matchedDate;\n hash["params"] = dateHash;\n hash["tiddler"] = matches[t].title;\n hash["tags"] = matches[t].tags;\n arr.pushUnique(hash);\n }\n }\n }while(formatMatch);\n }\n if(arr.length > 1) //Sort the array by number of days remaining.\n {\n arr.sort(function (a,b) {if(a["diff"] == b["diff"]) {return(0);} else {return (a["diff"] < b["diff"]) ? -1 : +1; } });\n }\n return arr;\n};\n\n//This function takes the reminder macro parameters and\n//generates the string that is used for display.\n//This function is not intended to be called by \n//other plugins.\nfunction getReminderMessageForDisplay(diff, params, matchedDate, tiddlerTitle)\n{\n var anniversaryString = "";\n var reminderTitle = params["title"];\n if (reminderTitle == null)\n {\n reminderTitle = config.macros.reminders["untitledReminder"];\n }\n if (params["firstyear"] != null)\n {\n anniversaryString = config.macros.reminders["defaultAnniversaryMessage"].replace("DIFF", (matchedDate.getFullYear() - params["firstyear"]));\n }\n var mess = "";\n var diffString = "";\n if (diff == 0)\n {\n diffString = config.macros.reminders["todayString"];\n }\n else if (diff == 1)\n {\n diffString = config.macros.reminders["tomorrowString"];\n }\n else\n {\n diffString = config.macros.reminders["ndaysString"].replace(/DIFF/g, diff);\n }\n var format = config.macros.reminders["defaultReminderMessage"];\n if (params["format"] != null)\n {\n format = params["format"];\n }\n mess = format;\n//HACK! -- Avoid replacing DD in TIDDLER with the date\n mess = mess.replace(/TIDDLER/g, "TIDELER");\n mess = matchedDate.formatStringDateOnly(mess);\n mess = mess.replace(/TIDELER/g, "TIDDLER");\n if (tiddlerTitle != null)\n {\n mess = mess.replace(/TIDDLERNAME/g, tiddlerTitle);\n mess = mess.replace(/TIDDLER/g, "[[" + tiddlerTitle + "]]");\n }\n \n mess = mess.replace(/DIFF/g, diffString).replace(/TITLE/g, reminderTitle).replace(/DATE/g, matchedDate.formatString("DDD MMM DD, YYYY")).replace(/ANNIVERSARY/g, anniversaryString);\n return mess;\n};\n\n// Parse out the macro parameters into a hashtable. This\n// handles the arguments for reminder, showReminders and \n// displayTiddlersWithReminders.\nfunction getParamsForReminder(params)\n{\n var dateHash = {};\n var type = "";\n var num = 0;\n var title = "";\n for(var t=0; t<params.length; t++)\n {\n var split = params[t].split(":");\n type = split[0].toLowerCase();\n var value = split[1];\n for (var i=2; i < split.length; i++)\n {\n value += ":" + split[i];\n }\n if (type == "nolinks" || type == "limit" || type == "hidden")\n {\n num = 1;\n }\n else if (type == "leadtime")\n {\n var leads = value.split("...");\n if (leads.length == 1)\n {\n leads[1]= leads[0];\n leads[0] = 0;\n }\n leads[0] = parseInt(leads[0], 10);\n leads[1] = parseInt(leads[1], 10);\n num = leads;\n }\n else if (type == "offsetdayofweek")\n {\n if (value.substr(0,1) == "-")\n {\n dateHash["negativeOffsetDayOfWeek"] = 1;\n }\n num = parseInt(value, 10);\n }\n else if (type != "title" && type != "tag" && type != "format")\n {\n num = parseInt(value, 10);\n }\n else\n {\n title = value;\n t++;\n while (title.substr(0,1) == '"' && title.substr(title.length - 1,1) != '"' && params[t] != undefined)\n {\n title += " " + params[t++];\n }\n //Trim off the leading and trailing quotes\n if (title.substr(0,1) == "\s"" && title.substr(title.length - 1,1)== "\s"")\n {\n title = title.substr(1, title.length - 2);\n }\n num = title;\n }\n dateHash[type] = num;\n }\n //date is synonymous with day\n if (dateHash["day"] == null)\n {\n dateHash["day"] = dateHash["date"];\n }\n return dateHash;\n};\n\n//This function finds the date specified in the reminder \n//parameters. It will return null if no match can be\n//found. This function is not intended to be used by\n//other plugins.\nfunction findDateForReminder( dateHash, baseDate)\n{\n if (baseDate == null)\n {\n baseDate = new Date().getMidnight();\n }\n var hashKey = baseDate.convertToYYYYMMDDHHMM();\n for (var k in dateHash)\n {\n hashKey += "," + k + "|" + dateHash[k];\n }\n if (reminderCache[hashKey] == null)\n {\n //If we don't find a match in this run, then we will\n //cache that the reminder can't be matched.\n reminderCache[hashKey] = false;\n }\n else if (reminderCache[hashKey] == false)\n {\n //We've already tried this date and failed\n return null;\n }\n else\n {\n return reminderCache[hashKey];\n }\n var leadTime = dateHash["leadtime"];\n var bOffsetSpecified = dateHash["offsetyear"] != null || \n dateHash["offsetmonth"] != null || \n dateHash["offsetday"] != null || \n dateHash["offsetdayofweek"] != null || \n dateHash["recurdays"] != null;\n \n if (leadTime == null)\n {\n leadTime = config.macros.reminders["defaultLeadTime"]; \n }\n//HACK!\n if (dateHash["offsetdayofweek"] != null && dateHash["day"] != null && dateHash["month"] == null && dateHash["year"] == null)\n {\n if ((baseDate.getDate() - dateHash["day"]) < 7 && (baseDate.getDate() - dateHash["day"]) >= 0 && \n dateHash["offsetdayofweek"] >= baseDate.getDay())\n {\n //They've seleceted an offsetdayofweek that is greater than or equal to today.\n //We need to use today as the first matched date\n for (var i=0; i < 7; i++)\n {\n var testDate = baseDate.addDays(i);\n if (testDate.getDay() == dateHash["offsetdayofweek"])\n {\n var diff3 = testDate.getDifferenceInDays(baseDate);\n if (diff3 <= leadTime[1] && diff3 >= leadTime[0])\n {\n reminderCache[hashKey] = testDate;\n return testDate;\n }\n else\n {\n return null;\n }\n }\n }\n }\n }\n\n var matchedDate = baseDate.findMatch(dateHash, bOffsetSpecified ? [0, 6000] : leadTime);\n if (matchedDate != null)\n {\n var newMatchedDate = matchedDate;\n if (dateHash["recurdays"] != null)\n {\n while (newMatchedDate.getTime() < baseDate.getTime())\n {\n newMatchedDate = newMatchedDate.addDays(dateHash["recurdays"]);\n }\n }\n else if (dateHash["offsetyear"] != null || \n dateHash["offsetmonth"] != null || \n dateHash["offsetday"] != null || \n dateHash["offsetdayofweek"] != null)\n {\n dateHash["year"] = dateHash["offsetyear"];\n dateHash["month"] = dateHash["offsetmonth"];\n dateHash["day"] = dateHash["offsetday"];\n dateHash["dayofweek"] = dateHash["offsetdayofweek"];\n newMatchedDate = matchedDate.findMatch(dateHash, leadTime);\n //The offset couldn't be matched. return null.\n if (newMatchedDate == null)\n {\n return null;\n }\n }\n var diff2 = newMatchedDate.getDifferenceInDays(baseDate);\n if (diff2 <= leadTime[1] && diff2 >= leadTime[0])\n {\n reminderCache[hashKey] = testDate;\n return newMatchedDate;\n }\n }\n return null;\n};\n\n//This does much the same job as findDateForReminder, but\n//this one doesn't deal with offsets or recurring \n//reminders.\nDate.prototype.findMatch = function findMatch(dateHash, leadTime)\n{\n\n var bSpecifiedYear = (dateHash["year"] != null);\n var bSpecifiedMonth = (dateHash["month"] != null);\n var bSpecifiedDay = (dateHash["day"] != null);\n var bSpecifiedDayOfWeek = (dateHash["dayofweek"] != null);\n if (bSpecifiedYear && bSpecifiedMonth && bSpecifiedDay)\n {\n return new Date(dateHash["year"], dateHash["month"]-1, dateHash["day"], 0, 0);\n }\n var bMatchedYear = !bSpecifiedYear;\n var bMatchedMonth = !bSpecifiedMonth;\n var bMatchedDay = !bSpecifiedDay;\n var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;\n var searchInterval = 1;\n if ((bSpecifiedDayOfWeek && dateHash["dayofweek"] < 0) || \n dateHash["negativeOffsetDayOfWeek"] != null)\n {\n dateHash["dayofweek"] = dateHash["dayofweek"] * -1;\n searchInterval = -1;\n }\n if (bSpecifiedDay && bSpecifiedMonth && !bSpecifiedYear && !bSpecifiedDayOfWeek)\n {\n\n //Shortcut -- First try this year. If it's too small, try next year.\n var tmpMidnight = this.getMidnight();\n var tmpLeadTime = tmpMidnight.addDays(leadTime[0]);\n var tmpDate = new Date(this.getFullYear(), dateHash["month"]-1, dateHash["day"], 0,0);\n if (tmpDate.getTime() < tmpLeadTime.getTime())\n {\n tmpDate = new Date((this.getFullYear() + 1), dateHash["month"]-1, dateHash["day"], 0,0);\n }\n var diff2 = tmpDate.getDifferenceInDays(tmpMidnight);\n\n if (diff2 <= leadTime[1] && diff2 >= leadTime[0])\n {\n return tmpDate;\n }\n else\n {\n return null;\n }\n }\n\n var newDate = this;\n for (var i = 0; i <= leadTime[1]; i+=searchInterval)\n {\n newDate = newDate.addDays(searchInterval);\n var tmp = testDate(newDate, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek);\n if (tmp != null)\n {\n return tmp;\n }\n }\n//Only search backwards if we're not just trying to match the dayofweek\nif (leadTime[0] < 0 && (bSpecifiedYear || bSpecifiedMonth || bSpecifiedDay))\n{\n newDate = this;\n for (i = 0; i >= leadTime[0]; i+=(searchInterval * -1))\n {\n newDate = newDate.addDays(searchInterval * -1);\n var tmp = testDate(newDate, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek);\n if (tmp != null)\n {\n return tmp;\n }\n }\n}\n};\n\nfunction testDate(testDate, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek)\n{\n var bMatchedYear = !bSpecifiedYear;\n var bMatchedMonth = !bSpecifiedMonth;\n var bMatchedDay = !bSpecifiedDay;\n var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;\n if (bSpecifiedYear)\n {\n bMatchedYear = (dateHash["year"] == testDate.getFullYear());\n }\n if (bSpecifiedMonth)\n {\n bMatchedMonth = ((dateHash["month"] - 1) == testDate.getMonth() );\n }\n if (bSpecifiedDay)\n {\n bMatchedDay = (dateHash["day"] == testDate.getDate());\n }\n if (bSpecifiedDayOfWeek)\n {\n bMatchedDayOfWeek = (dateHash["dayofweek"] == testDate.getDay());\n }\n\n if (bMatchedYear && bMatchedMonth && bMatchedDay && bMatchedDayOfWeek)\n {\n return testDate;\n }\n};\n\n//Return a new date, with the time set to midnight (0000)\nDate.prototype.getMidnight = function getMidnight()\n{\n return new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0);\n};\n// Add the specified number of days to a date.\nDate.prototype.addDays = function addDays(numberOfDays)\n{\n return new Date(this.getFullYear(), this.getMonth(), this.getDate() + numberOfDays, 0, 0);\n};\n//Return the number of days between two dates.\nDate.prototype.getDifferenceInDays = function getDifferenceInDays(otherDate)\n{\n return Math.floor((this.getMidnight().getTime() - otherDate.getMidnight().getTime()) / 86400000);\n \n};\n\n// Substitute date components into a string\nDate.prototype.formatStringDateOnly = function formatStringDateOnly(template)\n{\n template = template.replace("YYYY",this.getFullYear());\n template = template.replace("YY",String.zeroPad(this.getFullYear()-2000,2));\n template = template.replace("MMM",config.messages.dates.months[this.getMonth()]);\n template = template.replace("0MM",String.zeroPad(this.getMonth()+1,2));\n template = template.replace("MM",this.getMonth()+1);\n template = template.replace("DDD",config.messages.dates.days[this.getDay()]);\n template = template.replace("0DD",String.zeroPad(this.getDate(),2));\n template = template.replace("DD",this.getDate());\n return template;\n};\n\n//}}}
The reminder macro can take the following arguments.\n\n!!!!date syntax\n* @@{{{year:NUMBER}}}@@ - The four digit representation of the year (for example {{{year:2046}}} or {{{year:1999}}}\n* @@{{{month:NUMBER}}}@@ - The numerical representation of the month (for example {{{month:1}}} for January, {{{month:12}}} for December)\n* @@{{{day:NUMBER}}}@@ - The numerical representation of the day of the month (for example {{{day:15}}} will match the 15th day of the month)\n* @@{{{dayofweek:NUMBER}}}@@ - The numerical representation of the day of the week. Valid values are in the range of 0-6. {{{dayofweek:0}}} will match Sunday, and {{{dayofweek:6}}} will match Saturday.\n\n!!!!offsets\n* @@{{{offsetdayofweek:NUMBER}}}@@ - The numerical representation of a day of the week. Valid values are in the range of 0-6. 0 will match Sunday, and 6 will match Saturday. If offsetdayofweek is specified, the year, month, day and dayofweek will be matched as usual, and the reminder will be set to the next occurence of the day of the week specified by offsetdayofweek. For example, the first Thursday of the month can be specified as {{{day:1 offsetdayofweek:4}}} and the second Thursday can be specified as {{{day:8 offsetdayofweek4}}} If offsetdayofweek is negative, the search will be performed backward. For example, the last Thursday in August can be found by {{{month:8 day:31 offsetdayofweek:-4}}}\n* @@{{{recurdays:NUMBER}}}@@ - If recurdays is set, then the reminder will fire on the base date specified by year, month, day, and dayofweek and also every N days afterward. For example, if the reminder is specified with {{{year:2005 month:8 day:16 recurdays:2}}} it will match August 16, 18, 20, etc. Please make sure that you fully specify year, month and day in any recurring reminder.\n\n!!!!leadtime\n* @@{{{leadtime:NUMBER}}}@@ - Use this to specify when this reminder will appear in [[showReminders]]. If a reminder has a leadtime of 2, it will only show up in showReminders if it will be matched in the next two days. Likewise, a reminder with a leadtime of 60 will show up in showReminders even if showReminders has a lower leadtime. showReminders can override this behavior with the limit argument.\n\n!!!!Reminder display options\n* @@{{{title:"STRING"}}}@@ - A string used to identify this reminder when it is shown in a list of reminders. For example, {{{title:"New Year's Day"}}} or {{{title:"Elvis' Birthday"}}}. You can put standard TiddlyWiki formatting in the title.\n* @@{{{format:"STRING"}}}@@ - Use this argument to override the default string used for display. You can put standard TiddlyWiki formatting in the format. The following substitutions will be made in the string before it is displayed.\n** DIFF will be replaced with the one of the strings "Today", "Tommorrow", or "N days", where N is the number of days between now and the date of the reminder. \n** TITLE will be replaced with the title of the reminder\n** DATE will be replaced with the matched date of the reminder.\n** ANNIVERSARY will be replaced with the number of years since between the matched date and firstyear\nThe default string is "DIFF: TITLE on DATE ANNIVERSARY"\n* @@{{{firstyear:NUMBER}}}@@ - The first year that a reminder occurred, in four digit format. For example {{{firstyear:2001}}}. This is used when calculating the number of years that a reminder has happened.\n* @@{{{hidden}}}@@ - If this option is present, the reminder will not be displayed in the regular view of the tiddler. You can use this to have reminders for [[displayTiddlersWithReminders]] to find, without having the countdown appear. See [[Season's Greetings example]] for an example.
If you rename a Tiddler and it lives in MainMenu or DefaultTiddlers, you'll need to update those SpecialTiddlers manually.
It's easy to make your own TiddlyWiki that you can publish yourself - see how to SaveChanges for details. If you want to change the layout or the colour scheme, you'll need some basic HTML and CSS knowledge.
GTDTiddlyWiki will incorporate [[updates|http://www.osmosoft.com/#RevisionHistory]] from the official TiddlyWiki and other contributors as appropriate. If you'd like to contribute to development, go the GTDTWForum.\n\nTo see my changes to Javascript, search the source code for "Nathan Edit".\n\nHowToUpgrade | UpdateNotification | VersionArchive\n\n! version 1.0.6 September 3rd 2005\n# Full rebuild based on TiddlyWiki Revision 1.2.32.\n\n! version 1.0.5 May 21st 2005\n# Added version number to footer and VersionArchive (major update soon).\n\n! version 1.0.4 May 17th 2005\n# Added JeremyRuston's CustomStyleSheet feature.\n\n! version 1.0.3 May 17th 2005\n# Now works in Safari (requires [[plugin by Jonathan Paisley|http://www.accela.net/~dankna/tiddlywiki/]]) Thanks Jonathan! \n# Constrained printed images to fit 3x5 cards (this won't work in IE)\n# Added saving on delete and put a small "save" link back into the sidebar.\n# Added links to GTDTWForum and RSS UpdateNotification\n\n! version 1.0.2 May 13th 2005\n# When "done" button or CRTL+ENTER is pressed to make changes to a Tiddler, entire wiki is saved and a backup is created. This should prevent accidental data loss. (Thanks to Ron, Jamie, and Terminus in the [[group|http://groups-beta.google.com/group/GTD-TiddlyWiki/browse_frm/thread/809f958426038e94?hl=en]])\n# Removed "Save Successful" confirmation dialog.\n# Removed big happy "Save" button (and died a little inside) ;) to avoid user ambiguity about saving. Also removed [alt+s] save.\n# Added Camino compatability ([[Thanks Schlafer|http://tinyurl.com/aeqpt]])\n# Added DevelopmentTips\n\n! version 1.0.1 May 10th 2005\n# Added TiddlyWiki fixes from original version 1.2.6\n\n! version 1.0.0 May 9th, 2005\n# Added print style sheet\n# Overhaul of CSS layout\n# Added alt + s quicksave with a simple accesskey attribute.\n# Changed sidebar "Timeline" and "All" to remove BR tags and extra Spaces. Check the javascript functions refreshTabTimeline() and refreshTabAll()\n# Changed incremental date stamped "backup on save" to a single backup file. See the saveChanges() javscript function in this page's source to re-enable datestamped backup.
/***\nIntended for use in ViewTemplate\n!Examples\n|{{{<<runMacroIfTagged [[Groceries]] toggleTag Buy>>}}}|<<runMacroIfTagged [[Groceries]] toggleTag Buy>>|\n|{{{<<runMacroIfTagged Plugins toggleTag systemConfig>>}}}|<<runMacroIfTagged Plugins toggleTag systemConfig>>|\n***/\n//{{{\n\n// This function contributed by Eric Shulman\nfunction toggleTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)==null) t.tags.push(tag)\n else t.tags.splice(t.tags.find(tag),1)\n}\n\n// This function contributed by Eric Shulman\nfunction isTagged(title,tag) {\n var t=store.getTiddler(title); if (!t) return false;\n return (t.tags.find(tag)!=null);\n}\n\nconfig.macros.runMacroIfTagged = {};\nconfig.macros.runMacroIfTagged.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (isTagged(tiddler.title,params[0]))\n config.macros[params[1]].handler(place,params[1],params.slice(2),wikifier,paramString/*fixme*/,tiddler);\n}\n\n//}}}\n/***\n!Todo\n* paramString needs to have the first word removed from the front of it at fixme above\n\n\n***/\n\n
You can SaveChanges if you're using FireFox or InternetExplorer:\n# if you're using Windows XP you might run into ServicePack2Problems\n# right click on [[this link|#]] and select 'Save link as...' or 'Save target as...'\n** choose where to save the file, and what to call it (but keep the .HTML extension)\n# open the newly downloaded file in your browser\n# click the 'options' button to set your username\n# edit, create and delete the tiddlers you want\n** you can change the SpecialTiddlers to change the SiteTitle and MainMenu etc.\n# Every time you click "done" or "delete" when editing a Tiddler, your changes are saved and a backup of the last saved state is created (customize this in the options panel).\n
/***\n''SearchOptionsPlugin for TiddlyWiki version 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#SearchOptionsPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nThe TiddlyWiki search function normally looks in both tiddler titles and tiddler body content ('text'). However, narrowing the search so that it examines only titles or only text, or expanding the search to include text contained in tiddler tags can be very helpful, especially when searching on common words or phrases. In addition, it is often useful for the search results to show tiddlers with matching titles before tiddlers that contain matching text or tags.\n\n!!!!!Usage\n<<<\nThis plugin adds checkboxes (see below and in AdvancedOptions) to let you selectively configure the TiddlyWiki search function to just examine any combination of tiddler titles, text, or tags. It also provides an option to switch the search results order between 'titles mixed in' (default) and 'titles shown first', as well as an option display the search results as a list of links (in an auto-generated "SearchResults" tiddler), rather than actually displaying all matching tiddlers. You can also enable/disable the "incremental search" (key-by-key searching), so that a search is only initiated when you press the ENTER key or click on the "search:" prompt text.\n<<<\n!!!!!Configuration\n<<<\nIn additional to the checkboxes in AdvancedOptions, a self-contained control panel is included here for your convenience:\n<<option chkSearchTitles>> Search tiddler titles\n<<option chkSearchText>> Search tiddler text\n<<option chkSearchTags>> Search in tiddler tags\n<<option chkSearchTitlesFirst>> Show title matches first\n<<option chkSearchList>> Show list of matching tiddlers\n<<option chkSearchIncremental>> Incremental searching\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''SearchOptionsPlugin'' (tagged with <<tag systemConfig>>)\n^^documentation and javascript for SearchOptionsPlugin handling^^\n\nWhen installed, this plugin automatically adds checkboxes in the AdvancedOptions shadow tiddler so you can enable/disable the extended search behavior. However, if you have customized your AdvancedOptions, you will need to manually add {{{<<option chkSearchTitles>>}}}, {{{<<option chkSearchText>>}}} and {{{<<option chkSearchTitlesFirst>>}}} (with suitable prompt text) to your customized tiddler.\n<<<\n!!!!!Revision History\n<<<\n''2006.02.03 [2.2.1]''\nrewrite timeout clearing code and blank search text handling to match 2.0.4 core release changes. note that core no longer permits "blank=all" searches, so neither does this plugin. To search for all, use "." with text patterns enabled.\n''2006.02.02 [2.2.0]''\nin search.handler(), KeyHandler() function clears 'left over' timeout when search input is < 3 chars. Prevents searching on shorter text when shortened by rapid backspaces (<500msec)\n''2006.02.01 [2.1.9]''\nin Story.prototype.search(), correct inverted logic for using/not using regular expressions when searching\nalso, blank search text now presents "No search text. Continue anyway?" confirm() message box, so search on blank can still be processed if desired by user.\n''2006.02.01 [2.1.8]''\nin doSearch(), added alert/return if search text is blank\n''2006.01.20 [2.1.7]''\nfixed setting of config.macros.search.reportTitle so that Tweaks can override it.\n''2006.01.19 [2.1.6]''\nimproved SearchResults formatting, added a "search again" form to the report (based on a suggestion from MorrisGray)\ndefine results report title using config.macros.search.reportTitle instead of hard-coding the tiddler title\n''2006.01.18 [2.1.5]''\nCreated separate functions for reportSearchResults(text,matches) and discardSearchResults(), so that other developers can create alternative report generators.\n''2006.01.17 [2.1.4]''\nUse regExp.search() instead of regExp.test() to scan for matches. Correctd the problem where only half the matching tiddlers (the odd-numbered ones) were being reported.\n''2006.01.15 [2.1.3]''\nAdded information (date/time, username, search options used) to SearchResults output\n''2006.01.10 [2.1.2]''\nuse displayTiddlers() to render matched tiddlers. This lets you display multiple matching tiddlers, even if SinglePageModePlugin is enabled.\n''2006.01.08 [2.1.1]''\ncorrected invalid variable reference, "txt.value" to "text" in story.search()\n''2006.01.08 [2.1.0]''\nre-write to match new store.search(), store.search.handler() and story.search() functions.\n''2005.12.30 [2.0.0]''\nUpgraded to TW2.0\nwhen rendering SearchResults tiddler, closeTiddler() first to ensure display is refreshed.\n''2005.12.26 [1.4.0]''\nadded option to search for matching text in tiddler tags\n''2005.12.21 [1.3.7]''\nuse \s\s to 'escape' single quotes in tiddler titles when generating "Open all matching tiddlers" link. Also, added access key: "O", to trigger "open all" link.\nBased on a suggestion by UdoBorkowski.\n''2005.12.18 [1.3.6]''\ncall displayMessage() AFTER showing matching tiddlers so message is not cleared too soon\n''2005.12.17 [1.3.5]''\nif no matches found, just display message and delete any existing SearchResults tiddler.\n''2005.12.17 [1.3.4]''\nuse """{{{""" and """}}}""" to 'escape' display text in SearchResults tiddler to ensure that formatting contained in search string is not rendered \nBased on a suggestion by UdoBorkowski.\n''2005.12.14 [1.3.3]''\ntag SearchResults tiddler with 'excludeSearch' so it won't list itself in subsequent searches\nBased on a suggestion by UdoBorkowski.\n''2005.12.14 [1.3.2]''\nadded "open all matching tiddlers..." link to search results output.\nBased on a suggestion by UdoBorkowski.\n''2005.12.10 [1.3.1]''\nadded "discard search results" link to end of search list tiddler output for quick self-removal of 'SearchResults' tiddler.\n''2005.12.01 [1.3.0]''\nadded chkSearchIncremental to enable/disable 'incremental' searching (i.e., search after each keystroke) (default is ENABLED).\nadded handling for Enter key so it can be used to start a search.\nBased on a suggestion by LyallPearce\n''2005.11.25 [1.2.1]''\nrenamed from SearchTitleOrTextPlugin to SearchOptionsPlugin\n''2005.11.25 [1.2.0]''\nadded chkSearchList option\nBased on a suggestion by RodneyGomes\n''2005.10.19 [1.1.0]''\nadded chkSearchTitlesFirst option.\nBased on a suggestion by ChristianHauck\n''2005.10.18 [1.0.0]''\nInitial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].\nBased on a suggestion by LyallPearce.\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.SearchTitleOrText = {major: 2, minor: 2, revision: 1, date: new Date(2006,2,3)};\n//}}}\n\n//{{{\nif (config.options.chkSearchTitles==undefined) config.options.chkSearchTitles=true;\nif (config.options.chkSearchText==undefined) config.options.chkSearchText=true;\nif (config.options.chkSearchTags==undefined) config.options.chkSearchTags=true;\nif (config.options.chkSearchTitlesFirst==undefined) config.options.chkSearchTitlesFirst=false;\nif (config.options.chkSearchList==undefined) config.options.chkSearchList=false;\nif (config.options.chkSearchIncremental==undefined) config.options.chkSearchIncremental=true;\n\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkSearchTitles>> Search in tiddler titles";\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkSearchText>> Search in tiddler text";\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkSearchTags>> Search in tiddler tags";\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkSearchTitlesFirst>> Search results show title matches first";\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkSearchList>> Search results show list of matching tiddlers";\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkSearchIncremental>> Incremental searching";\n//}}}\n\n//{{{\nif (config.macros.search.reportTitle==undefined)\n config.macros.search.reportTitle="SearchResults";\n//}}}\n\n//{{{\nconfig.macros.search.handler = function(place,macroName,params)\n{\n var lastSearchText = "";\n var searchTimeout = null;\n var doSearch = function(txt)\n {\n if (txt.value.length>0)\n {\n story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);\n lastSearchText = txt.value;\n }\n };\n var clickHandler = function(e)\n {\n doSearch(this.nextSibling);\n return false;\n };\n var keyHandler = function(e)\n {\n if (!e) var e = window.event;\n switch(e.keyCode)\n {\n case 13: // ELS: handle enter key\n doSearch(this);\n break;\n case 27:\n this.value = "";\n clearMessage();\n break;\n }\n if (config.options.chkSearchIncremental)\n {\n if(this.value.length > 2)\n {\n if(this.value != lastSearchText)\n {\n if(searchTimeout) clearTimeout(searchTimeout);\n var txt = this;\n searchTimeout = setTimeout(function() {doSearch(txt);},500);\n }\n }\n else\n if(searchTimeout) clearTimeout(searchTimeout);\n }\n };\n var focusHandler = function(e)\n {\n this.select();\n };\n var btn = createTiddlyButton(place,this.label,this.prompt,clickHandler);\n var txt = createTiddlyElement(place,"input",null,null,null);\n if(params[0])\n txt.value = params[0];\n txt.onkeyup = keyHandler;\n txt.onfocus = focusHandler;\n txt.setAttribute("size",this.sizeTextbox);\n txt.setAttribute("accessKey",this.accessKey);\n txt.setAttribute("autocomplete","off");\n if(config.browser.isSafari)\n {\n txt.setAttribute("type","search");\n txt.setAttribute("results","5");\n }\n else\n txt.setAttribute("type","text");\n}\n//}}}\n\n//{{{\nStory.prototype.search = function(text,useCaseSensitive,useRegExp)\n{\n highlightHack = new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");\n var matches = store.search(highlightHack,"title","excludeSearch");\n var q = useRegExp ? "/" : "'";\n clearMessage();\n if (!matches.length) {\n if (config.options.chkSearchList) discardSearchResults();\n displayMessage(config.macros.search.failureMsg.format([q+text+q]));\n } else {\n if (config.options.chkSearchList) \n reportSearchResults(text,matches);\n else {\n var titles = []; for(var t=0; t<matches.length; t++) titles.push(matches[t].title);\n this.closeAllTiddlers(); story.displayTiddlers(null,titles);\n displayMessage(config.macros.search.successMsg.format([matches.length, q+text+q]));\n }\n }\n highlightHack = null;\n}\n//}}}\n\n//{{{\nTiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag)\n{\n var candidates = this.reverseLookup("tags",excludeTag,false,sortField);\n\n // scan for matching titles\n var title_results = [];\n if (config.options.chkSearchTitles)\n for(var t=0; t<candidates.length; t++)\n if(candidates[t].title.search(searchRegExp)!=-1)\n title_results.push(candidates[t]);\n\n // scan for matching text\n var text_results = [];\n if (config.options.chkSearchText)\n for(var t=0; t<candidates.length; t++)\n if(candidates[t].text.search(searchRegExp)!=-1)\n text_results.push(candidates[t]);\n\n // scan for matching tags\n var tag_results = [];\n if (config.options.chkSearchTags)\n for(var t=0; t<candidates.length; t++)\n if(candidates[t].tags.join(" ").search(searchRegExp)!=-1)\n tag_results.push(candidates[t]);\n\n // merge the results, eliminating redundant matches\n var results = [];\n for(var t=0; t<title_results.length; t++) results.pushUnique(title_results[t]);\n for(var t=0; t<text_results.length; t++) results.pushUnique(text_results[t]);\n for(var t=0; t<tag_results.length; t++) results.pushUnique(tag_results[t]);\n\n // if not 'titles first', re-sort results to so titles, text and tag matches are mixed together\n if(!sortField) sortField = "title";\n var bySortField=function (a,b) {if(a[sortField] == b[sortField]) return(0); else return (a[sortField] < b[sortField]) ? -1 : +1; }\n if (!config.options.chkSearchTitlesFirst) results.sort(bySortField);\n return results;\n}\n//}}}\n\n// // ''REPORT GENERATOR''\n//{{{\nif (!window.reportSearchResults) window.reportSearchResults=function(text,matches)\n{\n var title=config.macros.search.reportTitle\n var q = config.options.chkRegExpSearch ? "/" : "'";\n var body="";\n\n // summary: nn tiddlers found matching '...', options used\n body+="''"+config.macros.search.successMsg.format([matches.length,q+"{{{"+text+"}}}"+q])+"''\sn";\n body+="^^//searched in:// ";\n body+=(config.options.chkSearchTitles?"''titles'' ":"");\n body+=(config.options.chkSearchText?"''text'' ":"");\n body+=(config.options.chkSearchTags?"''tags'' ":"");\n if (config.options.chkCaseSensitiveSearch||config.options.chkRegExpSearch) {\n body+=" //with options:// ";\n body+=(config.options.chkCaseSensitiveSearch?"''case sensitive'' ":"");\n body+=(config.options.chkRegExpSearch?"''text patterns'' ":"");\n }\n body+="^^";\n\n // numbered list of links to matching tiddlers\n body+="\sn<<<";\n for(var t=0;t<matches.length;t++) body+="\sn# [["+matches[t].title+"]]";\n body+="\sn<<<\sn";\n\n // open all matches button\n body+="<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n body+="onclick=\s"story.displayTiddlers(null,["\n for(var t=0;t<matches.length;t++)\n body+="'"+matches[t].title.replace(/\s'/mg,"\s\s'")+"'"+((t<matches.length-1)?", ":"");\n body+="],1);\s" ";\n body+="accesskey=\s"O\s" ";\n body+="value=\s"open all matching tiddlers\s"></html> ";\n\n // discard search results button\n body+="<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n body+="onclick=\s"story.closeTiddler('"+title+"'); store.deleteTiddler('"+title+"');\s" ";\n body+="value=\s"discard "+title+"\s"></html>";\n\n // search again\n body+="\sn\sn----\sn";\n body+="<<search \s""+text+"\s">> ";\n body+="<<option chkSearchTitles>>titles ";\n body+="<<option chkSearchText>>text ";\n body+="<<option chkSearchTags>>tags";\n body+="<<option chkCaseSensitiveSearch>>case-sensitive ";\n body+="<<option chkRegExpSearch>>text patterns";\n\n // create/update the tiddler\n var tiddler=store.getTiddler(title); if (!tiddler) tiddler=new Tiddler();\n tiddler.set(title,body,config.options.txtUserName,(new Date()),"excludeLists excludeSearch");\n store.addTiddler(tiddler); story.closeTiddler(title);\n\n // use alternate "search again" label in <<search>> macro\n var oldprompt=config.macros.search.label;\n config.macros.search.label="search again";\n\n // render tiddler\n story.displayTiddler(null,title,1); // force refresh\n\n // restore standard search label\n config.macros.search.label=oldprompt;\n\n}\n\nif (!window.discardSearchResults) window.discardSearchResults=function()\n{\n // remove the tiddler\n story.closeTiddler(config.macros.search.reportTitle);\n store.deleteTiddler(config.macros.search.reportTitle);\n}\n//}}}
Released in December 2004, the [[second version|secondversion.html]] of TiddlyWiki grew 50% over the FirstVersion to 76KB. It added IncrementalSearch, the ReferencesButton, the PermaLinkButton, PermaView, CloseAll, SmoothScrolling, an ImprovedSidebar, an animation for the CloseButton and a tiny EasterEgg in homage to Macintosh OS X. It also introduced a new SiteDesign.
/***\n| ''Name'' |Selective Tag Chooser|\n| ''Version'' |0.1|\n| ''Source'' |[[Rich Carrillo|http://www.kultofbubb.net/tiddlywiki/]]|\n| ''Author'' |[[RichCarrillo|RichCarrillo@gmail.com]]|\n| ''Type'' |Macro (for EditTemplate)|\n| ''Required'' |TiddlyWiki 2.0+|\n| ''License'' ||\n\n!Revision History\n|20060125|0.1|First release - very rough. I havent tested much.|\n\n\n!Description\nThis macro will create a button that works very similarly to the existing "Tag Chooser" button. With this macro you can choose what to list in the pop-up menu by passing a tag to the macro. The pop-up will list everything tagged with that tag and when you choose an item, it will tag the current tiddler with the chosen tag.\nThis is intened to be used in EditTemplates, just as the existing tag chooser is.\n\n!Installation\nImport (or copy the contents of) this Tiddler into your Wiki.\nTag it with systemConfg, Save and Refresh.\n\n!Syntax\n|{{{<<SelectiveTagChooser [button label] [button tooltip] [tag to list]>>}}}| It will list all tiddlers tagged with the parameter you give it. You will then be able to tag your current tiddler with a tiddler off the list.|\n\nI've included some example templates. Copy over all Tiddlers tagged with SelectiveTagChooserMacro to get you started.\n\n!Example\n<<SelectiveTagChooser "Projects" "Tag this tiddler with a Project" Projects>>\n\n!Credits\nMost of this code is adaptions of TiddlyWiki core functions.\n\n!Roadmap - ToDo list\n*Define our own button label, instead of just stealing tagChooser's\n*Let users pass mulitple tags to list.\n*Improve documentation. I did this in 15 minutes and I doubt if it makes sense\n\n!Code\n***/\n//{{{\n// default settings\nconfig.macros.SelectiveTagChooser = { }\n\nconfig.macros.SelectiveTagChooser.handler = function(place,macroName,params,wikifier,paramString,tiddler)\n{\n if(tiddler instanceof Tiddler)\n {\n var title = tiddler.title;\n var lingo = config.views.editor.tagChooser;\n var buttonLabel=params[0];\n var buttonTooltip=params[1];\n// start my stuff\n var tagToList = params[2];\n var tagList = store.getTaggedTiddlers(tagToList);\n var tiddlerTitles = [];\n var li,r;\n for(r=0;r<tagList.length;r++)\n if(tagList[r].title != tiddlerTitles){\n tiddlerTitles.push(tagList[r].title);}\n// end my stuff\n var ontagclick = function(e) {\n if (!e) var e = window.event;\n var tag = this.getAttribute("tag");\n story.setTiddlerTag(title,tag,0);\n return(false);\n };\n var onclick = function(e) {\n if (!e) var e = window.event;\n var popup = Popup.create(this);\n// start my stuff\n var tags = tiddlerTitles;\n // var tags = store.getTags();\n// end my stuff\n if(tags.length == 0)\n createTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone);\n for (var t=0; t<tags.length; t++)\n {\n// start my stuff\n var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t],lingo.tagTooltip.format([tags[t]]),ontagclick);\n theTag.setAttribute("tag",tags[t]);\n\n // var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),ontagclick);\n // theTag.setAttribute("tag",tags[t][0]);\n// end my stuff\n }\n Popup.show(popup,false);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n };\n createTiddlyButton(place,buttonLabel,buttonTooltip,onclick);\n }\n}\n\n//}}}\n
One of the neatest features of TiddlyWiki is that it is entirely self-contained in a single HTML file. It contains the actual hypertext document, and the JavaScript, CascadingStyleSheets and HTML necessary to both view and edit the document. This means that it is trivial to host a TiddlyWiki on a website, or to distribute one by email. And anyone with a reasonably recent web browser will be able to read and edit it.
"How do I run this on a server?" is the number one question people ask. \n\nThe answer is "You can't, and it's a feature, not a bug." \n\nThe idea behind TiddlyWiki is that you can update it from any device with a capable browser, whether you are connected or not. It's personal, not collaborative, though you could upload your version to your server if you wanted people to see your lists (PermaView is good for this).\n\nThe good news is that there are online versions of TiddlyWiki that you can find at [[Jeremy's site|http://www.tiddlywiki.com/#TiddlyWikiAdaptations]], and if you like the things I've done with GTDTiddlyWiki you could merge my version into other TiddlyWiki implementations.
Internet Explorer Windows XP SP2 seems to have a magical ability to keep track of html files that have been downloaded from the internet and saved on an NTFS drive. By storing additional data in an [[alternate data stream|http://www.jsware.net/jsware/sviewer.html]], it manages to keep them in the 'Internet Zone' regardless of attempts to rename or modify the file. But, in order to be able to SaveChanges, TiddlyWiki needs to run in the 'My Computer Zone'.\n\nThere are a couple of ways around the problem:\n* save the TiddlyWiki HTML file to a FAT drive (eg a USB thumb drive)\n* open the downloaded file with a text editor and save it again under a different name\n\nIn either case, The new file will open in 'My Computer Zone', which in turn causes Internet Explorer to put up it's information bar asking you whether you want to run it. You need to 'Allow blocked content' to let TiddlyWiki do it's stuff.\n\nThis is all a bit frustrating. An easy alternative is to use FireFox, which seems to do the trick on all platforms.
<<list shadowed>>
<part RecentEvents>\n! Last 3 Days\n<<showReminders leadtime:-3...-1 limit>>\n</part>\n<part TodaysEvents>\n! Today\n<<showReminders leadtime:0 limit>>\n</part>\n<part FutureEvents>\n! Next 30 days\n<<showReminders leadtime:1...30 limit>>\n</part>
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>><<tableOfContents label: sort:title size:1 inline>>
www.tedpavlic.com
tpavlic
/gtd/store.php
[[your gtd wiki|#]]
[[Un-Kinked GTDTiddlyWiki Plus|About GTD TiddlyWiki]]
http://www.tedpavlic.com/gtdtw.xml
// Begin SORTABLE.JS//\n// This Code is://\n// Code downloaded from the Browser Experiments section of kryogenix.org is licenced under the so-called MIT licence. The license is below.//\n////\n// Copyright (c) 1997-date Stuart Langridge//\n////\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this //\n// software and associated documentation files (the "Software"), to deal in the Software //\n// without restriction, including without limitation the rights to use, copy, modify, merge, //\n// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons //\n// to whom the Software is furnished to do so, subject to the following conditions://\n////\n// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //\n// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR //\n// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE //\n// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR //\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //\n// DEALINGS IN THE SOFTWARE.//\n// //\n// //\n// Modified under the same aforementioned terms by Demian Johnston, 2006//\n/*\n! Test Cases\nSortable\nGrid requires the header row to be marked "|h"\n\n|Name |Salary|Extension |Start date|h\n|Bloggs, Fred |$12000.00 |1353|08/19/2003|\n|Bloggs, Fred |$12000.00 |1353|09/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/18/2003|\n|Bloggs, Fred |$12000.00 |1353|07/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/17/2003|\n|Turvey, Kevin |$191200.00 |2342 |02/05/1979|\n|Mbogo, Arnold |$32010.12 |2755 |09/08/1998|\n|Shakespeare, Bill |$122000.00|3211 |12/11/1961|\n|Shakespeare, Hamnet |$9000 |9005|01/01/2002|\n|Fitz, Marvin |$3300 |5554 |05/22/1995|\n\nUnsortableGrid (doesn't mark header row)\n\n|Name |Salary|Extension |Start date|\n|Bloggs, Fred |$12000.00 |1353|08/19/2003|\n|Bloggs, Fred |$12000.00 |1353|09/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/18/2003|\n|Bloggs, Fred |$12000.00 |1353|07/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/17/2003|\n|Turvey, Kevin |$191200.00 |2342 |02/05/1979|\n|Mbogo, Arnold |$32010.12 |2755 |09/08/1998|\n|Shakespeare, Bill |$122000.00|3211 |12/11/1961|\n|Shakespeare, Hamnet |$9000 |9005|01/01/2002|\n|Fitz, Marvin |$3300 |5554 |05/22/1995|\n\nCredit to Stuart Langridge,November 2003\nhttp://www.kryogenix.org/code/browser/sorttable/\n*/\n//{{{\nversion.extensions.sortableGrid= {major: 1, minor: 0, revision: 0, date: new Date(2006,2,14)};\n//}}}\n//{{{\nconfig.macros.sortableGridPlugin = {SORT_COLUMN_INDEX: 0};\n\nconfig.macros.sortableGridPlugin.ts_makeSortable=function(table) {\n var firstRow;\n if (table.rows && table.rows.length > 0) {\n firstRow = table.rows[0];\n }\n if (!firstRow) return;\n \n // We have a first row: assume it's the header, and make its contents clickable links\n for (var i=0;i<firstRow.cells.length;i++) {\n var cell = firstRow.cells[i];\n var txt = config.macros.sortableGridPlugin.ts_getInnerText(cell);\n cell.innerHTML = '<a href="#" class="sortheader" onclick="config.macros.sortableGridPlugin.ts_resortTable(this);return false;">'+txt+'<span class="sortarrow">&nbsp;&nbsp;&nbsp;</span></a>';\n }\n};\n//}}}\n\n//{{{\nconfig.macros.sortableGridPlugin.ts_getInnerText=function(el) {\n if (typeof el == "string") return el;\n if (typeof el == "undefined") { return el };\n if (el.innerText) return el.innerText; //Not needed but it is faster\n var str = "";\n \n var cs = el.childNodes;\n var l = cs.length;\n for (var i = 0; i < l; i++) {\n switch (cs[i].nodeType) {\n case 1: //ELEMENT_NODE\n str += config.macros.sortableGridPlugin.ts_getInnerText(cs[i]);\n break;\n case 3: //TEXT_NODE\n str += cs[i].nodeValue;\n break;\n }\n }\n return str;\n};\n\nconfig.macros.sortableGridPlugin.getParent=function(el, pTagName) {\n if (el == null) return null;\n else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase\n return el;\n else\n return config.macros.sortableGridPlugin.getParent(el.parentNode, pTagName);\n};\n//}}}\n\n//{{{\nconfig.macros.sortableGridPlugin.ts_resortTable=function(lnk) {\n // get the span\n var span;\n for (var ci=0;ci<lnk.childNodes.length;ci++) {\n if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];\n }\n var td = lnk.parentNode;\n var column = td.cellIndex;\n var table = config.macros.sortableGridPlugin.getParent(td,'TABLE');\n \n // Work out a type for the column\n if (table.rows.length <= 1) return;\n var itm = config.macros.sortableGridPlugin.ts_getInnerText(table.rows[1].cells[column]);\n var sortfn = config.macros.sortableGridPlugin.ts_sort_caseinsensitive;\n if (itm.match(/^\sd\sd[\s/-]\sd\sd[\s/-]\sd\sd\sd\sd$/)) sortfn = config.macros.sortableGridPlugin.ts_sort_date;\n if (itm.match(/^\sd\sd[\s/-]\sd\sd[\s/-]\sd\sd$/)) sortfn = config.macros.sortableGridPlugin.ts_sort_date;\n if (itm.match(/^[?$]/)) sortfn = config.macros.sortableGridPlugin.ts_sort_currency;\n if (itm.match(/^[\sd\s.]+$/)) sortfn = config.macros.sortableGridPlugin.ts_sort_numeric;\n config.macros.sortableGridPlugin.SORT_COLUMN_INDEX = column;\n var firstRow = new Array();\n var newRows = new Array();\n for (var i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }\n for (var j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }\n\n newRows.sort(sortfn);\n var ARROW;\n if (span.getAttribute("sortdir") == 'down') {\n ARROW = '&nbsp;&nbsp;&uarr;';\n newRows.reverse();\n span.setAttribute('sortdir','up');\n } else {\n ARROW = '&nbsp;&nbsp;&darr;';\n span.setAttribute('sortdir','down');\n }\n \n // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones\n // don't do sortbottom rows\n for ( i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}\n // do sortbottom rows only\n for ( i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}\n \n // Delete any other arrows there may be showing\n var allspans = document.getElementsByTagName("span");\n for ( ci=0;ci<allspans.length;ci++) {\n if (allspans[ci].className == 'sortarrow') {\n if (config.macros.sortableGridPlugin.getParent(allspans[ci],"table") == config.macros.sortableGridPlugin.getParent(lnk,"table")) { // in the same table as us?\n allspans[ci].innerHTML = '&nbsp;&nbsp;&nbsp;';\n }\n }\n }\n \n span.innerHTML = ARROW;\n};\n//}}}\n\n//{{{\n config.macros.sortableGridPlugin.ts_sort_date=function(a,b) {\n // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX\n var mmdd=1; // US Mode (set to 0) for dd/mm/yyyy\n\n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n var dt1;\n var dt2;\n var yr;\n if (aa.length == 10) {\n if (mmdd)\n dt1 = aa.substr(6,4)+aa.substr(0,2)+aa.substr(3,2);\n else\n dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);\n } else {\n yr = aa.substr(6,2);\n if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }\n if (mmdd)\n dt1 = yr+aa.substr(0,2)+aa.substr(3,2);\n else\n dt1 = yr+aa.substr(3,2)+aa.substr(0,2);\n }\n if (bb.length == 10) {\n if (mmdd)\n dt2 = bb.substr(6,4)+bb.substr(0,2)+bb.substr(3,2);\n else\n dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);\n } else {\n yr = bb.substr(6,2);\n if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }\n if (mmdd)\n dt2 = yr+bb.substr(0,2)+bb.substr(3,2);\n else\n dt2 = yr+bb.substr(3,2)+bb.substr(0,2);\n }\n if (dt1==dt2) return 0;\n if (dt1<dt2) return -1;\n return 1;\n};\n\n config.macros.sortableGridPlugin.ts_sort_currency=function(a,b) { \n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');\n return parseFloat(aa) - parseFloat(bb);\n};\n\n config.macros.sortableGridPlugin.ts_sort_numeric=function(a,b) { \n var aa = parseFloat(config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]));\n if (isNaN(aa)) aa = 0;\n var bb = parseFloat(config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX])); \n if (isNaN(bb)) bb = 0;\n return aa-bb;\n};\n\n config.macros.sortableGridPlugin.ts_sort_caseinsensitive=function(a,b) {\n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).toLowerCase();\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).toLowerCase();\n if (aa==bb) return 0;\n if (aa<bb) return -1;\n return 1;\n};\n\n config.macros.sortableGridPlugin.ts_sort_default=function(a,b) {\n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n if (aa==bb) return 0;\n if (aa<bb) return -1;\n return 1;\n};\n//}}}\n\n// end Code downloaded from the Browser Experiments section of kryogenix.org is licenced under the so-called MIT licence. The license is below.//\n// //\n// end Copyright (c) 1997-date Stuart Langridge//\n// END SORTABLE.JS//\n\n\n\n//{{{\nconfig.formatters[0].handler=function(w)\n {\n var table = createTiddlyElement(w.output,"table");\n w.nextMatch = w.matchStart;\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n var currRowType = null, nextRowType;\n var rowContainer, rowElement;\n var prevColumns = [];\n var rowCount = 0;\n var want_sortable=0;\n do {\n lookaheadRegExp.lastIndex = w.nextMatch;\n var lookaheadMatch = lookaheadRegExp.exec(w.source);\n var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;\n if(matched)\n {\n nextRowType = lookaheadMatch[2];\n if(nextRowType != currRowType)\n rowContainer = createTiddlyElement(table,this.rowTypes[nextRowType]);\n currRowType = nextRowType;\n if(currRowType == "c")\n {\n if(rowCount == 0)\n rowContainer.setAttribute("align","top");\n else\n rowContainer.setAttribute("align","bottom");\n w.nextMatch = w.nextMatch + 1;\n w.subWikify(rowContainer,this.rowTerminator);\n table.insertBefore(rowContainer,table.firstChild);\n }\n else\n {\n var rowClass = (rowCount & 1) ? "oddRow" : "evenRow";\n rowElement = createTiddlyElement(rowContainer,"tr",null,rowClass);\n this.rowHandler(w,rowElement,prevColumns);\n }\n if(currRowType == "h") {\n want_sortable=1;\n }\n rowCount++;\n }\n } while(matched);\n if (want_sortable) {\n table.setAttribute("class","sortable");\n config.macros.sortableGridPlugin.ts_makeSortable(table);\n }\n };\n\n//}}}
TiddlyWiki uses several special tiddlers to hold the text used for the MainMenu, the SiteTitle and the SiteSubtitle. DefaultTiddlers is used to store the titles of the tiddlers that are shown at startup. SaveChanges is automatically displayed if there's a problem with saving. StyleSheet is a user defined stylesheet that exists as a Tiddler. \n\nAll except StyleSheet can be edited with the changes taking effect immediately.
When it loads, TiddlyWiki looks for the names of tiddlers to open as a space-separated list after the # in the URL. If there are no tiddlers in the URL it instead loads the tiddlers named in DefaultTiddlers, one of the SpecialTiddlers.
/***\n!Calendar CSS\n***/\n/*{{{*/\n.calendar{\n border-bottom: 1px solid #550000;\n}\n\n.viewer .calendar{\n width: 220px;\n}\n\n#mainMenu .calendar{\n font-size: 8px;\n cursor: pointer;\n width: 100%;\n border: 0;\n border-collapse: collapse;\n}\n\n#mainMenu .calendar .button{\n border: 0;\n}\n\n#mainMenu .calendar td{\n font-size: 8pt;\n padding: 0;\n background: #fff;\n border: 0;\n}\n\n#mainMenu .calendar a{\n margin: 0;\n color: #000;\n background: transparent;\n}\n\n#mainMenu .calendar a:hover{\n color: #000;\n background: transparent;\n}\n\n#mainMenu .calendarMonthname,\n#mainMenu .calendar .calendarMonthTitle td a{\n color: #fff;\n}\n\n#mainMenu .calendarDaysOfWeek td{\n background: #500;\n color: #fff;\n}\n/*}}}*/\n/***\n!GTD Style\n\n!Generic rules /%==================================================================== %/\n***/\n/*{{{*/\nbody {\n background: #464646 url('http://shared.snapgrid.com/images/tiddlywiki/bodygradient.png') repeat-x top fixed;\n color: #000;\n font: .82em/1.25em "Bitstream Vera Sans", Verdana, Helvetica, Arial, sans-serif;\n/*"Lucida Sans Unicode", "Lucida Grande","Trebuchet MS", */\n}\n/*}}}*/\n/***\n!Header rules /%====================================================================== %/\n***/\n/*{{{*/\n#contentWrapper\n{\n margin: 0 auto;\nwidth: 59em;\nposition: relative;\n}\n\n#header\n{\n color: #fff;\n padding: 1.5em 1em .6em 0;\n}\n\n#siteTitle {\n\n font-size: 2.3em;\n margin: 0;\n}\n\n#siteSubtitle {\n font-size: 1em;\n padding-left: .8em;;\n}\n\n#titleLine{\n background: transparent;\n padding: 0;\n}\n\n#titleLine a {\n color: #cf6;\n}\n/*}}}*/\n/***\n!Sidebar rules /%====================================================================== %/\n***/\n/*{{{*/\n#sidebar{\n left: 0;\nwidth: 18em;\n margin: .9em .9em 0 0;\n color: #000;\n background: transparent;\n}\n/*}}}*/\n/***\n!Main menu rules /%=================================================================== %/\n***/\n/*{{{*/\n#mainMenu{\n position: static;\n width: auto;\n\n background: #600;\n border-right: 3px solid #500;\npadding: 0;\n text-align: left;\n font-size: 1em;\n}\n\n#mainMenu h1{\n padding: 0;\n margin: 0;\n font-size: 1em;\n font-weight: normal;\n}\n\n#mainMenu ul{\n padding: 0;\n margin: 0;\n list-style: none;\n}\n\n#mainMenu h1 a,\n#mainMenu li a,\n#mainMenu li a.button{\n display: block;\n padding: 0 5px 0 10px;\nborder: 0;\n border-bottom: 1px solid #500;\n border-top: 1px solid #900;\nmargin: 0;\n}\n\n#mainMenu a,\n#mainMenu a.button{\n height: 22px;\nheight: 1.83em;\n line-height: 22px;\n color: #fff;\n background: #700;\nmargin-left: 1em;\n}\n\n#mainMenu a:hover,\n#mainMenu a.button:hover {\n background: #b00;\n color: #fff;\n}\n/*}}}*/\n/***\n!Sidebar options rules /%============================================================ %/\n***/\n/*{{{*/\n#sidebarOptions {\n background: #eeb;\n border-right: 3px solid #bb8;\n color: #B4C675;\n padding: .5em 0;\n}\n\n#sidebarOptions a {\n color: #700;\n margin: .2em .8em;\n padding: 0;\n border: 0;\n}\n\n#sidebarOptions a:hover, #sidebarOptions a:active {\n color: #fff;\n background: #700;\n border: 0;\n}\n\n#sidebarOptions input{\n margin: 2px 10px;\n border: 1px inset #333;\npadding: 0;\n}\n\n#sidebarOptions .sliderPanel {\n background: #fff;\n color: #000;\n padding: 5px 10px;\n font-size: .9em;\n}\n\n#sidebarOptions .sliderPanel a{\n font-weight: normal;\n margin: 0;\n}\n\n#sidebarOptions .sliderPanel a:link,#sidebarOptions .sliderPanel a:visited {\n color: #700;\n}\n\n#sidebarOptions .sliderPanel a:hover,#sidebarOptions .sliderPanel a:active {\n color: #fff;\n background: #700;\n}\n/*}}}*/\n/***\n!Sidebar tabs rules /%===================================================================== %/\n***/\n/*{{{*/\n#sidebarTabs {\n background: transparent;\n border-right: 3px solid #740;\n border-bottom: 3px solid #520;\n border: 0;\n padding: 0;\n}\n\n#contentWrapper #sidebarTabs a,\n#contentWrapper #displayArea .tabContents a{\n color: #fff;\n}\n\n#contentWrapper #sidebarTabs a:hover,\n#contentWrapper #displayArea .tabContents a:hover {\n background: #000;\n color: #fff;\n}\n\n#contentWrapper #sidebarTabs a:active,\n#contentWrapper #displayArea .tabContents a:active{\n color: #000;\n}\n\n\n\n#contentWrapper .tabSelected {\n background: #960;\n}\n\n#contentWrapper .tabUnselected{\n background: #660;\n}\n\n#contentWrapper #sidebar .tabset{\n background: #eeb;\n border-right: 3px solid #bb8;\n padding: 0 0 0 .75em;\n}\n\n#contentWrapper .tabContents{\nfont-size: .95em;\nbackground: #960;\nborder:0;\n border-right: 3px solid #740;\n border-bottom: 3px solid #520;\n padding: .75em;\n}\n\n#contentWrapper .tabContents{\n width: auto;\n}\n\n#contentWrapper #sidebarTabs .tabContents .tabset,\n#contentWrapper .tabContents .tabset{\n border: 0;\n padding: 0;\n background: transparent;\n}\n\n#contentWrapper .tabContents .tabSelected,\n#contentWrapper .tabContents .tabContents {\n background: #700;\n border: 0;\n}\n\n#contentWrapper .tabContents .tabUnselected {\n background: #440;\n}\n\n#contentWrapper .tabset a {\n color: #fff;\n padding: .2em .7em;\n margin: 0 .17em 0 0;\n height: 2em;\nposition: static;\n}\n\n#contentWrapper .tabset a:hover {\n background: #000;\n color: #fff;\n}\n\n#contentWrapper .tabset a:active {\n color: #000;\n}\n\n#contentWrapper .tabContents ul{\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n#contentWrapper .tabContents .tabContents ul{\n color: #eeb;\n}\n\n.tabContents ul a,\n.tabContents ul .button{\n color: #fff;\n display: block;\n padding: .1em 0 .1em .7em;\n background: transparent;\n border: 0;\n}\n\n.tabContents ul a:hover {\n color: #fff;\n background: #000;\n}\n/*}}}*/\n/***\n!License panel rules /%==================================================================== %/\n***/\n/*{{{*/\n#licensePanel {\n padding: 0px 1em;\n font-size: .9em;\n}\n\n#licensePanel a {\n color: #960;\n display: block;\n margin-top: .9em;\n}\n\n#licensePanel a:hover {\n color: #fff;\n background: transparent;\n}\n/*}}}*/\n/***\n!Popup rules /%================================================================= %/\n***/\n/*{{{*/\n.popup {\n font-size: .8em;\n padding: 0em;\n background: #333;\n border: 1px solid #000;\n}\n\n.popup hr {\n margin: 1px 0 0 0;\n visibility: hidden;\n}\n\n.popup li.disabled {\n color: #666;\n}\n\n.popup li a,\n.popup li a:visited{\n color: #000;\n border: .1em outset #cf6;\n background: #cf6;\n}\n\n.popup li a:hover {\nborder: .1em outset #cf6;\n background: #ef9;\n color: #000;\n}\n/*}}}*/\n/***\n!Message area rules /%================================================================= %/\n***/\n/*{{{*/\n#messageArea{\n font-size: .9em;\n padding: .4em;\n background: #FFE72F;\n border-right: .25em solid #da1;\n border-bottom: .25em solid #a80;\n\nposition: fixed;\n top: 10px;\n right: 10px;\n color: #000;\n}\n\n#contentWrapper #messageArea a{\n color: #00e;\n text-decoration: none;\n}\n\n#contentWrapper #messageArea a:hover{\n color: #00e;\n text-decoration: underline;\n background: transparent;\n}\n\n#contentWrapper #messageArea .messageToolbar a.button{\n border: 1px solid #da1;\n}\n\n#contentWrapper #messageArea .messageToolbar a.button:hover{\n color: #00e;\n text-decoration: none;\n border: 1px solid #000;\n background: #fff;\n}\n\n\n\n/*}}}*/\n/***\n!Tiddler display rules /%================================================================== %/\n***/\n/*{{{*/\n#displayArea {\n width: 39.75em;\n margin: 0 0 0 17em;\n}\n\n.tiddler {\n margin: 0 0 .9em 0;\n padding: 0 1em;\n border-right: .25em solid #aaa;\n border-bottom: .25em solid #555;\n background: #fff;\n}\n\n.title {\n font-size: 1.5em;\n font-weight: bold;\n color: #900;\n}\n\n.toolbar {\n font-size: .8em;\n padding: .5em 0;\n}\n\n.toolbar .button{\n padding: .1em .3em;\n color: #000;\n\n border: .1em outset #cf6;\n background: #cf6;\nmargin: .1em;\n}\n\n.toolbar .button:hover {\n background: #ef9;\n color: #000;\n}\n\n.toolbar .button:active {\n background: #ff0;\n}\n\n/*}}}*/\n/***\n!Viewer rules /% ------------------------------------------------------------------------------------------ %/\n***/\n/*{{{*/\n.viewer {\n line-height: 1.4em;\n font-size: 1em;\n}\n\n.viewer a:link, .viewer a:visited {\n color: #15b;\n}\n\n.viewer a:hover {\n color: #fff;\n background: #000;\n}\n\n.viewer .button{\n background: transparent;\n border-top: 1px solid #eee;\n border-left: 1px solid #eee;\n border-bottom: 1px solid #000;\n border-right: 1px solid #000;\n}\n\n.viewer .button:hover{\n background: #eee;\n color: #000;\n}\n\n.viewer .button:active{\n background: #ccc;\n border-bottom: 1px solid #eee;\n border-right: 1px solid #eee;\n border-top: 1px solid #111;\n border-left: 1px solid #111;\n}\n\n\n.viewer blockquote {\n border-left: 3px solid #777;\n margin: .3em;\n padding: .3em;\n}\n\n.viewer pre{\n background: #fefefe;\n border: 1px solid #f1f1f1;\n}\n\n.viewer pre, .viewer code{\n color: #000;\n}\n\n.viewer ul {\n padding-left: 30px;\n}\n\n.viewer ol {\n padding-left: 30px;\n}\nul{\nlist-style-type: asquare;\n}\nol{ \n list-style-type: decimal;\n}\n\nol ol{ \n list-style-type: lower-alpha;\n}\n\nol ol ol{ \n list-style-type: lower-roman;\n}\n\n.viewer ul, .viewer ol, .viewer p {\n margin: .0;\n}\n\n.viewer li {\n margin: .2em 0;\n}\n\nh1,h2,h3,h4,h5,h6 {\n color: #000;\n font-weight: bold;\n background: #eee;\n padding: 2px 10px;\n margin: 5px 0;\n}\n\n.viewer h1 {font-size: 1.3em;}\n.viewer h2 {font-size: 1.2em;}\n.viewer h3 {font-size: 1.1em;}\n.viewer h4 {font-size: 1em;}\n.viewer h5 { font-size: .9em;}\n.viewer h6 { font-size: .8em;}\n\n.viewer table {\n border: 2px solid #303030;\n font-size: 11px;\n margin: 10px 0;\n}\n\n.viewer th, .viewer thead td{\n color: #000;\n background: #eee;\n border: 1px solid #aaa;\n padding: 0 3px;\n}\n\n.viewer td {\n border: 1px solid #aaa;\n padding: 0 3px;\n}\n\n.viewer caption {\n padding: 3px;\n}\n\n.viewer hr {\n border: none;\n border-top: dotted 1px #777;\n height: 1px;\n color: #777;\n margin: 7px 0;\n}\n\n.viewer\n{\n margin: .5em 0 0 0;\n padding: .5em 0;\n border-top: 1px solid #ccc;\n}\n\n.highlight {\n color: #000;\n background: #ffe72f;\n}\n/*}}}*/\n/***\n!Editor rules /% ----------------------------------------------------------------------------------------- %/\n***/\n/*{{{*/\n.editor {\n font-size: .8em;\n color: #402C74;\n padding: .3em 0;\n}\n\n.editor input, .editor textarea {\n font: 1.1em/130% "Andale Mono", "Monaco", "Lucida Console", "Courier New", monospace;\n margin: 0;\n border: 1px inset #333;\n padding: 2px 0;\n}\n\n.editor textarea {\n height: 42em;\n width: 100%;\n}\n\ninput:focus, textarea:focus\n{\n background: #ffe;\n border: 1px solid #000;\n}\n.footer\n{\n padding: .5em 0;\n margin: .5em 0;\n border-top: 1px solid #ddd;\n color: #555;\n text-align: center; \n}\n/*}}}*/\n/***\n!IE Display hacks /% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%/\n***/\n/*{{{*/\nbody{\n _text-align: center;\n}\n\n#contentWrapper\n{\n/* _width: 770px; CSS UNDERSCORE HACK FOR PROPER WIN/IE DISPLAY */\n _text-align: left; /* CSS UNDERSCORE HACK FOR PROPER WIN/IE DISPLAY */ \n}\n\n#messageArea{\n _position: absolute;\n}\n/*}}}*/\n/***\n!DatePlugin Calendar Hacks\n***/\n/*{{{*/\n.popup {\n font-size: .8em;\n padding: 0em;\n background: #f3f3f3;\n border: 1px solid #000;\n}\n/*}}}*/
/*{{{*/\n\n@media print {\n#mainMenu, #sidebar, #messageArea {display: none !important;}\n#displayArea {margin: 1em 1em 0em 1em;}\n\n\n/* LAYOUT ELEMENTS ========================================================== */\n*\n{\n margin: 0;\n padding: 0;\n}\n\nbody {\n background: #fff;\n color: #000;\n font-size: 6.2pt;\n font-family: "Lucida Grande", "Bitstream Vera Sans", Helvetica, Verdana, Arial, sans-serif;\n}\n\nimg {\n max-width: 2.2in;\n max-height: 4.3in;\n}\n\n#header, #side_container, #storeArea, #copyright, #floater, #messageArea, .save_accesskey, .site_description, #saveTest, .toolbar, .footer\n{\n display: none;\n}\n\n#tiddlerDisplay, #displayArea\n{\n display: inline;\n}\n\n.tiddler {\n margin: 0 0 2em 0;\n border-top: 1px solid #000;\n page-break-before: always;\n}\n\n.tiddler:first-child {\n page-break-before: avoid;\n}\n\n.title {\n font-size: 1.6em;\n font-weight: bold;\n margin-bottom: .3em;\n padding: .2em 0;\n border-bottom: 1px dotted #000;\n}\n\np, blockquote, ul, li, ol, dt, dd, dl, table\n{\n margin: 0 0 .3em 0;\n}\n\nh1, h2, h3, h4, h5, h6\n{\n margin: .2em 0;\n} \n\nh1\n{\n font-size: 1.5em;\n}\n\nh2\n{\n font-size: 1.3em;\n}\n\nh3\n{\n font-size: 1.25em;\n}\n\nh4\n{\n font-size: 1.15em;\n}\n\nh5\n{\n font-size: 1.1em;\n}\n\nblockquote\n{\n margin: .6em;\n padding-left: .6em;\n border-left: 1px solid #ccc;\n}\n\nul\n{\n list-style-type: circle;\n}\n\nli\n{\n margin: .1em 0 .1em 2em;\n line-height: 1.4em; \n}\n\ntable\n{\n border-collapse: collapse;\n font-size: 1em;\n}\n\ntd, th\n{\n border: 1px solid #999;\n padding: .2em;\n}\n\nhr {\n border: none;\n border-top: dotted 1px #777;\n height: 1px;\n color: #777;\n margin: .6em 0;\n}\n}\n/*}}}*/
!Supported\n* Safari (requires [[plugin by Jonathan Paisley|http://www.dcs.gla.ac.uk/~jp/tiddlywiki/]])\n* Firefox\n* Win IE 6 (caveat: see KnownBugs)\n* Camino (I haven't verified this)\n\n!Unsupported\n* ==Safari: Saving doesn't work in Safari, which renders TiddlyWiki useless.== FIXED! Thanks to [[Jonathan Paisley|http://www.dcs.gla.ac.uk/~jp/]].\n* Opera: I've gotten mixed reports.
/***\n''Table of Contents Plugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#TableOfContentsPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nWhen there are many tiddlers in a document, the standard 'tabbed list of tiddlers' in the right-hand sidebar can become very long, occupying a lot of page space and requiring a lot scrolling in order to locate and select a tiddler.\n\nThe TableOfContentsPlugin addresses this problem by replacing the standard tabbed list display with a single listbox/droplist control that uses a very small amount of page space, regardless of the number of tiddlers in the document.\n\n!!!!!Usage\n<<<\nTo view a tiddler, simply select (or double-click) its title from the listbox and it will automatically be displayed on the page. The listbox also includes special 'command' items that determine the order and type of tiddlers that are shown in the list:\n\n''[by title]'' displays all tiddlers in the document.\n''[by date/author/tags]'' displays indented sections, sorted accordingly, with headings (indicated by a '+') that can be expanded, one at a time, to view the list of tiddlers in that section.\n''[missing]'' displays tiddlers that have been referenced within the document but do not yet exist.\n''[orphans]'' displays tiddlers that do exist in the document but have not been referenced by a link from anywhere else within the document.\n''[system]'' displays special tiddlers that are used by TiddlyWiki to configure built-in features and add-on macros/extensions. The list includes all tiddlers tagged with <<tag systemTiddlers>> ("templates") or <<tag systemConfig>> (plug-in extensions), plus any 'shadow tiddlers' (built-in default systemTiddlers) that have not been over-ridden by custom tiddler definitions.\n\nThe current list ''display setting is indicated by an arrow (">")'' symbol to the left of command item. Selecting a command item causes the listbox to be reloaded with the appropriate contents and sort order.\n\nWhen you are viewing a list of tiddlers by date/author/tags, ''shift-clicking'' on a section heading or command item causes the listbox display to ''toggle between "show-one-section-at-a-time" and "expand-all-sections"'' display options, allowing you to quickly see all tiddler titles at once without having to view individual indented sections one at a time.\n\nThe ''size of the listbox can be adjusted'' so you can view more (or less) tiddler titles at one time. Select ''[-]'' to reduce the size by one line, ''[+]'' to increase the size by one line, or ''[=]'' to autosize the list to fit the current contents (toggles on/off). //Note: If the listbox is reduced to a single line, it displayed as a droplist instead of a fixed-sized listbox.// You can ''show/hide the entire listbox'' by selecting the "contents" label that appears above the listbox.\n<<<\n!!!!!Control Panel\n<<<\nBy default, tiddlers tagged with <<tag excludeLists>>, are omitted from the TableOfContents so that 'system' tiddlers (e.g. MainMenu, SiteTitle, StyleSheet, etc.) can be hidden, reducing "information overload" and making it easier to select relevant tiddlers when reading your document. However, when //editing// your document, including these hidden tiddlers in the list can be more helpful, so that changes to the menus, titles, styles, etc. can be more quickly accomplished.\n----\n''To include hidden tiddlers in the TableOfContents display, select the following option:''\n<<option chkTOCIncludeHidden>> include hidden tiddlers in TableOfContents(ignores <<tag excludeLists>> tag)\n^^note: this setting is ignored when ''<<option chkHttpReadOnly>> HideEditingFeatures when viewed over HTTP'' is enabled^^\n<<<\n!!!!!Parameters\n<<<\nThe macro accepts optional parameters to control various features and functions:\n* ''label:text''\nReplace the default text ("contents") that appears above the TableOfContents listbox. //Note: to include spaces in the label text, you must enclose the entire parameter in quotes// (e.g., {{{"label:my list of tiddlers"}}})\n* ''sort:fieldtype''\nSets the initial display order for items in the listbox. 'fieldtype' is one of the following pre-defined keywords: ''title'', ''modified'' //(date)//, ''modifier'' //(author)//, ''tags'', ''missing'', ''orphans'', or ''system''\n* ''date:format''\nControls the formatting of dates in TableOfContents display. 'format' is a text-substitution template containing one or more of the following special notations.\n** DDD - day of week in full (eg, "Monday")\n** DD - day of month, 0DD - adds leading zero\n** MMM - month in full (eg, "July")\n** MM - month number, 0MM - adds leading zero\n** YYYY - full year, YY - two digit year\n** hh - hours\n** mm - minutes\n** ss - seconds\n//Note: to include spaces in the formatting template, you must enclose the entire parameter in quotes// (e.g., {{{"date:DDD, DD/MM/YY"}}})\n* ''size:nnn''\nSets the initial number of lines to display in the listbox. If this parameter is omitted or "size:1" is specified, a single-line droplist is created. When a size > 1 is provided, a standard, fixed-size scrollable listbox is created. You can use "size:0" or "size:auto" to display a varible-height listbox that automatically adjusts to fit the current list contents without scrolling.\n* ''width:nnn[cm|px|em|%]''\nSets the width of the listbox control. Overrides the built-in CSS width declaration (=100%). Use standard CSS width units (cm=centimeters, px=pixels, em=M-space, %=proportional to containing area). You can also use a ".TOCList" custom CSS class definition to override the built-in CSS declarations for the listbox.\n* ''hidelist''\nHides the listbox when the TableOfContents is first displayed. Initially, only the listbox label and size controls will appear. Clicking on the listbox label text will alternately show/hide the listbox display. //Note: this setting does not affect the content of the listbox, only whether or not it is initially visible.//\n* ''prompt''\nSets the non-selectable prompt text that is displayed as the first line of the listbox //(note: this feature is not supported by the listbox control on all browsers)//. Let's you include a short text message (such as "select a tiddler"), even when displaying a compact single-line droplist.\n* ''padding:nnn[cm|px|em|%]''\nOverrides default listbox control padding. Sets the CSS padding style.\n* ''margin:nnn[cm|px|em|%]''\nOverrides default listbox control spacing. Sets the CSS margin style.\n* ''inline''\nNormally, the TableOfContents plugin is contained inside a {{{<div>}}} element. This setting causes the plugin to use a {{{<span>}}} instead, allowing for more flexible 'inline' placement when embedded within other content.\n<<<\n!!!!!Examples\n<<<\n<<tableOfContents "label:all tiddlers" sort:title width:40% size:1>>\n<<tableOfContents "label:by date" sort:modified size:1 width:40%>>\n<<tableOfContents "label:tagged tiddlers" sort:tags size:1 width:40%>>\n<<tableOfContents "label:system tiddlers" sort:system size:1 width:40%>>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''TableOfContentsPlugin'' (tagged with <<tag systemConfig>>)\n^^documentation and javascript for TableOfContents handling^^\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add {{{<<tableOfContents>>}}} macro^^\n\n<<<\n!!!!!Revision History\n<<<\n''2006.02.14 [2.2.6]''\nFF1501 fix: add 'var r' and 'var k' to unintended global variable declarations in refreshTOCList() and getTOCListFromButton(). Thanks for report from AndreasHoefler.\n''2006.02.04 [2.2.5]''\nadd 'var' to unintended global variable declarations to avoid FireFox 1.5.0.1 crash bug when assigning to globals\n''2005.12.21 [2.2.2]''\nin onClickTOCList() and onDblClickTOCList(), prevent mouse events from 'bubbling' up to other handlers\n''2005.10.30 [2.2.1]''\nin refreshTOCList(), fixed calculation of "showHidden" to check for 'readOnly' (i.e., "via HTTP") flag\nbased on a report from LyallPearce\n''2005.10.30 [2.2.0]''\nhide tiddlers tagged with 'excludeLists' (with option to override, i.e., "include hidden tiddlers")\n''2005.10.09 [2.1.0]''\ncombined documentation and code in a single tiddler\nadded click toggle for expand-all vs. show-one-branch\n''2005.08.07 [2.0.0]''\nmajor re-write to not use static ID values for listbox controls, so that multiple macro instances can exist without corrupting each other or the DOM. Moved HTML and CSS definitions into plugin code instead of using separate tiddlers. Added macro parameters for label, sort, date, size, width, hidelist and showtabs\n''2005.08.03 [1.0.3]''\nadded "showtabs" optional parameter\n''2005.07.27 [1.0.2]''\ncore update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet(). Added show/hide toggle (click on 'contents' link)\n''2005.07.23 [1.0.1]''\nadded parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]''\nInitial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.tableOfContents = {major: 2, minor: 2, revision: 6, date: new Date(2006,2,14)};\n//}}}\n\n// // 1.2.x compatibility\n//{{{\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n//{{{\n// define defaults for cookie-based option values\nif (config.options.txtTOCSortBy==undefined) config.options.txtTOCSortBy="modified";\nif (config.options.txtTOCListSize==undefined) config.options.txtTOCListSize=12;\nif (config.options.chkTOCShow==undefined) config.options.chkTOCShow=true;\nif (config.options.chkTOCIncludeHidden==undefined) config.options.chkTOCIncludeHidden=false;\n\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkTOCIncludeHidden>> include hidden tiddlers in TableOfContents";\n\n// define macro "tableOfContents" to render controls\nconfig.macros.tableOfContents = { label: "contents" };\nconfig.macros.tableOfContents.cmdMax=7;\n\nconfig.macros.tableOfContents.css = '\s\n.TOC { padding:0.5em 1em 0.5em 1em; }\s\n.TOC a { padding:0em 0.25em 0em 0.25em; color:inherit; }\s\n.TOCList { width: 100%; font-size:8pt; margin:0em; }\s\n';\n\nconfig.macros.tableOfContents.html = '\s\n<div style="text-align:right">\s\n <span style="float:left">\s\n <a href="JavaScript:;" id="TOCMenu" style="padding: 0em;"\s\n onclick="onClickTOCMenu(this)" title="show/hide table of contents">%label%</a>\s\n </span>\s\n <a href="JavaScript:;" id="TOCSmaller" style="display:inline"\s\n onclick="resizeTOC(this)" title="reduce list size">&#150;</a>\s\n <a href="JavaScript:;" id="TOCLarger"style="display:inline"\s\n onclick="resizeTOC(this)" title="increase list size">+</a>\s\n <a href="JavaScript:;" id="TOCMaximize"style="display:inline"\s\n onclick="resizeTOC(this)" title="maximize/restore list size">=</a>\s\n</div>\s\n';\n\nconfig.macros.tableOfContents.handler = function(place,macroName,params) { \n var parsedParams = new Array();\n parsedParams['label']=this.label;\n parsedParams['inline']=false;\n while (params.length>0) {\n if (params[0]=="label:none")\n parsedParams['label']="";\n else if (params[0].substr(0,6)=="label:")\n parsedParams['label']=params[0].substr(6);\n if (params[0].substr(0,7)=="prompt:")\n parsedParams['prompt']=params[0].substr(7);\n if (params[0].substr(0,8)=="padding:")\n parsedParams['padding']=params[0].substr(8);\n if (params[0].substr(0,7)=="margin:")\n parsedParams['margin']=params[0].substr(7);\n if (params[0].substr(0,5)=="sort:")\n parsedParams['sortby']=params[0].substr(5);\n if (params[0].substr(0,5)=="date:")\n parsedParams['date']=params[0].substr(5);\n if ((params[0]=="size:auto")||(params[0]=="size:0"))\n parsedParams['autosize']=true;\n else if (params[0] && (params[0].substr(0,5)=="size:"))\n parsedParams['requestedSize']=params[0].substr(5);\n if (params[0].substr(0,6)=="width:")\n parsedParams['width']=params[0].substr(6);\n if (params[0]=="hidelist")\n parsedParams['hidelist']=true;\n if (params[0]=="inline")\n parsedParams['inline']=true;\n params.shift(); \n }\n setStylesheet(config.macros.tableOfContents.css,"tableOfContents");\n var newTOC=createTiddlyElement(place,parsedParams['inline']?"span":"div",null,"TOC",null)\n if (parsedParams['margin']) { newTOC.style.margin=parsedParams['margin']; }\n if (parsedParams['padding']) { newTOC.style.padding=parsedParams['padding']; }\n if (parsedParams['label']!="") newTOC.innerHTML=config.macros.tableOfContents.html.replace(/%label%/,parsedParams['label']);\n var newTOCList=createTOCList(newTOC,parsedParams)\n refreshTOCList(newTOCList);\n store.addNotification(null,reloadTOCLists); // reload listbox after every tiddler change\n}\n\n// IE needs explicit global scoping for functions/vars called from browser events\nwindow.onChangeTOCList=onChangeTOCList;\nwindow.onClickTOCList=onClickTOCList;\nwindow.onDblClickTOCList=onDblClickTOCList;\nwindow.reloadTOCLists=reloadTOCLists;\nwindow.refreshTOCList=refreshTOCList;\nwindow.onClickTOCMenu=onClickTOCMenu;\nwindow.resizeTOC=resizeTOC;\n \nfunction createTOCList(place,params)\n{\n var theList = createTiddlyElement(place,"select",null,"TOCList",params['prompt'])\n theList.onchange=onChangeTOCList;\n theList.onclick=onClickTOCList;\n theList.ondblclick=onDblClickTOCList;\n theList.style.display=config.options.chkTOCShow ? "block" : "none" ;\n theList.sortBy=config.options.txtTOCSortBy;\n theList.dateFormat="DD MMM YYYY";\n theList.requestedSize=config.options.txtTOCListSize;\n theList.expandall=false;\n if (params['sortby'])\n { theList.sortBy=params['sortby']; theList.noSortCookie=true; }\n if (params['date'])\n { theList.dateFormat=params['date']; }\n if (params['autosize'])\n { theList.autosize=true; theList.noSizeCookie=true; }\n if (params['requestedSize'])\n { theList.requestedSize=params['requestedSize']; theList.noSizeCookie=true; }\n if (params['width'])\n { theList.style.width=params['width']; }\n if (params['hidelist'])\n { theList.style.display ="none" ; theList.noShowCookie=true; }\n if (params['expandall'])\n { theList.expandall=true; }\n return theList;\n}\n\nfunction onChangeTOCList()\n{\n var thisTiddler=this.options[this.selectedIndex].value;\n if ((this.size==1)&&(thisTiddler!='')) story.displayTiddler(null,thisTiddler,1);\n refreshTOCList(this);\n return false;\n}\n\nfunction onClickTOCList(e)\n{\n\n if (!e) var e = window.event;\n if (this.size==1)\n return; // don't toggle display for droplist\n if (e.shiftKey)\n { this.expandall=!this.expandall; refreshTOCList(this);}\n e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation();\n return true;\n}\n\nfunction onDblClickTOCList(e)\n{\n if (!e) var e = window.event;\n var thisTiddler=this.options[this.selectedIndex].value;\n if (thisTiddler!='') story.displayTiddler(null,thisTiddler,1);\n e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation();\n return false;\n}\n\nfunction reloadTOCLists()\n{\n var all=document.all? document.all : document.getElementsByTagName("*");\n for (var i=0; i<all.length; i++)\n if (all[i].className=="TOCList")\n { all[i].selectedIndex=-1; refreshTOCList(all[i]); }\n}\n\nfunction refreshTOCList(theList)\n{\n // DEBUG var starttime=new Date();\n var selectedIndex = theList.selectedIndex;\n if (selectedIndex==-1) selectedIndex=0;\n var sortBy = theList.sortBy;\n var showHidden = config.options.chkTOCIncludeHidden\n && !(config.options.chkHttpReadOnly && readOnly);\n\n if (selectedIndex==0) sortBy=theList.sortBy; // "nnn tiddlers" heading\n if (selectedIndex==1) sortBy='title';\n if (selectedIndex==2) sortBy='modified';\n if (selectedIndex==3) sortBy='modifier';\n if (selectedIndex==4) sortBy='tags';\n if (selectedIndex==5) sortBy='missing';\n if (selectedIndex==6) sortBy='orphans';\n if (selectedIndex==7) sortBy='system';\n if (selectedIndex>config.macros.tableOfContents.cmdMax)\n {\n if (theList.options[theList.selectedIndex].value=='')\n expandTOC(theList);\n return;\n }\n theList.sortBy = sortBy;\n if (!theList.noSortCookie)\n { config.options.txtTOCSortBy=sortBy; saveOptionCookie("txtTOCSortBy"); }\n\n // get the list of tiddlers and filter out 'hidden' tiddlers (i.e., tagged with "excludeLists")\n var tiddlers = [];\n switch (sortBy) {\n case "missing":\n tiddlers = store.getMissingLinks();\n break;\n case "tags":\n tiddlers = store.getTags();\n break;\n case "orphans":\n var titles = store.getOrphans();\n for (var t = 0; t < titles.length; t++)\n if (showHidden || store.getTiddler(titles[t]).tags.find("excludeLists")==null)\n tiddlers.push(titles[t]);\n break;\n case "system":\n var temp = store.getTaggedTiddlers("systemTiddlers");\n for (var t = 0; t < temp.length; t++)\n if (showHidden || temp[t].tags.find("excludeLists")==null)\n tiddlers.pushUnique(temp[t].title,true);\n var temp = store.getTaggedTiddlers("systemConfig");\n for (var t = 0; t < temp.length; t++)\n if (showHidden || temp[t].tags.find("excludeLists")==null)\n tiddlers.pushUnique(temp[t].title,true);\n for (var t in config.shadowTiddlers) tiddlers.pushUnique(t,true);\n tiddlers.sort();\n break;\n default:\n var temp = store.getTiddlers(sortBy);\n for (var t = 0; t < temp.length; t++)\n if (showHidden || temp[t].tags.find("excludeLists")==null)\n tiddlers.push(temp[t]);\n }\n\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n theList.saved=null;\n\n // add heading and control items to list\n var i=0;\n var theHeading=tiddlers.length+' tiddlers:';\n if (sortBy=='missing') theHeading=tiddlers.length+' missing tiddlers:';\n if (sortBy=='orphans') theHeading=tiddlers.length+' orphaned tiddlers:';\n if (sortBy=='tags') theHeading=tiddlers.length+' tags:';\n if (sortBy=='system') theHeading=tiddlers.length+' system tiddlers:';\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n var sel=">";\n theList.options[i++]=new Option(theHeading,'',false,false);\n theList.options[i++]=new Option(((sortBy=="title")?sel:indent)+' [by title]','',false,false);\n theList.options[i++]=new Option(((sortBy=="modified")?sel:indent)+' [by date]','',false,false);\n theList.options[i++]=new Option(((sortBy=="modifier")?sel:indent)+' [by author]','',false,false);\n theList.options[i++]=new Option(((sortBy=="tags")?sel:indent)+' [by tags]','',false,false);\n theList.options[i++]=new Option(((sortBy=="missing")?sel:indent)+' [missing]','',false,false);\n theList.options[i++]=new Option(((sortBy=="orphans")?sel:indent)+' [orphans]','',false,false);\n theList.options[i++]=new Option(((sortBy=="system")?sel:indent)+' [system]','',false,false);\n // output the tiddler list\n switch(sortBy)\n {\n case "title":\n for (var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);\n break;\n case "modified":\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });\n // continue with same logic as for 'modifier'...\n case "modifier":\n var lastSection = "";\n for (var t = 0; t < tiddlers.length; t++)\n {\n var tiddler = tiddlers[t];\n var theSection = "";\n if (sortBy=="modified") theSection = tiddler.modified.formatString(theList.dateFormat);\n if (sortBy=="modifier") theSection = tiddler.modifier;\n if (theSection != lastSection)\n {\n theList.options[i++] = new Option('+ '+theSection,"",false,false);\n lastSection = theSection;\n }\n theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);\n }\n expandTOC(theList);\n break;\n case "tags":\n // tagged tiddlers, by tag\n var tagcount=0;\n var lastTag = null;\n for (var t = 0; t < tiddlers.length; t++) // actually a list of tags, not tiddlers...\n {\n var theTag = tiddlers[t][0];\n var tagged = new Array();\n var temp = store.getTaggedTiddlers(theTag);\n for(var r=0; r<temp.length; r++)\n if (showHidden || temp[r].tags.find("excludeLists")==null)\n tagged.push(temp[r]);\n if (tagged.length)\n {\n tagcount++;\n theList.options[i++]= new\n Option('+ '+theTag+" ("+tagged.length+")","",false,false);\n for(var r=0; r<tagged.length; r++)\n theList.options[i++] = new\n Option(indent+indent+tagged[r].title,tagged[r].title,false,false);\n }\n }\n // count untagged tiddlers\n var temp = store.getTiddlers("title");\n var c=0; for (var r=0; r<temp.length;r++) if (!temp[r].tags.length) c++;\n // create 'pseudo-tag' listing untagged tiddlers (if any)\n if (c>0)\n {\n theList.options[i++] = new Option("+ untagged ("+c+")","",false,false);\n for (var r=0; r<temp.length;r++) if (!temp[r].tags.length)\n theList.options[i++] = new\n Option(indent+indent+temp[r].title,temp[r].title,false,false);\n }\n theList.options[0].text=tagcount+' tags:';\n expandTOC(theList);\n break;\n case "missing":\n case "orphans":\n case "system":\n for (var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t],tiddlers[t],false,false);\n break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n theList.size = (theList.autosize)?theList.options.length:theList.requestedSize;\n // DEBUG var endtime=new Date();\n // DEBUG alert("refreshTOC() elapsed time: "+(endtime-starttime)+" msec");\n}\n\n// show/hide branch of TOCList based on current selection\nfunction expandTOC(theList)\n{\n var selectedIndex = theList.selectedIndex;\n if (selectedIndex==-1) selectedIndex=0;\n var sortBy = theList.sortBy;\n\n // don't collapse/expand list for alpha-sorted "flatlist" TOC contents\n if ((sortBy=="title")||(sortBy=="missing")||(sortBy=="orphans")||(sortBy=="system"))\n return;\n // or list control items\n if ((selectedIndex>0)&&(selectedIndex<=config.macros.tableOfContents.cmdMax))\n return;\n\n var theText = theList.options[selectedIndex].text;\n var theValue = theList.options[selectedIndex].value;\n // save fully expanded list contents (if not already saved)\n if (!theList.saved)\n {\n theList.saved = new Array();\n for (var i=0; i < theList.length; i++)\n {\n opt = theList.options[i];\n theList.saved[i] = new Option(opt.text, opt.value, opt.defaultSelected, opt.selected);\n }\n }\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n\n // put back all items \n if (theList.expandall)\n {\n var i=0;\n for (var t=0; t<theList.saved.length; t++)\n {\n var opt=theList.saved[t];\n theList.options[i++] = new Option(opt.text,opt.value,opt.defaultSelected,opt.selected);\n if (opt.text==theText) selectedIndex=i-1;\n }\n theList.selectedIndex = selectedIndex;\n theList.size = (theList.autosize)?theList.options.length:theList.requestedSize;\n return;\n }\n\n // put back heading items until item text matches current selected heading\n var i=0;\n for (var t=0; t<theList.saved.length; t++)\n {\n var opt=theList.saved[t];\n if (opt.value=='')\n theList.options[i++] = new Option(opt.text,opt.value,opt.defaultSelected,opt.selected);\n if (opt.text==theText)\n break;\n }\n selectedIndex=i-1; // this is the NEW index of the current selected heading\n // put back items with value!='' until value==''\n for ( t++; t<theList.saved.length; t++)\n {\n var opt=theList.saved[t];\n if (opt.value!='')\n theList.options[i++] = new Option(opt.text,opt.value,opt.defaultSelected,opt.selected);\n if (opt.value=='')\n break;\n }\n // put back remaining items with value==''\n for ( ; t<theList.saved.length; t++)\n {\n var opt=theList.saved[t];\n if (opt.value=='')\n theList.options[i++] = new Option(opt.text,opt.value,opt.defaultSelected,opt.selected);\n }\n theList.selectedIndex = selectedIndex;\n theList.size = (theList.autosize)?theList.options.length:theList.requestedSize;\n}\n\n// these functions process clicks on the 'control links' that are displayed above the listbox\nfunction getTOCListFromButton(which)\n{\n var theList = null;\n switch (which.id)\n {\n case 'TOCMenu':\n var theSiblings = which.parentNode.parentNode.parentNode.childNodes;\n var thePlace=which.parentNode.parentNode.parentNode.parentNode.parentNode.id;\n break;\n case 'TOCSmaller':\n case 'TOCLarger':\n case 'TOCMaximize':\n var theSiblings = which.parentNode.parentNode.childNodes;\n var thePlace=which.parentNode.parentNode.parentNode.parentNode.id;\n break;\n }\n for (var k=0; k<theSiblings.length; k++)\n if (theSiblings[k].className=="TOCList") { theList=theSiblings[k]; break; }\n // DEBUG if (theList) alert('found '+theList.className+' for '+which.id+' button in '+thePlace);\n return theList;\n}\n\nfunction onClickTOCMenu(which)\n{\n var theList=getTOCListFromButton(which);\n if (!theList) return;\n var opening = theList.style.display=="none";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(theList,opening,false,"none"));\n else\n theList.style.display = opening ? "block" : "none" ;\n if (!theList.noShowCookie)\n { config.options.chkTOCShow = opening; saveOptionCookie("chkTOCShow"); }\n return(false);\n}\n\nfunction resizeTOC(which)\n{\n var theList=getTOCListFromButton(which);\n if (!theList) return;\n\n var size = theList.size;\n if (theList.style.display=="none") // make sure list is visible\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(theList,true,false,"none"));\n else\n theList.style.display = "block" ;\n switch (which.id)\n {\n case 'TOCSmaller': // decrease current listbox size\n if (theList.autosize) { theList.autosize=false; size=config.options.txtTOCListSize; }\n if (size==1) break;\n size -= 1; // shrink by one line\n theList.requestedSize = theList.size = size;\n break;\n case 'TOCLarger': // increase current listbox size\n if (theList.autosize) { theList.autosize=false; size=config.options.txtTOCListSize; }\n if (size>=theList.options.length) break;\n size += 1; // grow by one line\n theList.requestedSize = theList.size = size;\n break;\n case 'TOCMaximize': // toggle autosize\n theList.autosize = (theList.size!=theList.options.length);\n theList.size = (theList.autosize)?theList.options.length:theList.requestedSize;\n break;\n }\n if (!theList.noSizeCookie && !theList.autosize)\n { config.options.txtTOCListSize=size; saveOptionCookie("txtTOCListSize"); }\n}\n//}}}\n
/***\n| Name:|TagBasedTemplates|\n| Source:|http://simonbaird.com/mptw/#TagBasedTemplates|\n| Version:|Prototype (12-Jan-2006)|\n| Usage:|See [[FlipMeOver!]] for an example|\n***/\n//{{{\n\nconfig.templateChooser = {};\n\nfunction registerTemplate(tiddlerName,tagName) {\n config.templateChooser[tagName] = tiddlerName;\n}\n\nregisterTemplate("UpsideDownTemplate","UpsideDown");\n\nfunction checkTagTemplateRules(tags) {\n for (var t in config.templateChooser)\n for (var j=0; j<tags.length; j++)\n if (t == tags[j])\n return config.templateChooser[t];\n return null;\n}\n\nstory.chooseTemplateForTiddler = function(title,template) {\n if (!template) {\n var tiddler = store.getTiddler(title);\n if (tiddler) {\n var tagBasedTemplate = checkTagTemplateRules(store.getTiddler(title).tags);\n if (tagBasedTemplate)\n return tagBasedTemplate;\n }\n return config.tiddlerTemplates[DEFAULT_VIEW_TEMPLATE];\n }\n else \n return config.tiddlerTemplates[template];\n};\n\n//}}}\n
/***\n|Name|TagglyListPlugin|\n|Created by|SimonBaird|\n|Location|http://simonbaird.com/mptw/#TagglyListPlugin|\n|Version|1.1 20-jan-06|\n|Requires|See TagglyTagging|\n***/\n\n/***\n!Setup and config\n***/\n//{{{\n\nconfig.macros.tagglyList = {};\nconfig.macros.tagglyListByTag = {};\nconfig.macros.tagglyListControl = {};\nconfig.macros.tagglyListWithSort = {};\nconfig.macros.hideSomeTags = {};\n\n// change this to your preference\nconfig.macros.tagglyListWithSort.maxCols = 6;\n\nconfig.macros.tagglyList.label = "Tagged as %0:";\n\n// the default sort options. set these to your preference\nconfig.macros.tagglyListWithSort.defaults = {\n sortBy:"title", // title|created|modified\n sortOrder: "asc", // asc|desc\n hideState: "show", // show|hide\n groupState: "nogroup", // nogroup|group\n numCols: 1\n};\n\n// these tags will be ignored by the grouped view\nconfig.macros.tagglyListByTag.excludeTheseTags = [\n "systemConfig",\n "TiddlerTemplates"\n];\n\nconfig.macros.tagglyListControl.tags = {\n title:"sortByTitle", \n modified: "sortByModified", \n created: "sortByCreated",\n asc:"sortAsc", \n desc:"sortDesc",\n hide:"hideTagged", \n show:"showTagged",\n nogroup:"noGroupByTag",\n group:"groupByTag",\n cols1:"list1Cols",\n cols2:"list2Cols",\n cols3:"list3Cols",\n cols4:"list4Cols",\n cols5:"list5Cols",\n cols6:"list6Cols",\n cols7:"list7Cols",\n cols8:"list8Cols",\n cols9:"list9Cols" \n}\n\n// note: should match config.macros.tagglyListControl.tags\nconfig.macros.hideSomeTags.tagsToHide = [\n "sortByTitle",\n "sortByCreated",\n "sortByModified",\n "sortDesc",\n "sortAsc",\n "hideTagged",\n "showTagged",\n "noGroupByTag",\n "groupByTag",\n "list1Cols",\n "list2Cols",\n "list3Cols",\n "list4Cols",\n "list5Cols",\n "list6Cols",\n "list7Cols",\n "list8Cols",\n "list9Cols"\n];\n\n\n//}}}\n/***\n\n!Utils\n***/\n//{{{\n// from Eric\nfunction isTagged(title,tag) {\n var t=store.getTiddler(title); if (!t) return false;\n return (t.tags.find(tag)!=null);\n}\n\n// from Eric\nfunction toggleTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)==null) t.tags.push(tag);\n else t.tags.splice(t.tags.find(tag),1);\n}\n\nfunction addTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n t.tags.push(tag);\n}\n\nfunction removeTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)!=null) t.tags.splice(t.tags.find(tag),1);\n}\n\n// from Udo\nArray.prototype.indexOf = function(item) {\n for (var i = 0; i < this.length; i++) {\n if (this[i] == item) {\n return i;\n }\n }\n return -1;\n};\nArray.prototype.contains = function(item) {\n return (this.indexOf(item) >= 0);\n}\n//}}}\n/***\n\n!tagglyList\ndisplays a list of tagged tiddlers. \nparameters are sortField and sortOrder\n***/\n//{{{\n\n// not used at the moment...\nfunction sortedListOfOtherTags(tiddler,thisTag) {\n var list = tiddler.tags.concat(); // so we are working on a clone..\n for (var i=0;i<config.macros.hideSomeTags.tagsToHide.length;i++) {\n if (list.find(config.macros.hideSomeTags.tagsToHide[i]) != null)\n list.splice(list.find(config.macros.hideSomeTags.tagsToHide[i]),1); // remove hidden ones\n }\n for (var i=0;i<config.macros.tagglyListByTag.excludeTheseTags.length;i++) {\n if (list.find(config.macros.tagglyListByTag.excludeTheseTags[i]) != null)\n list.splice(list.find(config.macros.tagglyListByTag.excludeTheseTags[i]),1); // remove excluded ones\n }\n list.splice(list.find(thisTag),1); // remove thisTag\n return '[[' + list.sort().join("]] [[") + ']]';\n}\n\nfunction sortHelper(a,b) {\n if (a == b) return 0;\n else if (a < b) return -1;\n else return +1;\n}\n\nconfig.macros.tagglyListByTag.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n\n var sortBy = params[0] ? params[0] : "title"; \n var sortOrder = params[1] ? params[1] : "asc";\n\n var result = store.getTaggedTiddlers(tiddler.title,sortBy);\n\n if (sortOrder == "desc")\n result = result.reverse();\n\n var leftOvers = []\n for (var i=0;i<result.length;i++) {\n leftOvers.push(result[i].title);\n }\n\n var allTagsHolder = {};\n for (var i=0;i<result.length;i++) {\n for (var j=0;j<result[i].tags.length;j++) {\n\n if ( \n result[i].tags[j] != tiddler.title // not this tiddler\n && config.macros.hideSomeTags.tagsToHide.find(result[i].tags[j]) == null // not a hidden one\n && config.macros.tagglyListByTag.excludeTheseTags.find(result[i].tags[j]) == null // not excluded\n ) {\n if (!allTagsHolder[result[i].tags[j]])\n allTagsHolder[result[i].tags[j]] = "";\n allTagsHolder[result[i].tags[j]] += "**[["+result[i].title+"]]\sn";\n\n if (leftOvers.find(result[i].title) != null)\n leftOvers.splice(leftOvers.find(result[i].title),1); // remove from leftovers. at the end it will contain the leftovers...\n }\n }\n }\n\n\n var allTags = [];\n for (var t in allTagsHolder)\n allTags.push(t);\n\n allTags.sort(function(a,b) {\n var tidA = store.getTiddler(a);\n var tidB = store.getTiddler(b);\n if (sortBy == "title") return sortHelper(a,b);\n else if (!tidA && !tidB) return 0;\n else if (!tidA) return -1;\n else if (!tidB) return +1;\n else return sortHelper(tidA[sortBy],tidB[sortBy]);\n });\n\n if (sortOrder == "desc")\n allTags.reverse();\n\n var markup = "";\n for (var i=0;i<allTags.length;i++)\n markup += "*[["+allTags[i]+"]]\sn" + allTagsHolder[allTags[i]];\n\n for (var i=0;i<leftOvers.length;i++)\n markup += "*[["+leftOvers[i]+"]]\sn";\n\n wikify(markup,place);\n}\n\nconfig.macros.tagglyList.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n var sortBy = params[0] ? params[0] : "title"; \n var sortOrder = params[1] ? params[1] : "asc";\n var numCols = params[2] ? params[2] : 1;\n\n var result = store.getTaggedTiddlers(tiddler.title,sortBy);\n if (sortOrder == "desc")\n result = result.reverse();\n\n var listSize = result.length;\n var colSize = listSize/numCols;\n var remainder = listSize % numCols;\n\n var upperColsize;\n var lowerColsize;\n if (colSize != Math.floor(colSize)) {\n // it's not an exact fit so..\n lowerColsize = Math.floor(colSize);\n upperColsize = Math.floor(colSize) + 1;\n }\n else {\n lowerColsize = colSize;\n upperColsize = colSize;\n }\n\n var markup = "";\n var c=0;\n\n var newTaggedTable = createTiddlyElement(place,"table");\n var newTaggedBody = createTiddlyElement(newTaggedTable,"tbody");\n var newTaggedTr = createTiddlyElement(newTaggedBody,"tr");\n\n for (var j=0;j<numCols;j++) {\n var foo = "";\n var thisSize;\n\n if (j<remainder)\n thisSize = upperColsize;\n else\n thisSize = lowerColsize;\n\n for (var i=0;i<thisSize;i++) \n foo += ( "*[[" + result[c++].title + "]]\sn"); // was using splitList.shift() but didn't work in IE;\n\n var newTd = createTiddlyElement(newTaggedTr,"td",null,"tagglyTagging");\n wikify(foo,newTd);\n\n }\n\n};\n\n/* snip for later.....\n //var groupBy = params[3] ? params[3] : "t.title.substr(0,1)";\n //var groupBy = params[3] ? params[3] : "sortedListOfOtherTags(t,tiddler.title)";\n //var groupBy = params[3] ? params[3] : "t.modified";\n var groupBy = null; // for now. groupBy here is working but disabled for now.\n\n var prevGroup = "";\n var thisGroup = "";\n\n if (groupBy) {\n result.sort(function(a,b) {\n var t = a; var aSortVal = eval(groupBy); var aSortVal2 = eval("t".sortBy);\n var t = b; var bSortVal = eval(groupBy); var bSortVal2 = eval("t".sortBy);\n var t = b; var bSortVal2 = eval(groupBy);\n return (aSortVal == bSortVal ?\n (aSortVal2 == bSortVal2 ? 0 : (aSortVal2 < bSortVal2 ? -1 : +1)) // yuck\n : (aSortVal < bSortVal ? -1 : +1));\n });\n }\n\n if (groupBy) {\n thisGroup = eval(groupBy);\n if (thisGroup != prevGroup)\n markup += "*[["+thisGroup+']]\sn';\n markup += "**[["+t.title+']]\sn';\n prevGroup = thisGroup;\n }\n\n\n\n*/\n\n\n//}}}\n\n/***\n\n!tagglyListControl\nUse to make the sort control buttons\n***/\n//{{{\n\nfunction getSortBy(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.sortBy;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["title"])) return "title";\n else if (tiddler.tags.contains(usetags["modified"])) return "modified";\n else if (tiddler.tags.contains(usetags["created"])) return "created";\n else return defaultVal;\n}\n\nfunction getSortOrder(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.sortOrder;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["asc"])) return "asc";\n else if (tiddler.tags.contains(usetags["desc"])) return "desc";\n else return defaultVal;\n}\n\nfunction getHideState(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.hideState;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["hide"])) return "hide";\n else if (tiddler.tags.contains(usetags["show"])) return "show";\n else return defaultVal;\n}\n\nfunction getGroupState(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.groupState;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["group"])) return "group";\n else if (tiddler.tags.contains(usetags["nogroup"])) return "nogroup";\n else return defaultVal;\n}\n\nfunction getNumCols(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.numCols; // an int\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n for (var i=1;i<=config.macros.tagglyListWithSort.maxCols;i++)\n if (tiddler.tags.contains(usetags["cols"+i])) return i;\n return defaultVal;\n}\n\n\nfunction getSortLabel(title,which) {\n // TODO. the strings here should be definable in config\n var by = getSortBy(title);\n var order = getSortOrder(title);\n var hide = getHideState(title);\n var group = getGroupState(title);\n if (which == "hide") return (hide == "show" ? "−" : "+"); // 0x25b8;\n else if (which == "group") return (group == "group" ? "normal" : "grouped");\n else if (which == "cols") return "cols±"; // &plusmn;\n else if (by == which) return which + (order == "asc" ? "↓" : "↑"); // &uarr; &darr;\n else return which;\n}\n\nfunction handleSortClick(title,which) {\n var currentSortBy = getSortBy(title);\n var currentSortOrder = getSortOrder(title);\n var currentHideState = getHideState(title);\n var currentGroupState = getGroupState(title);\n var currentNumCols = getNumCols(title);\n\n var tags = config.macros.tagglyListControl.tags;\n\n // if it doesn't exist, lets create it..\n if (!store.getTiddler(title))\n store.saveTiddler(title,title,"",config.options.txtUserName,new Date(),null);\n\n if (which == "hide") {\n // toggle hide state\n var newHideState = (currentHideState == "hide" ? "show" : "hide");\n removeTag(title,tags[currentHideState]);\n if (newHideState != config.macros.tagglyListWithSort.defaults.hideState)\n toggleTag(title,tags[newHideState]);\n }\n else if (which == "group") {\n // toggle hide state\n var newGroupState = (currentGroupState == "group" ? "nogroup" : "group");\n removeTag(title,tags[currentGroupState]);\n if (newGroupState != config.macros.tagglyListWithSort.defaults.groupState)\n toggleTag(title,tags[newGroupState]);\n }\n else if (which == "cols") {\n // toggle num cols\n var newNumCols = currentNumCols + 1; // confusing. currentNumCols is an int\n if (newNumCols > config.macros.tagglyListWithSort.maxCols || newNumCols > store.getTaggedTiddlers(title).length)\n newNumCols = 1;\n removeTag(title,tags["cols"+currentNumCols]);\n if (("cols"+newNumCols) != config.macros.tagglyListWithSort.defaults.groupState)\n toggleTag(title,tags["cols"+newNumCols]);\n }\n else if (currentSortBy == which) {\n // toggle sort order\n var newSortOrder = (currentSortOrder == "asc" ? "desc" : "asc");\n removeTag(title,tags[currentSortOrder]);\n if (newSortOrder != config.macros.tagglyListWithSort.defaults.sortOrder)\n toggleTag(title,tags[newSortOrder]);\n }\n else {\n // change sortBy only\n removeTag(title,tags["title"]);\n removeTag(title,tags["created"]);\n removeTag(title,tags["modified"]);\n\n if (which != config.macros.tagglyListWithSort.defaults.sortBy)\n toggleTag(title,tags[which]);\n }\n\n store.setDirty(true); // save is required now.\n story.refreshTiddler(title,false,true); // force=true\n}\n\nconfig.macros.tagglyListControl.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n var onclick = function(e) {\n if (!e) var e = window.event;\n handleSortClick(tiddler.title,params[0]);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return false;\n };\n createTiddlyButton(place,getSortLabel(tiddler.title,params[0]),"Click to change sort options",onclick,params[0]=="hide"?"hidebutton":"button");\n}\n//}}}\n/***\n\n!tagglyListWithSort\nput it all together..\n***/\n//{{{\nconfig.macros.tagglyListWithSort.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n if (tiddler && store.getTaggedTiddlers(tiddler.title).length > 0)\n wikify(\n "<<tagglyListControl hide>>"+\n (getHideState(tiddler.title) != "hide" ? \n '<html><span class="tagglyLabel">'+config.macros.tagglyList.label.format([tiddler.title])+' </span></html>'+\n "<<tagglyListControl title>><<tagglyListControl modified>><<tagglyListControl created>><<tagglyListControl cols>><<tagglyListControl group>>\sn" + \n "<<tagglyList" + (getGroupState(tiddler.title)=="group"?"ByTag ":" ") + getSortBy(tiddler.title)+" "+getSortOrder(tiddler.title)+" "+getNumCols(tiddler.title)+">>" // hacky\n // + \sn----\sn" +\n //"<<tagglyList "+getSortBy(tiddler.title)+" "+getSortOrder(tiddler.title)+">>"\n : ""),\n place,null,tiddler);\n}\n\n//}}}\n/***\n\n!hideSomeTags\nSo we don't see the sort tags.\n(note, they are still there when you edit. Will that be too annoying?\n***/\n//{{{\n\n// based on tags.handler\nconfig.macros.hideSomeTags.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n var theList = createTiddlyElement(place,"ul");\n if(params[0] && store.tiddlerExists[params[0]])\n tiddler = store.getTiddler(params[0]);\n var lingo = config.views.wikified.tag;\n var prompt = tiddler.tags.length == 0 ? lingo.labelNoTags : lingo.labelTags;\n createTiddlyElement(theList,"li",null,"listTitle",prompt.format([tiddler.title]));\n for(var t=0; t<tiddler.tags.length; t++)\n if (!this.tagsToHide.contains(tiddler.tags[t])) // this is the only difference from tags.handler...\n createTagButton(createTiddlyElement(theList,"li"),tiddler.tags[t],tiddler.title);\n\n}\n\n//}}}\n/***\n\n!Refresh everything when we save a tiddler. So the tagged lists never get stale. Is this too slow???\n***/\n//{{{\n\nfunction refreshAllVisible() {\n story.forEachTiddler(function(title,element) {\n story.refreshTiddler(title,false,true);\n });\n}\n\nstory.saveTiddler_orig_mptw = story.saveTiddler;\nstory.saveTiddler = function(title,minorUpdate) {\n var result = this.saveTiddler_orig_mptw(title,minorUpdate);\n refreshAllVisible();\n return result;\n}\n\nstore.removeTiddler_orig_mptw = store.removeTiddler;\nstore.removeTiddler = function(title) {\n this.removeTiddler_orig_mptw(title);\n refreshAllVisible();\n}\n\n//}}}\n\n// // <html>&#x25b8;&#x25be;&minus;&plusmn;</html>
* Name: Ted Pavlic\n* E-mail: [[ted@tedpavlic.com|mailto:ted@tedpavlic.com]]\n* Website: http://www.tedpavlic.com/\n* Birthday: February 28, 1981\n** <<reminder month:2 day:28 firstyear:1981 title:"Ted's Birthday" format:"Next Birthday ANNIVERSARY: DATE - DIFF">>
Super-duper thanks to JeremyRuston for creating such a great Open Source project.\n \nThanks to Merlin Mann of 43Folders for his work evangelizing and expanding GTD and other life hacks.\n \nThanks to David Allen and Davidco. for coming up with such an elegant and powerful system for dealing with modern life.\n\nFinally, thanks to everyone who made comments and reported bugs.\n\nJeremy's original thank you follows:\n----\nThank you to everybody who has helped me with support and suggestions for TiddlyWiki, but especially IsaoSonobe for his cunning regular expression code, and to my friend RebeccaWelby for the SiteDesign.
This is the ThirdVersion of TiddlyWiki, released in April 2005. The SecondVersion was released in December 2004, and before that the FirstVersion in September 2004.\n\nSee the RevisionHistory for details of minor changes and bug-fixes since the ThirdVersion.
/***\n|''Name'' |TiddlerTemplatesMacros|\n|''Version'' |1.0|\n|''Source'' |http://www.kultofbubb.net/tiddlywiki/|\n|''Author'' |[[RichCarrillo|mailto://RichCarrillo@gmail.com]]|\n|''Type'' |Macros|\n|''Required'' |[[TiddlyWiki|http://www.tiddlywiki.com]] 2.0+|\n|''License'' ||\n|''Documentation''| TiddlerTemplatesMacrosDocumentation|\n\n!Code\n***/\n//{{{\n// Drop down indicator for pop-up menu buttons\nvar dropdownchar = (document.all?"▼":"▾") // the fat one is the only one that works in IE\n\nversion.extensions.TiddlerTemplatesMacros = {\n major: 0, minor: 9, revision: 0,\n date: new Date(2006, 2, 21), \n type: 'macro',\n source: "http://www.kultofbubb.net/tiddlywiki/index.html#TiddlerTemplatesMacros"\n};\n\n// shadow tiddler to provide basic syntax and link to full documentation\nconfig.shadowTiddlers.TiddlerTemplatesMacrosDocumentation = "[[Full Documentation|http://www.kultofbubb.net/tiddlywiki/index.html#TiddlerTemplatesMacrosDocumentation]]\sn"; \n\nconfig.macros.newFromTemplate = {}\nconfig.macros.newFromTemplatePopup = {}\nconfig.macros.newFromTemplateButton = {}\n\n// The tiddlerTemplatesMacros object just holds default settings, messages and common functions used by the other macros\nconfig.macros.tiddlerTemplatesMacros = {\n // messages\n label: "New...",\n tooltip: "Create a tiddler from a Template",\n titlePrefix: "New",\n errorNoTemplates: "No templates found! Add the tag '%0' to a tiddler you would like to use as a template",\n errorNoTemplateTiddler: "The template tiddler: '%0', could not be found.",\n errorMissingRequiredParam: "Missing a required parameter: %0 ",\n errorTiddlerAlreadyExists: "The tiddler: %0 already exists!",\n\n // default settings\n templateTag: "TiddlerTemplates",\n\n // common functions used by other macros\n myReadMacroParams: function(paramString){\n var regexpMacroParam = new\n RegExp("(?:\s\ss*)(?:(?:\s"((?:(?:\s\s\s\s\s")|[^\s"])*)\s")|(?:'((?:(?:\s\s\s\s\s')|[^'])*)')|(?:\s\s[\s\s[([^\s\s]]*)\s\s]\s\s])|([^\s"'\s\ss][^\s"'\s\ss]*))","mg");\n var params = [];\n do {\n var match = regexpMacroParam.exec(paramString);\n if(match){\n if(match[1]) // Double quoted\n params.push(match[1]);\n else if(match[2]) // Single quoted\n params.push(match[2]);\n else if(match[3]) // Double-square-bracket quoted\n params.push(match[3]);\n else if(match[4]) // Unquoted\n params.push(match[4]);\n }\n } while(match);\n return params;\n }, // closes myReadMacroParams function definition\n\n reparseParams: function( params ) {\n var s = params.join(" ");\n var re = /([^:\ss]*):["]([^"]*)["]/g ;\n var ret = new Array() ;\n var m ;\n while( (m = re.exec( s )) != null ) ret[ m[1] ] = m[2] ;\n return ret ;\n }, // closes reparseParams function definition\n\n getTiddlerEditField: function(title,field){\n var tiddler = document.getElementById(story.idPrefix + title);\n if(tiddler != null){\n var children = tiddler.getElementsByTagName("*")\n var e = null;\n for (var t=0; t<children.length; t++){\n var c = children[t];\n if(c.tagName.toLowerCase() == "input" || c.tagName.toLowerCase() == "textarea"){\n if(!e) {e = c;}\n if(c.getAttribute("edit") == field){e = c;}\n }\n }\n if(e){return e;}\n }\n }, // closes getTiddlerEditField function definition\n\n newFromTemplate: function(event){\n var title = this.getAttribute("templateTitle");\n if (this.getAttribute("tagToAdd")) {var tagToAdd = this.getAttribute("tagToAdd");}\n if (this.getAttribute("tagToStrip")) {var tagToStrip = this.getAttribute("tagToStrip");}\n\n // get the template and extract its info\n var template = store.getTiddler(title);\n var newTitle = config.macros.tiddlerTemplatesMacros.titlePrefix+template.title;\n var newText = template.text;\n var newTags = template.getTags();\n \n // if a tiddler by this name already exists, show an error message and quit\n if (store.getTiddler(newTitle)) {\n displayMessage(config.macros.tiddlerTemplatesMacros.errorTiddlerAlreadyExists.format([newTitle]));\n story.displayTiddler(null,newTitle,DEFAULT_VIEW_TEMPLATE);\n return;\n }\n // create new tiddler\n story.displayTiddler(null,newTitle,DEFAULT_EDIT_TEMPLATE);\n\n // grab the new Tiddlers text edit box\n var tiddlerTextArea = config.macros.tiddlerTemplatesMacros.getTiddlerEditField(newTitle,"text");\n var tiddlerTagArea = config.macros.tiddlerTemplatesMacros.getTiddlerEditField(newTitle,"tags");\n\n // Stuff template info into newly created tiddler\n tiddlerTextArea.value=newText;\n if (tagToAdd){newTags += " " + String.encodeTiddlyLink(tagToAdd);}\n tiddlerTagArea.value=newTags;\n if (tagToStrip) {story.setTiddlerTag(newTitle,tagToStrip,-1);}\n story.focusTiddler(newTitle,"title");\n return false; //why false?\n } // closes newFromTemplate function definition\n}; // closes tiddlerTemplateMacros object definition\n\nconfig.macros.newFromTemplatePopup.handler = function(place,macroName,params,wikifier,paramString,callingTiddler){\n var makeTemplateList = function(event) {\n if (!event) var event = window.event;\n var templateTag = this.getAttribute("templateTag");\n if (this.getAttribute("tagToAdd")){var tagToAdd = this.getAttribute("tagToAdd");}\n\n var templateList = store.getTaggedTiddlers(templateTag);\n var popup = Popup.create(templateButton);\n\n // pull the titles out of the tiddlers retured by getTaggedTiddlers\n var templateTitles = [];\n var li,r;\n for(r=0;r<templateList.length;r++)\n if(templateList[r].title != templateTitles){templateTitles.push(templateList[r].title);}\n\n // for each one of the titles create a new TiddlyButton in the popup\n for(r=0; r<templateTitles.length; r++){\n var templateListItem = createTiddlyButton(createTiddlyElement(popup,"li"),templateTitles[r],null,config.macros.tiddlerTemplatesMacros.newFromTemplate);\n templateListItem.setAttribute("templateTitle",templateTitles[r]);\n templateListItem.setAttribute("tagToStrip",templateTag);\n if (tagToAdd){templateListItem.setAttribute("tagToAdd",tagToAdd);}\n }\n\n Popup.show(popup,true);\n event.cancelBubble = true;\n if (event.stopPropagation) event.stopPropagation();\n return false; // why false?\n } // closes makeTemplateList function definition\n\n // process params\n var paramsToParse = params;\n var input = config.macros.tiddlerTemplatesMacros.reparseParams( paramsToParse ) ;\n var templateTag = input["templateTag"]?input["templateTag"].trim():config.macros.tiddlerTemplatesMacros.templateTag ;\n var label = input["label"]?input["label"].trim():config.macros.tiddlerTemplatesMacros.label ;\n label = label.replace(/<arrow>/g, dropdownchar) \n var tooltip = input["tooltip"]?input["tooltip"].trim():config.macros.tiddlerTemplatesMacros.tooltip ;\n\n // user can only use hereMode if callingTiddler was passed to the macro\n var hereMode; \n if (input["hereMode"] && callingTiddler) {hereMode = callingTiddler.title;}\n else {hereMode = null;}\n\n // error out if no tiddlers are tagged as templates\n var templateList = store.getTaggedTiddlers(templateTag);\n if(templateList == "") {\n createTiddlyError(place,config.messages.macroError.format([macroName]),config.macros.tiddlerTemplatesMacros.errorNoTemplates.format([templateTag]));\n return;\n }\n\n var templateButton = createTiddlyButton(place,label,tooltip,makeTemplateList);\n templateButton.setAttribute("templateTag",templateTag);\n if (hereMode){templateButton.setAttribute("tagToAdd",hereMode);}\n}; // closes newFromTemplatePopup handler definition\n\n\nconfig.macros.newFromTemplateButton.handler = function(place,macroName,params,wikifier,paramString,callingTiddler){\n\n // process params\n var paramsToParse = params;\n var input = config.macros.tiddlerTemplatesMacros.reparseParams( paramsToParse ) ;\n var templateTiddler = input["templateTiddler"]?input["templateTiddler"].trim():null ;\n var templateTag = input["templateTag"]?input["templateTag"].trim():null ;\n var label = input["label"]?input["label"].trim():config.macros.tiddlerTemplatesMacros.label ;\n var tooltip = input["tooltip"]?input["tooltip"].trim():config.macros.tiddlerTemplatesMacros.tooltip ;\n\n // user can only use hereMode if callingTiddler was passed to the macro\n var hereMode; \n if (input["hereMode"] && callingTiddler) {hereMode = callingTiddler.title;}\n else {hereMode = null;}\n\n // error out if template tiddler was not specified or if it does not exist\n if (templateTiddler == null){\n createTiddlyError(place,config.messages.macroError.format([macroName]),config.macros.tiddlerTemplatesMacros.errorMissingRequiredParam.format(["templateTiddler"]));\n return;\n } // ends if templateTiddler == null (not in params)\n\n var templateTiddlerObj = store.getTiddler(templateTiddler);\n if(templateTiddlerObj == null) {\n createTiddlyError(place,config.messages.macroError.format([macroName]),config.macros.tiddlerTemplatesMacros.errorNoTemplateTiddler.format([templateTiddler]));\n return;\n } // ends if templateTiddlerObj == null (not in store)\n\n var templateButton = createTiddlyButton(place,label,tooltip,config.macros.tiddlerTemplatesMacros.newFromTemplate);\n templateButton.setAttribute("templateTitle",templateTiddlerObj.title);\n if (hereMode){templateButton.setAttribute("tagToAdd",hereMode);}\n if (templateTag){templateButton.setAttribute("tagToStrip",templateTag);}\n\n}; // closes newFromTemplateButton handler definition\n\n// This macro only in here for backward compatibility. I'll problably drop it from the next release\nconfig.macros.newFromTemplate.handler = function(place,macroName,params,wikifier,paramString,callingTiddler){\n\n // juggle params around since this macro does NOT use named parameters and newFromTemplatePopup does\n if (params[0] != null) {paramString = 'templateTag:\s"'+paramString+'\s"';}\n var paramsToPass = paramString.readMacroParams();\n config.macros.newFromTemplatePopup.handler(place,macroName,paramsToPass, wikifier,paramString, callingTiddler);\n\n}; // closes newFromTemplate handler definition\n\n//}}}\n\n
|''Name'' |TiddlerTemplatesMacros|\n|''Version'' |1.0|\n|''Source'' |http://www.kultofbubb.net/tiddlywiki/|\n|''Author'' |[[RichCarrillo|mailto://RichCarrillo@gmail.com]]|\n|''Type'' |Macros|\n|''Required'' |[[TiddlyWiki|http://www.tiddlywiki.com]] 2.0+|\n|''License'' ||\n|''Code''|TiddlerTemplatesMacros|\n\n!Description\nTiddlerTemplatesMacros is a collection macros that allow you to easily create new tiddlers using existing tiddlers as templates. The package is comprised of two macros: newFromTemplatePopup and newFromTemplateButton. I've also retained the old newFromTemplate macro name and re-directed it to newFromTemplatePopup for backward compatibility. I'll problably drop that from the next release.\n\n''newFromTemplatePopup (and the old newFromTemplate) -'' Using this macro will create a pop-up that lists anything tagged with TiddlerTemplates. Choosing an item off this list will create a new Tiddler. This new Tiddler will have the same contents as the template. The title will be NEW<template title> and it's tags will be the same as the template, but with the TiddlerTemplates tag stripped off. TiddlerTemplates is the same tag that WikiBar uses for templates. You can chose your own template tag with the parameter "templateTag".(see the syntax section below)\n\n''newFromTemplateButton -'' Using this macro will create a button. Clicking this button will create a new Tiddler. This new Tiddler will have the same contents as the tiddler you specifiy as the template in the parameters. The title will be NEW<template title> and it's tags will be the same as the template tiddler, with any tag you specifiy as templateTag stripped off.\n\n!Installation\nImport (or copy the contents of) TiddlerTemplatesMacros into your Wiki.\nTag it with systemConfg, Save and Reload (Refresh).\n\nYou may also import or copy this documentation tiddler. It should not be tagged with systemConfig.\nI've included some example templates. Import or copy all Tiddlers tagged with [[TiddlerTemplates]] to get you started.\n\n!Syntax - {{{<<newFromTemplatePopup>>}}}\n|>|>|{{{<<}}}''newFromTemplatePopup'' //label:"button label <arrow>"// //tooltip:"tooltip text"// //templateTag:"MyTemplates"// //hereMode:"true"//{{{>>}}}|\n|''Parameter''|''Default Value''|''Description''|\n|//label//|New Here...|The text to appear on the button. If you add <arrow> to your button label (within the quotes), a small drop-down indicator arrow will be automaticly added|\n|//tooltip//|Create a tiddler from a template|The text to appear on the tooltip, when you hover over the button|\n|//templateTag//|TiddlerTemplates|The pop-up menu will list any tiddler of a certain tag. This is the tag that indicated which tiddlers you'd like to use as templates. This tag will be stripped off the new tiddler, so it doesnt become a template itself.|\n|//hereMode//|False|If set to true, the new tiddler will be tagged with the title of the tiddler where the macro is called from. To be used in the ViewTemplate|\n|>|>|~~Syntax formatting: Required parameters in ''bold'', optional parameters in //italics//. Parameters may appear in any order, but must be in the //keyword:"value"// format. All values should be double-quoted without any spaces before the quotes~~|\n\n!Syntax - {{{<<newFromTemplateButton>>}}}\n|>|>|{{{<<}}}''newFromTemplateButton'' //label:"button label"// //tooltip:"tooltip text"// ''templateTiddler:"TaskItem"'' //templateTag:"MyTemplates"// //hereMode:"true"//{{{>>}}}|\n|''Parameter''|''Default Value''|''Description''|\n|//label//|New Here...|The text to appear on the button.|\n|//tooltip//|Create a tiddler from a template|The text to appear on the tooltip, when you hover over the button|\n|//templateTag//|TiddlerTemplates|Since there is no pop-up menu, this tag will just be stripped off the new tiddler, so it doesnt become a template itself.|\n|''templateTiddler''|null|''Required'' - The tiddler to use as a template. The title, text and tags will be copied.|\n|//hereMode//|False|If set to true, the new tiddler will be tagged with the title of the tiddler where the macro is called from. To be used in the ViewTemplate|\n|>|>|~~Syntax formatting: Required parameters in ''bold'', optional parameters in //italics//. Parameters may appear in any order, but must be in the //keyword:"value"// format. All values should be double-quoted without any spaces before the quotes~~|\n\n!Syntax - {{{<<newFromTemplate>>}}}\n|>|>|{{{<<}}}''newFromTemplate'' //templateTag//{{{>>}}}|\n|''Parameter''|''Default Value''|''Description''|\n|//templateTag//|TiddlerTemplates|The pop-up menu will list any tiddler of a certain tag. This is the tag that indicated which tiddlers you'd like to use as templates. This tag will be stripped off the new tiddler, so it doesnt become a template itself.|\n|>|>|~~Syntax formatting: Required parameters in ''bold'', optional parameters in //italics//.~~|\n|>|>|~~''This macro does NOT use named parameters. It has only one optional parameter "templateTag". You can not override default label & tooltip. HereMode is not available''~~|\n\n!Example\nnewFromTemplatePopup <<newFromTemplatePopup tooltip:"Choose a template" label:"Template List <arrow>">>\nnewFromTemplateButton <<newFromTemplateButton templateTiddler:"TaskItem" tooltip:"Create a new Task Item" label:"New Task">>\nnewFromTemplate <<newFromTemplate>>\n\n!Revision History\n* 0.1 (2006-01-13)\n** First release\n* 0.2 (2006-01-16)\n** Added the ability to pass the templateTag as an optional first parameter.\n* 0.3 (2006-01-16)\n** Bunch of little code tweaks trying to figure out why it was breaking in IE. Fixed it.\n* 0.9 (2006-02-15)\n** Changed the name to TiddlerTemplatesMacros. It is now a collection of macros\n** Reorganized code\n** Implemented named macro parameters (using [[Paul Petterson|http://thepettersons.org/PaulsNotepad.html]]'s reparse function)\n** Improved error catching & reporting (when a required parameter is missing or to prevent overwritting of an existing tiddler)\n** The user can now pass the button label, tooltip and templateTag as parameters\n** Created second macro that shows a button linked to a specfic template\n** Incorporated "New Here" code from Simon Baird. Now you have the ability to create a new tiddler, from a template and have it tagged with the title of the tiddler where the macro was called from.\n** Seperated documentation from the code. I'm using a shadow tiddler that shows the syntax and a link to the full documentation if the user doesnt have it.\n** Made it easier to translate by putting all the message text in one place\n** All new documentation\n\n!Credits\n* Most of this code is adaptions of TiddlyWiki core functions. I took a close look at PopupMacro and WikiBar's Templater Add-on for help.\n* The named macro parameters function "reparse" is from [[Paul Petterson|http://thepettersons.org/PaulsNotepad.html]]\n* The "New Here" functionality provided by [[Simon Baird|http://simonbaird.com/mptw/]]\n* Thanks to Ted Pavlic for QA and feature suggestions (including the optional dropdown arrow)\n\n!Roadmap - ToDo list\n*==Let users pass the button label, tooltip and template tag as parameters.==\n*==Make it easier to translate by putting all the message text into one place==\n*==Create a standalone button (no popup) that is keyed directly to a template tiddler==\n*==Use named parameters==\n*==Specify tag(s) to strip off a new tiddler when created with newFromTemplateButton==\n*==More error catching and reporting (Error when missing required parameters. Check to see if tiddler we're about to create already exists)==\n*==Combine with NewHere in some way. Maybe make this into a toolbar command so it's more like NewHereFromTemplate. I'd like to be able to be in a Project tiddler and have a "New Task Here" or "New Reminder Here" type of commands available.==\n*Let users pass more than one tag in templateTag, but collate them all together into one pop-up menu\n*Make named parameters work with double square bracket style closures
/***\n|''Name:''|TiddlerWithParamsPlugin|\n|''Version:''|1.0.0 (2006-01-20)|\n|''Source:''|http://tiddlywiki.abego-software.de/#TiddlerWithParamsPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n!Description\n\nThe TiddlerWithParamsPlugin extends the build-in {{{<<tiddler...>>}}} macro. It replaces placeholders ($1, $2, ...) in the given tiddler by values passed with the macro. Then it inserts the (replaced) text, just like the original {{{<<tiddler...>>}}} macro.\n\n''Syntax:'' \n|>|{{{<<}}}''tiddler '' //tiddlerName// [//className//] [''with:'' //arguments// ] [''prefix:'' //prefixString//] {{{>>}}}|\n|//tiddlerName//|The name of the tiddler to be included. The tiddler may contain placeholders ($1, $2, ... $9) that will be replaced with the values passed with the macro|\n|//className//|The (CSS) class to be used around the embedded tiddler|\n|//arguments//|up to 9 arguments may be passed to the macro, used as the values for the placeholders $1, $2, ... $9 in the referenced template|\n|//prefixString//|By default the placeholders $1, $2, $3,..., $9 are used. But you may change the "prefix" before the placeholder number ("$") to some other text through the "prefix:" option. This may be necessary when you are using the $n in the tiddler you are referencing (e.g. when you are using regular expressions).|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. ~~|\n\n!Example\n\nThe following ''//ProjectTemplate//'' tiddler defines an "Overview" page for a project, that gives access to various "sub-tiddlers" used in the project, that follow a static naming schema (e.g. all Notes for any project are stored in a tiddler called "//projectName// Notes"). $1 holds the name of the Project (e.g. "ForEachTiddler"), $2 holds the type of the published component (e.g. "Plugin", "Macro", "Function").\n{{{\n![[$1Project]] Overview\n* [[$1$2]]\n* [[ToDo|$1 ToDos]]\n* [[Notes|$1 Notes]]\n* [[Examples|$1Examples]]\n* [[Tests|$1 Tests]]\n* [[Open Bugs/CRs|$1 Open Bugs and ChangeRequests]]\n}}}\n\nThis template is now used in the ''//ForEachTiddlerProject//'' tiddler:\n{{{\n<<tiddler ProjectTemplate with: ForEachTiddler Plugin>>\n}}}\n\nThis results in the following tiddler text for the ''//ForEachTiddlerProject//'' tiddler:\n{{{\n![[ForEachTiddlerProject]] Overview\n* [[ForEachTiddlerPlugin]]\n* [[ToDo|ForEachTiddler ToDos]]\n* [[Notes|ForEachTiddler Notes]]\n* [[Examples|ForEachTiddlerExamples]]\n* [[Tests|ForEachTiddler Tests]]\n* [[Open Bugs/CRs|ForEachTiddler Open Bugs and ChangeRequests]]\n}}}\n\n!Revision history\n* v1.0.0 (2006-01-20)\n** initial version\n!Code\n***/\n//{{{\n//============================================================================\n// TiddlerWithParamsPlugin\n//============================================================================\n\n// Ensure that the Plugin is only installed once.\n//\nif (!version.extensions.TiddlerWithParamsPlugin) {\n\nversion.extensions.TiddlerWithParamsPlugin = {\n major: 1, minor: 0, revision: 0, \n date: new Date(2006,1,20), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#TiddlerWithParamsPlugin"\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nvar indexInArray = function(array, item) {\n for (var i = 0; i < array.length; i++) {\n if (array[i] == item) {\n return i;\n }\n }\n return -1;\n}\n\n// ---------------------------------------------------------------------------\n// The (hijacked) tiddler Macro Handler \n// ---------------------------------------------------------------------------\n\nconfig.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n var argsStart;\n var className = params[1];\n if (className == "with:") {\n className = null;\n argsStart = 2;\n } else {\n argsStart = (params[2] == "with:") ? 3 : -1;\n }\n \n var wrapper = createTiddlyElement(place,"span",null,className ? className : null,null);\n var text = store.getTiddlerText(params[0]);\n if(text) {\n if (argsStart >= 0) {\n // The params between the "with:" and the "prefix:" (or the end) are the arguments,\n // The param behind the "prefix:" is the prefix before the placeholder numbers.\n var argsEnd = params.length;\n var prefix = "$";\n var prefixIndex = indexInArray(params, "prefix:");\n if (prefixIndex >= argsStart) {\n argsEnd = prefixIndex;\n if (prefixIndex < (params.length-1)) {\n prefix = params[prefixIndex+1];\n }\n }\n // to avoid any "special RE chars" problems with the prefix string escape all chars.\n prefix = prefix.escapeRegExp();\n \n var arguments = params.slice(argsStart, argsEnd);\n var n = Math.min(arguments.length, 9);\n for (var i = 0; i < n; i++) {\n var value = arguments[i];\n \n var placeholderRE = new RegExp(prefix+(i+1),"mg");\n text = text.replace(placeholderRE, value);\n }\n }\n wikify(text,wrapper,null,store.getTiddler(params[0]));\n }\n}\n\n\n// End of "install only once"\n}\n\n//============================================================================\n// End of TiddlerWithParamsPlugin\n//============================================================================\n//}}}\n/***\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2006 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n
A TiddlyWiki is like a blog because it's divided up into neat little chunks, but it encourages you to read it by hyperlinking rather than sequentially: if you like, a non-linear blog analogue that binds the individual microcontent items into a cohesive whole. I think that TiddlyWiki represents a novel medium for writing, and will promote it's own distinctive WritingStyle. This is the ThirdVersion of TiddlyWiki, which adds several NewFeatures. There are also several TiddlyWikiAdaptations by other developers based on earlier versions.\n\nThe original TiddlyWiki is [[here|http://tiddlywiki.com]].
The first and original was [[PhpTiddlyWiki|http://www.patrickcurry.com/tiddly/]] from PatrickCurry and GabrielJeffrey that adds a simple ServerSide in PHP with MySQL. Patrick's site allows anyone to create and edit tiddlers, and has become the de facto community site around TiddlyWiki.\n\nSome of the other adaptations include:\n* HenrikAastedSorensen's at http://aasted.org/wiki\n* IsaoSonobe's OgreKitWiki at http://www-gauge.scphys.kyoto-u.ac.jp/~sonobe/OgreKit/OgreKitWiki.html \n* JacquesTurbé's TidliPo, in French at http://avm.free.fr/IMG/html/carnet_gt_BigCo.html\n* ChristianHauck's at http://www.christianhauck.net/html/14300.html\n* TonyLownds's at http://tony.lownds.com/home/\n* PoulStaugaard and IvanMetalnikov's at http://poul.staugaard.dk/IeWiki.htm\n\n* There's also KevemBuangga's TiddlyWikiClone at http://www.kevembuangga.com/hwk/hailiwiki.htm (caution: on Safari, it seems to get locked up with error alerts)
TiddlyWiki has been used as the basis of a couple of experiments in hypertext fiction. GinaTrapani created [[Baby Dog Sitter|http://scribbling.net/tiddlywiki-and-non-linear-fiction]] with the FirstVersion of TiddlyWiki, followed by "[[Die, Vampire! Die!|http://www.davidvanwert.com/wiki/dievampiredie.html]]" from DavidVanWert.
IsaoSonobe's TiddlyWikiPod is a nifty utility for Mac OS X that copies the content of a TiddlyWiki to an iPod where it can be read, and links followed, using the touch wheel. Isao has also added the ability to link to songs from the TiddlyWiki text which enables some interesting applications. At the moment, it only works with the older SecondVersion of TiddlyWiki. It can be found at http://www8.ocn.ne.jp/~sonoisa/TiddlyWikiPod/index.html
/***\nExamples:\n\n|Code|Description|Example|h\n|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|\n|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|\n|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|\n|{{{<<toggleTag TagName TiddlerName nolabel>>Click me}}}|Same but hide the label|<<toggleTag TagName TiddlerName nolabel>>Click me|\n(Note if TiddlerName does exist it will be silently created)\n***/\n//{{{\n\n\n// This function contributed by Eric Shulman\nfunction toggleTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)==null) t.tags.push(tag)\n else t.tags.splice(t.tags.find(tag),1)\n}\n\n// This function contributed by Eric Shulman\nfunction isTagged(title,tag) {\n var t=store.getTiddler(title); if (!t) return false;\n return (t.tags.find(tag)!=null);\n}\n\nconfig.macros.toggleTag = {};\nconfig.views.wikified.toggleTag = {fulllabel: "[[%0]] [[%1]]", shortlabel: "[[%0]]", nolabel: "" };\n\nconfig.macros.toggleTag.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if(tiddler instanceof Tiddler) {\n var tag = (params[0] && params[0] != '.') ? params[0] : "checked";\n var title = (params[1] && params[1] != '.') ? params[1] : tiddler.title;\n var hidelabel = params[2]?true:false;\n\n var onclick = function(e) {\n if (!e) var e = window.event;\n if (!store.getTiddler(title))\n store.saveTiddler(title,title,"",config.options.txtUserName,new Date(),null);\n toggleTag(title,tag);\n\n store.setDirty(true); // so TW knows it has to save now\n\n story.forEachTiddler(function(title,element) {\n story.refreshTiddler(title,false,true)\n });\n\n return false;\n };\n\n var lingo = config.views.wikified.toggleTag;\n\n // this part also contributed by Eric Shulman\n var c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick=onclick;\n place.appendChild(c);\n c.checked=isTagged(title,tag);\n\n if (!hidelabel) {\n var label = (title!=tiddler.title)?lingo.fulllabel:lingo.shortlabel;\n wikify(label.format([tag,title]),place);\n }\n }\n}\n\n//}}}\n
A row of ToolbarButtons appears to the right of a tiddler title when the mouse is hovered over it. The buttons are:\n* ''close'' - close the current tiddler\n* ''edit'' - edit the current tiddler\n* ''permalink'' - puts a link direct to the current tiddler into the address bar\n* ''references'' - displays all the tiddlers that link to the current tiddler\n* ''done'' - save all changes and create a backup\n* ''cancel'' - cancel changes to a tiddler being edited\n* ''delete'' - delete the current tiddler
/***\n''ToolkitPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#ToolkitPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nTiddlyWiki uses many different options, messages, shadow tiddlers, styles, notification functions and macro handlers to control a variety of program behaviors and appearances. While many of these values are normally hidden from the TW user, it can be helpful to know this information when diagnosing the behavior of macros that may be interacting with core functions and can even modify or dynamically add to the internal values currently being used.\n\n!!!!!Usage\n<<<\n''{{{<<sysInfo options|messages|shadows|styles|notify|macros>>}}}''\n\nThe ''sysInfo'' macro lets you view many key program values, so you can quickly determine the internal state of the TW core functions and the effect of any macros that may have modified or extended the TW program operating environment. Key values that sysInfo can display includes:\n*''options'' include default values hard-coded into TW, persistent local options stored in cookies, and plugin configuration options defined in systemConfig tiddlers.\n*''messages'' include built-in error text and custom-defined messages from plugins.\n*''shadows'' includes all built-in 'shadow tiddlers'.\n*''styles'' include default hard-coded CSS definitions, custom StyleSheet tiddlers, and plugin-defined styles.\n*''notify'' lists built-in or plugin-defined functions that are triggered whenever changes to tiddlers are made.\n*''macros'' include built-in and plugin-defined handlers for program functions that can be embedded and displayed within tiddler content.\n\n''{{{<<sysConfig options|messages>>}}}''\n\nThe ''sysConfig'' macro generates a form that lets you manually create or update browser cookies that can override ANY of the values currently defined in the config.options[...] array, even if those settings are not normally made visible to the TW user. sysConfig can also be used to display a list of all message text definitions, using a simple "id=text" format.\n\n''{{{<<DOMViewer rows:nn indent:xxxx inline path elementID|tiddlertitle>>}}}''\n\nWhenever TiddlyWiki renders a given tiddler, it creates a 'tree' of DOM (Document Object Model) elements that represent the information that is displayed by the browser. You can use the ''DOMViewer'' macro to examine the internal DOM elements that are produced by TiddlyWiki's formatter (the 'wikifier'), or elements directly produced by embedded macros that create custom formatted output. This can be particularly helpful when trying to fine tune the layout and appearance of your tiddler content.\n\nDOMViewer creates a textarea control and reports the DOM tree for the current 'insertion point' where the DOMViewer macro is being placed. ''inline'' flag uses TiddlyWiki rendering instead of textarea control. ''path'' shows the relative location of each child element in the DOM tree, using subscript notation, ''[elementID or tiddlertitle]'' displays DOM elements starting from the node with the specified ID. If that ID is not found in the DOM tree, the macro attempts to open a tiddler with that title and then displays the "tiddler"+title DOM elements that were rendered.\n<<<\n!!!!!Examples\n<<<\nTiddlyWiki current operating values, styles, and function definitions:\n<<sysInfo options messages shadows styles notify macros>>\n''[[ToolkitExample:DOMViewer]]''\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document\n(each tagged with <<tag systemConfig>>):\n''[[ToolkitPlugin]]''\n^^documentation and javascript for Toolkit macro handling^^\n<<<\n!!!!!Revision History\n<<<\n''2006.02.17 [2.0.1]''\nFF1501 fix: "var theTextArea"\n''2006.01.01 [2.0.0]''\nupdate for TW2.0\n''2005.10.09 [1.0.2]''\ndocumentation and code cleanup only.\n''2005.09.29 [1.0.1]''\ndocumentation and code cleanup only.\nmerged separate Toolkit:* code tiddlers into one tiddler for easier distribution\n''2005.09.27 [1.0.0]''\nInitial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].\n<<<\n!!!!!Code\n***/\n// // 1.2.x compatibility\n//{{{\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n// // ''{{{<<sysInfo options|messages|shadows|styles|notify|macros>>}}}''\n//{{{\nversion.extensions.sysInfo = {major: 2, minor: 0, revision: 1, date: new Date(2006,2,17)};\n\nconfig.macros.sysInfo = { };\nconfig.macros.sysInfo.handler = function(place,macroName,params) {\n // OPTIONS\n if (!params[0]||(params.find("options")!=null)) {\n var theOptList=createTiddlyElement(place,"select");\n var c=0;\n theOptList.options[c++]=new Option("options...","",false,false);\n var cookies = { };\n if (document.cookie != "") {\n var p = document.cookie.split("; ");\n for (var i=0; i < p.length; i++) {\n var pos=p[i].indexOf("=")\n if (pos==-1)\n cookies[p[i]]="";\n else\n cookies[p[i].substr(0,pos)]=unescape(p[i].slice(pos+1));\n }\n }\n var opt=new Array(); for (var i in config.options) opt.push(i); opt.sort();\n for(var i=0; i < opt.length; i++) {\n var txt = opt[i];\n var val = "config.options."+txt+"\sn"+config.options[opt[i]];\n if (cookies[opt[i]]) txt += " [cookie]";\n theOptList.options[c++]=new Option(txt,val,false,false);\n }\n }\n // MESSAGES\n if (!params[0]||(params.find("messages")!=null)) {\n var theMsgList=createTiddlyElement(place,"select");\n var c=0;\n theMsgList.options[c++]=new Option("messages...","",false,false);\n var msgs=new Array(); for (var i in config.messages) msgs.push(i); msgs.sort();\n for(var i=0; i < msgs.length; i++) {\n var txt = msgs[i];\n var val = "config.messages."+txt+"\sn"+config.messages[msgs[i]];\n theMsgList.options[c++]=new Option(txt,val,false,false);\n }\n }\n // SHADOWS\n if (!params[0]||(params.find("shadows")!=null)) {\n var theShadowList=createTiddlyElement(place,"select");\n var c=0;\n theShadowList.options[c++]=new Option("shadows...","",false,false);\n var shadows=new Array(); for (var i in config.shadowTiddlers) shadows.push(i); shadows.sort();\n for(var i=0; i < shadows.length; i++) {\n var txt = shadows[i];\n var val = "config.shadowTiddlers."+txt+"\sn"+config.shadowTiddlers[shadows[i]];\n theShadowList.options[c++]=new Option(txt,val,false,false);\n }\n }\n // STYLES\n if (!params[0]||(params.find("styles")!=null)) {\n var theStyleList=createTiddlyElement(place,"select");\n var c=0;\n theStyleList.options[c++]=new Option("stylesheets...","",false,false);\n var styles=document.getElementsByTagName("style");\n for(var i=0; i < styles.length; i++) {\n var id=styles[i].getAttribute("id"); if (!id) id="(default)";\n var txt=id;\n var val="/* stylesheet:"+txt+" */\sn"+styles[i].innerHTML;\n theStyleList.options[c++]=new Option(txt,val,false,false);\n }\n }\n // NOTIFY\n if (!params[0]||(params.find("notify")!=null)) {\n var theNotifyList=createTiddlyElement(place,"select");\n var c=0;\n theNotifyList.options[c++]=new Option("notifications...","",false,false);\n for (var i=0; i<store.namedNotifications.length; i++) {\n var n = store.namedNotifications[i];\n var fn = n.notify.toString();\n fn = fn.substring(fn.indexOf("function ")+9,fn.indexOf("{")-1);\n var txt=(n.name?n.name:"any change")+"="+fn;\n var val="/* notify: "+txt+" */"+n.notify.toString();\n theNotifyList.options[c++]=new Option(txt,val,false,false);\n }\n }\n // MACROS\n if (!params[0]||(params.find("macros")!=null)) {\n var theMacroList=createTiddlyElement(place,"select");\n var c=0;\n theMacroList.options[c++]=new Option("macro handlers...","",false,false);\n var macros=new Array();\n for (var m in config.macros) macros.push(m);\n macros.sort();\n for(var i=0; i < macros.length; i++) {\n if (config.macros[macros[i]].handler) {\n var txt=macros[i];\n var val="/* macro:"+txt+" */"+config.macros[macros[i]].handler.toString();\n theMacroList.options[c++]=new Option(txt,val,false,false);\n }\n }\n }\n // TEXTAREA DISPLAY\n var theTextArea=createTiddlyElement(place,"textarea");\n theTextArea.rows=10;\n theTextArea.cols=60;\n theTextArea.style.width="100%";\n theTextArea.style.fontSize="8pt";\n var num=!params[0]?6:params.length; var pct=100/num+"%";\n if (theOptList) {\n theOptList.textarea=theTextArea;\n theOptList.onchange=function() { this.textarea.value=this.value; }\n theOptList.style.fontSize="8pt"; theOptList.style.width=pct;\n }\n if (theMsgList) {\n theMsgList.textarea=theTextArea;\n theMsgList.onchange=function() { this.textarea.value=this.value; }\n theMsgList.style.fontSize="8pt"; theMsgList.style.width=pct;\n }\n if (theShadowList) {\n theShadowList.textarea=theTextArea;\n theShadowList.onchange=function() { this.textarea.value=this.value; }\n theShadowList.style.fontSize="8pt"; theShadowList.style.width=pct;\n }\n if (theStyleList) {\n theStyleList.textarea=theTextArea;\n theStyleList.onchange=function() { this.textarea.value=this.value; }\n theStyleList.style.fontSize="8pt"; theStyleList.style.width=pct;\n }\n if (theNotifyList) {\n theNotifyList.textarea=theTextArea;\n theNotifyList.onchange=function() { this.textarea.value=this.value; }\n theNotifyList.style.fontSize="8pt"; theNotifyList.style.width=pct;\n }\n if (theMacroList) {\n theMacroList.textarea=theTextArea;\n theMacroList.onchange=function() { this.textarea.value=this.value; }\n theMacroList.style.fontSize="8pt"; theMacroList.style.width=pct;\n }\n}\n//}}}\n// // ''{{{<<sysConfig options|messages>>}}}''\n//{{{\nversion.extensions.sysConfig= {major: 2, minor: 0, revision: 0, date: new Date(2006,1,1)};\nconfig.macros.sysConfig = { };\nconfig.macros.sysConfig.handler = function(place,macroName,params) {\n // OPTIONS\n if (!params[0]||(params.find("options")!=null)) {\n var out="";\n var options=new Array(); for (var i in config.options) options.push(i); options.sort();\n for(var i=0; i < options.length; i++)\n if ((options[i].substr(0,3)=="txt")||(options[i].substr(0,3)=="chk"))\n out += "<<option "+options[i]+">> "+options[i]+"\sn";\n else\n out += options[i]+"="+config.options[options[i]]+"\sn";\n }\n // MESSAGES\n if (!params[0]||(params.find("messages")!=null)) {\n var out="";\n var msgs=new Array(); for (var i in config.messages) msgs.push(i); msgs.sort();\n for(var i=0; i < msgs.length; i++)\n out += msgs[i]+"="+config.messages[msgs[i]]+"\sn";\n }\n if (out.length>0) wikify(out,place);\n}\n//}}}\n// // ''{{{<<DOMViewer rows:nn indent:xxxx inline path elementID|tiddlertitle>>}}}''\n//{{{\nversion.extensions.DOMViewer = {major: 2, minor: 0, revision: 0, date: new Date(2006,1,1)};\nconfig.macros.DOMViewer = { };\nconfig.macros.DOMViewer.handler = function(place,macroName,params) {\n // set default params\n var inline=false;\n var theRows=15;\n var theIndent="| ";\n var showPath=false;\n var theTarget=place;\n // unpack options parameters\n if (params[0]=='inline') { inline=true; theIndent=">"; params.shift(); } \n if (params[0]&&(params[0].substr(0,7)=="indent:")) { theIndent=params[0].substr(7); params.shift(); } \n if (params[0]&&(params[0].substr(0,5)=="rows:")) { theRows=params[0].substr(5); params.shift(); } \n if (params[0]=='path') { showPath=true; params.shift(); } \n if (params[0]) {\n theTarget=document.getElementById(params[0]);\n if (!theTarget)\n if (store.getTiddler(params[0])!=undefined) {\n theTarget=document.getElementById("tiddler"+params[0]);\n if (!theTarget && confirm("DOMViewer asks:\sn\snIs it OK to open tiddler '"+params[0]+"' now?")) { \n story.displayTiddler(null,params[0],1,null,null,false);\n theTarget=document.getElementById("tiddler"+params[0]);\n }\n }\n params.shift();\n }\n // generate and display DOM tree\n if (inline) {\n var out=getNodeTree(theTarget,theIndent,showPath,inline);\n wikify(out,place);\n }\n else {\n var out=getNodeTree(theTarget,theIndent,showPath,inline);\n var css=".DOMViewer{width:100%;font-size:8pt;color:inherit;background:transparent;border:0px;}";\n setStylesheet(css,"DOMViewerPlugin");\n var theTextArea=createTiddlyElement(place,"textarea",null,"DOMViewer",out);\n theTextArea.rows=theRows;\n theTextArea.cols=60;\n theTextArea.wrap="off";\n theTextArea.theTarget=theTarget;\n theTextArea.theIndent=theIndent;\n theTextArea.showPath=showPath;\n }\n}\nfunction getNodeTree(theNode,theIndent,showPath,inline,thePrefix,thePath)\n{\n if (!theNode) return "";\n if (!thePrefix) thePrefix="";\n if (!thePath) thePath="";\n var mquote='"'+(inline?"{{{":"");\n var endmquote=(inline?"}}}":"")+'"';\n // generate output for this node\n var out = thePrefix;\n if (showPath && thePath.length)\n out += (inline?"//":"")+thePath.substr(1)+":"+(inline?"//":"")+"\sr\sn"+thePrefix;\n if (theNode.className=="DOMViewer")\n return out+'[DOMViewer]\sr\sn'; // avoid self-referential recursion\n out += (inline?"''":"")+theNode.nodeName.toUpperCase()+(inline?"''":"");\n if (theNode.nodeName=="#text")\n out += ' '+mquote+theNode.nodeValue.replace(/\sn/g,'\s\sn')+endmquote;\n if (theNode.className)\n out += ' class='+mquote+theNode.className+endmquote;\n if (theNode.type)\n out += ' type='+mquote+theNode.type+endmquote;\n if (theNode.id)\n out += ' id='+mquote+theNode.id+endmquote;\n if (theNode.name)\n out += " "+theNode.name+(theNode.value?"="+mquote+theNode.value+endmquote:"");\n if (theNode.href)\n out += ' href='+mquote+theNode.href+endmquote;\n if (theNode.src)\n out += ' src='+mquote+theNode.src+endmquote;\n if (theNode.attributes && theNode.getAttribute("tiddlyLink")!=undefined)\n out += ' tiddler='+mquote+theNode.getAttribute("tiddlyLink")+endmquote;\n out += "\sr\sn";\n // recursively generate output for child nodes\n thePath=thePath+"."+theNode.nodeName.toLowerCase();\n thePrefix=theIndent+thePrefix;\n for (var i=0;i<theNode.childNodes.length;i++)\n {\n var thisChild=theNode.childNodes.item(i);\n var theNum=(inline?"~~":"(")+(i+1)+(inline?"~~":")");\n out += getNodeTree(thisChild,theIndent,showPath,inline,thePrefix,thePath+theNum);\n }\n return out;\n}\n//}}}\n
''Unfiled Actions (i.e., with no project)''\n\n! Pending Actions\n<<forEachTiddler\n where\n "tiddler.tags.contains('action') && ! tiddler.tags.contains('TiddlerTemplates') && ! tiddler.tags.contains('done') && ! tiddler.tags.contains('somedayMaybe') && isNotFiled(tiddler, []) && ! tiddler.tags.contains('project') && ! tiddler.tags.contains('context')"\n sortBy \n"getSortedTagsText(tiddler,['action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;} function isNotFiled(tiddler,excludetags) { var sortedtagstext = getSortedTagsText(tiddler,excludetags); if( sortedtagstext != "" ) { return ! sortedtagstext.contains("!"); } return false; }'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['action']) ? ' (' + getSortedTagsText(tiddler, ['action']) + ')' : '' ) + '\sn'"\n>>\n! Done Actions\n<<forEachTiddler\n where\n "tiddler.tags.contains('action') && ! tiddler.tags.contains('TiddlerTemplates') && tiddler.tags.contains('done') && isNotFiled(tiddler, ['done']) && ! tiddler.tags.contains('project') && ! tiddler.tags.contains('context')"\n sortBy \n"getSortedTagsText(tiddler,['done','action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;} function isNotFiled(tiddler,excludetags) { var sortedtagstext = getSortedTagsText(tiddler,excludetags); if( sortedtagstext != "" ) { return ! sortedtagstext.contains("!"); } return false; }'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['done','action']) ? ' (' + getSortedTagsText(tiddler, ['done','action']) + ')' : '' ) + '\sn'"\n>>\n! Someday Maybe Actions\n<<forEachTiddler\n where\n "tiddler.tags.contains('action') && ! tiddler.tags.contains('TiddlerTemplates') && ! tiddler.tags.contains('done') && tiddler.tags.contains('somedayMaybe') && isNotFiled(tiddler, []) && ! tiddler.tags.contains('project') && ! tiddler.tags.contains('context')"\n sortBy \n"getSortedTagsText(tiddler,['somedayMaybe','action'])+'###'+tiddler.title"\n script\n 'function getSortedTagsText(tiddler,excludetags) { var tags = []; for( var i = 0; i < tiddler.tags.length; ++i ) { if( ! excludetags.contains( tiddler.tags[i] ) ) tags.push( tiddler.tags[i] ); } if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += ( i == 0 ? "" : " " ) + ( store.tiddlerExists(tags[i]) ? "[[" + tags[i] + "]]" : "\s<\s<tag " + tags[i] + "\s>\s>" );} return result;} function isNotFiled(tiddler,excludetags) { var sortedtagstext = getSortedTagsText(tiddler,excludetags); if( sortedtagstext != "" ) { return ! sortedtagstext.contains("!"); } return false; }'\n write\n "'* [[' + tiddler.title + ']]' + ( getSortedTagsText(tiddler, ['somedayMaybe','action']) ? ' (' + getSortedTagsText(tiddler, ['somedayMaybe','action']) + ')' : '' ) + '\sn'"\n>>
!!!!Simple reminders that fire on the same month/day of every year.\n*<<reminder month:1 day:1 title:"New Year's Day" >>\n*<<reminder month:2 day:2 title:"Groundhog Day" >>\n\n!!!!Offset reminders\nThese are all holidays that are specified as the Nth DAYOFWEEK in Month.\n*President's Day is the third Monday of February \n**<<reminder month:2 day:15 offsetdayofweek:1 title:"President's Day">>\n*Mother's Day is the second Sunday of May\n**<<reminder month:5 day:8 offsetdayofweek:0 title:"Mother's Day">>\n\n*Memorial Day is the last Monday of May (note that offsetdayofweek is a negative number, meaning match backwards)\n**<<reminder month:5 day:31 offsetdayofweek:-1 title:"Memorial Day">>\n\n!!!Ignore these\nThese are just here to fill in the common US holidays\n*<<reminder month:2 day:14 title:"Valentine's Day" >>\n*<<reminder month:4 day:1 title:"April Fool's Day" >>\n*<<reminder month:4 day:15 title:"Tax day">>\n*<<reminder month:4 day:22 title:"Earth Day">>\n*<<reminder month:6 day:14 title:"Flag Day" >>\n*Father's Day is the third Sunday of June \n**<<reminder month:6 day:15 offsetdayofweek:0 title:"Father's Day">>\n*<<reminder month:7 day:4 title:"Independence Day" >>\n*Labor Day is the first Monday of September\n**<<reminder month:9 day:1 offsetdayofweek:1 title:"Labor Day">>\n*Columbus Day is the second Monday of October\n**<<reminder month:10 day:8 offsetdayofweek:1 title:"Columbus Day">>\n*<<reminder month:10 day:31 title:"Halloween" >>\n*<<reminder month:11 day:11 title:"Veteran's Day" >>\n*Thanksgiving(US) is the third Thursday of November\n**<<reminder month:11 day:22 offsetdayofweek:4 title:"Thanksgiving (US)">>\n*<<reminder month:12 day:25 title:"Christmas Day" >>
/***\n''UnformattedTextPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#UnformattedTextPlugin \nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nAdd //extended quotes// around specific tiddler content to prevent any embedded formatting syntax from being processed by TiddlyWiki's rendering engine, so the content will appear exactly as entered into the tiddler (i.e., "raw text"), even when it contains character sequences that would normally be treated as TiddlyWiki formatting instructions.\n!!!!!Usage\n<<<\nWhen installed, this plugin adds new wiki syntax for surrounding tiddler content so that it can be excluded from the TiddlyWiki formatting rules when it is rendered.\n//{{{\n"""content goes here"""\n//}}}\nwhere:\n* {{{"""}}} //(three double-quote characters)//^^\nmarks the start and end of the unformatted content^^\n<<<\n!!!!!Examples\n<<<\nContent containing TiddlyWiki formatting syntax can be shown with the syntax unchanged:\n{{{\n"""this text is //not italic// and <<not a macro>> and [[not a link]]"""\n}}}\n"""this text is //not italic// and <<not a macro>> and [[not a link]]"""\n\nNote that, although formatting syntax contained ''within'' the quoted content does not affect the style of the output, any formatting syntax ''surrounding'' the quoted content will still be applied. For example, the following unformatted output will be underlined:\n{{{\n__"""this text is //not italic// and <<not a macro>> and [[not a link]], but it IS underlined"""__\n}}}\n__"""this text is //not italic// and <<not a macro>> and [[not a link]], but it IS underlined"""__\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''UnformattedTextPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2005.11.07 [1.0.0]''\ninitial release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.unformattedText = {major: 0, minor: 5, revision: 0, date: new Date(2005,11,07)};\n\nconfig.formatters.push( {\n name: "rawText",\n match: "\s\s\s"{3}",\n lookahead: "\s\s\s"{3}((?:.|\s\sn)*?)\s\s\s"{3}",\n handler: function(w)\n {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n var e = createTiddlyElement(w.output,"span",null,null,lookaheadMatch[1]);\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n }\n)\n//}}}
Supscribe to the GTDTW RSS newfeed at http://shared.snapgrid.com/feed/gtdtw.xml to be notified of official releases.
Get all this tiddler simply using EricShulman's ImportTiddlersPlugin and selecting all tiddlers tagged [[Upload]].\n\n[[Upload]] is <<tagging Upload>>
This form is provided for uploading any file with the store.php script describe in UploadPlugin\n----\n<html><center>\n<form enctype="multipart/form-data" action="http://web.bidix.info/TiddlyWiki/store2.php" method="post">\n <input type="hidden" name="MAX_FILE_SIZE" value="3000000" />\nThis file : <input name="userfile" type="file" /><p>\nOptions* : <input type="text" name="UploadPlugin" size=70 value="backupDir=backupDir;user=UPLOAD_USER;password=UPLOAD_PASSWORD;" /><p>\n <input type="submit" value="Upload" />\n</form></center>\n</html>\n----\n * Don't save your real username and password in any tiddler
|!Date|!url|!toFilename|!backupDir|!user|!status|
!Options used by UploadPlugin\nUsername : <<option txtUploadUserName>>\nPassword : <<option pasUploadPassword>>\n\nUrl of the [[store.php]] script^^(1)^^ : <<option txtUploadStoreUrl>>\nFilename of the uploaded file^^(2)^^ : <<option txtUploadFilename>>\nDirectory to backup file on webserver^^(3)^^ : <<option txtUploadBackupDir>>\n\n^^(1)^^Mandatory either in UploadOptions or in MacroParameter\n^^(2)^^If omitted take the actual filename\n^^(3)^^If omitted existing file with same name on webserver will be overwriten\n\n!Macro\n{{{<<upload [[UploadStoreUrl]}}}^^(1)^^{{{ [UploadFilename] [UploadBackupDir]]>>}}}\n\n<<upload>>
/***\n\n\n----\nUploadPlugin, with [[store.php]], provides @@upload@@ and @@save to web@@ functions. See [[HowToUpload|http://TiddlyWiki.bidix.info/#HowToUpload]].\nUploadPlugin uses Username and Password from UploadOptions stored in cookies to authenticate itself to [[store.php]].\nThe french translation available as a separate tiddler UploadPluginMsgFR\n----\n\n\n***/\n\n/***\n|''Name:''|UploadPlugin|\n|''Type:''|Plugin|\n|''Version:''|3.2.3 (25/02/2006)|\n|''Source:''|[[TiddlyWiki.BidiX.info/#UploadPlugin|http://tiddlywiki.BidiX.info/#UploadPlugin]]|\n|''Author:''|BidiX[at]BidiX.info|\n|''Compatibility:''|TW1.2 & TW2 & FF1.5.0.1|\n!Usage : \n{{{\n<<upload>>\n uses UploadOptions saved in cookies :\n txtUploadUserName: username\n pasUploadPassword : password\n txtUploadStoreUrl : store script\n txtUploadDir : upload directory\n txtUploadFilename : upload filename\n txtUploadBackupDir : backup directory\n\n<<upload [storeUrl [toFilename [backupDir]]]>>\n overwrite UploadOptions\n storeUrl : the url of the store.php to upload the TiddlyWiki\n toFilename : the filename in the storeUrl directory\n backupDir : if present backup the previous toFilename file\n to the backupDir directory\n}}}\n\nInstall the {{{<<upload ... >>}}} macro in SideBarOptions just below {{{<<saveChanges>>}}} macro.\n\n!Description\n!!UploadPlugin\n*If the TiddlyWiki is viewed from @@local disk@@ :\n**{{{<<saveChanges>>}}} \n***display as ''save to disk''\n***work as usual\n**{{{<<upload>>}}}\n***display as ''upload''\n***after saving to disk, upload in the storeUrl directory.\n*If the TiddlyWiki is viewed from @@website@@ :\n**{{{<<saveChanges>>}}} \n***print nothing\n***has been disabled\n**{{{<<upload>>}}}\n***display as '''save to web''\n***save in the storeUrl directory.\n*If GenerateAnRssFeed in AdvancedOptions is set :\n**generate the content of the RSSFeed \n**upload the RssFile in the same directory\n**Caution : use the SiteUrl tiddler to specify the right url of the TiddlyWiki in the generated RssFile\n*DisplayMessage\n*Log upload action in UploadLog\nhint : if UploadLog is the first tiddler in the Timeline Tab, no tiddler has been updated since last upload.\n\n!![[store.php]]\n*UserVariables to set :\n//{{{\n$AUTHENTICATE_USER = true; // true | false\n$USERS = array(\n 'UserName1'=>'Password1', \n 'UserName2'=>'Password2', \n 'UserName3'=>'Password3'); // set usernames and strong passwords\n$DEBUG = false; // true | false\n//}}}\n*method GET\n**display an information page\n*method POST\n**if $~AUTHENTICATE_USER is ''true''\n***presence and value of user and password are checked with $USER and $PASSWORD \n**if toFilename already exists and backDir parameter specified\n***rename toFilename to backupDir/toFilename.AAAAMMDD.HHSS.html\n**copy temporaryUploadedFile to toFilename\n** return status\n\n!User manual\nSee HowToUpload\n\n!Installation :\n*Install the UploadPlugin as usual\n*Upload the [[store.php]] file on your php aware webserver in your TiddlyWiki directory\n*Protect against malicious upload. Two approaches :\n**set $~AUTHENTICATE_USER to true in the [[store.php]] script\n***configure $USER and $PASSWORD in the [[store.php]] script on your webserver\n***set UploadOptions in conformity with [[store.php]]\n**Use server protection :\n***for Apache web server ([[for detail see Apache documentation|http://httpd.apache.org/docs/1.3/howto/htaccess.html]]) : \n****configure and upload the [[.htaccess]] [[.passwd]]\n***for other web servers see the appropriate documentation\n*Configure an upload button, for example in the SideBarOptions\n!Suppported Browser\n*Firefox : tested Ok\n*Internet Explorer : tested Ok\n*Safari : reported ok on OS X\n*Others : Not tested, please report status.\n\n!Revision history\n*V3.2.3 (25/02/2006)\n**Rename getLocalPath in config.macros.upload.getLocalPath\n*V3.2.2 (25/02/2006)\n**Use PasswordTweak 1.0.1\n**uploaddir is a relative path\n**backupdir is a relative path\n+++!![previous versions]\n*V3.2.1 (13/02/2006)\n**name and password added to open.request (Thanks to TedPavlic)\n*V3.2.0 (14/02/2006)\n**Use PassworDTweak (http://tiddlyWiki.bidix.info/#PasswordTweak) for password\n*V3.1.0 (12/02/2006)\n**UploadOptions in Cookies\n**Username and password from UploadOptions pass to store.php script for authentification check\n*V3.0.3 (03/02/2006)\n**Firefox 1.5.0.1 crashes due to global var fixed\n*V3.0.2 (25-Jan-2006)\n**HTTPS compatible\n*V3.0.1 (18-Jan-2006)\n**UTF8toUnicode conversion problem in Firefox\n*V3.0.0 (15-Jan-2006)\n**Asynchronous upload\n**Synchronous upload before unload of the page\n**All strings extracted in macro config\n**Compatibility checked with TW 2.0.2 & TW 1.2.39 for both FF 1.5 and IE 6\n*V2.0.2 (8-Jan-2006)\n**conversion of SiteTitle and SiteSubtitle in web page Title\n*V2.0.1 (8-Jan-2006)\n**Compatibilty with TiddlyWiki 2.0.1\n*V2.0.0 (3-Jan-2006)\n**Save to web\n**Compatibilty with TiddlyWiki 1.2.39 and TiddlyWiki 2.0.0 Beta 6\n*v1.1.0 (27-Dec-2005)\n**Upload RSS File\n*v1.0.3 (26-Dec-2005)\n**UploadLog tiddler\n*v1.0.2 (24-Dec-2005)\n**Optional parameter toFilename\n**Optional parameter backupDir\n*v1.0.1 (23-Dec-2005)\n**reformatting code\n* v1.0.0 (17-Dec-2005)\n** first public working version\n===\n\n\n!Code\n***/\n//{{{\nversion.extensions.UploadPlugin = {major: 3, minor: 2, revision: 3, date: new Date(2006,2,25)};\n//}}}\n/***\n!! Macro definition\n***/\n//{{{\nconfig.macros.upload = {\n accessKey: "U",\n formName: "UploadPlugin",\n contentType: "text/html;charset=UTF-8",\n defaultStoreScript: "store.php"\n};\n\n// only this two configs need to be translated\nconfig.macros.upload.messages = {\n aboutToUpload: "About to upload TiddlyWiki to %0",\n errorDownloading: "Error downloading",\n errorUploadingContent: "Error uploading content",\n fileNotFound: "file to upload not found",\n fileNotUploaded: "File %0 NOT uploaded",\n mainFileUploaded: "Main TiddlyWiki file uploaded to %0",\n urlParamMissing: "url param missing",\n rssFileNotUploaded: "RssFile %0 NOT uploaded",\n rssFileUploaded: "Rss File uploaded to %0"\n};\n\nconfig.macros.upload.label = {\n promptOption: "Save and Upload this TiddlyWiki with UploadOptions",\n promptParamMacro: "Save and Upload this TiddlyWiki in %0",\n saveLabel: "save to web", \n saveToDisk: "save to disk",\n uploadLabel: "upload" \n};\n\nconfig.macros.upload.handler = function(place,macroName,params){\n var storeUrl;\n if (params[0]) {\n storeUrl = params[0];\n this.defaultStoreScript = basename(storeUrl);\n }\n var toFilename=params[1];\n var backupDir=params[2];\n var label;\n if (document.location.toString().substr(0,4) == "http")\n label = this.label.saveLabel;\n else\n label = this.label.uploadLabel;\n var prompt;\n if (storeUrl) {\n prompt = this.label.promptParamMacro.toString().format([dirname(storeUrl)]);\n }\n else {\n prompt = this.label.promptOption;\n }\n createTiddlyButton(place, label, prompt, \n function () {upload(storeUrl, toFilename, backupDir, true); return false;}, \n null, null, this.accessKey);\n};\n//}}}\n/***\n!! UploadOPtions stored in cookies\n***/\n//{{{\nconfig.options.txtUploadStoreUrl = 'UploadStoreUrl';\nconfig.options.txtUploadFilename = 'UploadFilename ';\nconfig.options.txtUploadDir = '';\nconfig.options.txtUploadBackupDir = 'UploadBackupDir ';\nconfig.options.txtUploadUserName = config.options.txtUserName;\nconfig.options.pasUploadPassword = 'UploadPassword ';\n//We have to reload Cookies because options are loaded before systemConfigs\nloadOptionsCookie();\n//}}}\n/***\n!!Core tweaks\n***/\n//{{{\n// overwrite the saveChanges handler \n// configure no Macro instead of saveChanges Macro in case of http: access\nconfig.macros.saveChanges.label = config.macros.upload.label.saveToDisk;\nconfig.macros.saveChanges.handler = function(place,macroName,params)\n{\n if(!readOnly) {\n if (document.location.toString().substr(0,4) != "http") \n createTiddlyButton(place,this.label,this.prompt,function () {saveChanges(); return false;},null,null,this.accessKey);\n // else no TiddlyButton\n }\n};\n\n// Check if there is any unsaved changes before exiting\n// if unsaved changes : saveOrUpload\n//function checkUnsavedChanges()\ncheckUnsavedChanges = function ()\n{\n if(store && store.dirty) {\n if(confirm(config.messages.unsavedChangesWarning))\n saveOrUpload(false); // Because called by <body onunload=... Upload must be synchronous\n }\n};\n\n// saveOrUpload\nfunction saveOrUpload(asynchronous) {\n if (document.location.toString().substr(0,4) == "http") {\n // try a default synchronous upload\n var url = dirname(document.location.toString())+"/"+ config.macros.upload.defaultStoreScript;\n upload(url, null, null, asynchronous);\n }\n else \n saveChanges();\n}\n\n//}}}\n/***\n!!Utility functions \n***/\n//{{{\nfunction dirname(filePath)\n{\n var lastpos;\n if ((lastpos = filePath.lastIndexOf("/")) != -1) {\n return filePath.substring(0, lastpos);\n }\n else\n return filePath.substring(0, filePath.lastIndexOf("\s\s"));\n}\n\nfunction basename(filePath)\n{\n var lastpos;\n if ((lastpos = filePath.lastIndexOf("#")) != -1) \n filePath = filePath.substring(0, lastpos);\n if ((lastpos = filePath.lastIndexOf("/")) != -1) {\n return filePath.substring(lastpos + 1);\n }\n else\n return filePath.substring(filePath.lastIndexOf("\s\s")+1);\n}\n\n// TiddlyWiki utilities\n\n config.macros.upload.getLocalPath = function() {\n //extract from the Jeremy's SaveFile \n var originalPath = document.location.toString();\n // Check we were loaded from a file URL\n if(originalPath.substr(0,5) != "file:")\n {\n alert(config.messages.notFileUrlError);\n displayTiddler(null,"SaveChanges",0,null,null,false,false);\n return;\n }\n // Remove any location part of the URL\n var hashPos = originalPath.indexOf("#");\n if(hashPos != -1)\n originalPath = originalPath.substr(0,hashPos);\n // Convert to a native file format assuming\n // "file:///x:/path/path/path..." - pc local file --> "x:\spath\spath\spath..."\n // "file://///server/share/path/path/path..." - FireFox pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n // "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."\n // "file://server/share/path/path/path..." - pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n var localPath;\n if(originalPath.charAt(9) == ":") // pc local file\n localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file:///") === 0) // mac/unix local file\n localPath = unescape(originalPath.substr(7));\n else if(originalPath.indexOf("file:/") === 0) // mac/unix local file\n localPath = unescape(originalPath.substr(5));\n else // pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\s\s");\n return localPath;\n}\n\n//}}}\n/***\n!! UploadLog \n***/\n//{{{\n\nfunction getUploadLogTiddler() {\n var tiddler;\n if (version.major < 2)\n tiddler = store.tiddlers['UploadLog'];\n else\n tiddler = store.getTiddler("UploadLog");\n if (!tiddler) \n {\n tiddler = new Tiddler();\n tiddler.title = 'UploadLog';\n tiddler.text = "|!Date|!url|!toFilename|!backupDir|!user|!status|";\n if (version.major < 2)\n store.tiddlers['UploadLog'] = tiddler;\n else\n store.addTiddler(tiddler);\n }\n return tiddler;\n}\n\nfunction uploadLog(url, toFilename, backupDir) \n{\n var tiddler = getUploadLogTiddler();\n var now = new Date();\n var newText = "| ";\n //newText += now.toLocaleString() + " | ";\n \n newText += now.getDate()+"/"+(now.getMonth()+1)+"/"+now.getFullYear() + " ";\n newText += now.getHours()+":"+now.getMinutes()+":"+now.getSeconds()+" | ";\n newText += "[["+basename(url)+"|"+url + "]] | ";\n if (config.options.txtUploadDir) {\n toFilename = config.options.txtUploadDir + "/" + basename(toFilename);\n } else {\n toFilename = basename(toFilename);\n }\n newText += "[[" + basename(toFilename) + "|" + dirname(url)+ "/" + toFilename + "]] | ";\n newText += backupDir + " | ";\n newText += config.options.txtUserName + " |";\n\n tiddler.text = tiddler.text + "\sn" + newText;\n tiddler.modifier = config.options.txtUserName;\n tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers['UploadLog'] = tiddler;\n else\n store.addTiddler(tiddler);\n //displayTiddler(document.getElementById('sidebar'),"UploadLog",1,null,null,false);\n if (version.major < 2)\n store.notifyAll();\n}\n\nfunction uploadLogStatusOk() \n{\n var tiddler = getUploadLogTiddler();\n var newText = " ok |";\n tiddler.text = tiddler.text + newText;\n tiddler.modifier = config.options.txtUserName;\n tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers['UploadLog'] = tiddler;\n else\n store.addTiddler(tiddler);\n //displayTiddler(document.getElementById('sidebar'),"UploadLog",1,null,null,false);\n if (version.major < 2)\n store.notifyAll();\n store.notify('UploadLog',true);\n}\n\n//}}}\n\n/***\n!! download file before uploading it\n***/\n//{{{\n\nfunction download(uploadUrl, uploadToFilename, uploadBackupDir, asynchronous) {\n var request;\n try {\n request = new XMLHttpRequest();\n } \n catch (e) { \n request = new ActiveXObject("Msxml2.XMLHTTP"); \n }\n try {\n if (uploadUrl.substr(0,4) == "http") {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n }\n else {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n }\n } catch (e) { }\n\n request.open("GET",document.location.toString(), asynchronous, config.options.txtUploadUserName,\nconfig.options.pasUploadPassword);\n if (asynchronous) {\n request.onreadystatechange = function () {\n if (request.readyState == 4) {\n if(request.status == 200) {\n uploadChangesFrom(uploadUrl, uploadToFilename, uploadBackupDir, request.responseText, asynchronous);\n }\n else\n alert(config.macros.upload.messages.errorDownloading.format([document.location.toString()]));\n }\n };\n }\n request.send(null);\n if (! asynchronous) {\n if(request.status == 200) {\n uploadChangesFrom(uploadUrl, uploadToFilename, uploadBackupDir, request.responseText, asynchronous);\n }\n else\n alert(config.macros.upload.messages.errorDownloading.format([document.location.toString()]));\n }\n\n}\n\n//}}}\n\n/***\n!! Upload functions\n***/\n//{{{\n\nfunction upload(url, toFilename, backupDir, asynchronous)\n{\n clearMessage();\n // only for forcing the message to display\n if (version.major < 2)\n store.notifyAll();\n // determine good url\n if (!url) {\n url = config.options.txtUploadStoreUrl;\n }\n if ((!url) && (document.location.toString().substr(0,4) == "http")) {\n url = basename(document.location.toString())+"/"+config.macros.upload.defaultStoreScript;\n }\n if (!url) {\n alert(config.macros.upload.messages.urlParamMissing);\n return;\n }\n // backupdir\n if (!backupDir) {\n backupDir = config.options.txtUploadBackupDir;\n }\n if (!backupDir) {\n backupDir = '';\n }\n \n // UploadFilename\n var toPath;\n if (toFilename)\n toPath = toFilename;\n else {\n if (config.options.txtUploadFilename) {\n toPath = config.options.txtUploadFilename;\n }\n else {\n toPath = basename(document.location.toString());\n }\n }\n \n uploadLog(url, toPath, backupDir);\n if (document.location.toString().substr(0,5) == "file:") {\n saveChanges();\n }\n displayMessage(config.macros.upload.messages.aboutToUpload.format([dirname(url)]), dirname(url));\n uploadChanges(url, toPath, backupDir, asynchronous);\n if(config.options.chkGenerateAnRssFeed) {\n //var rssContent = convertUnicodeToUTF8(generateRss());\n var rssContent = generateRss();\n var rssPath = toPath.substr(0,toPath.lastIndexOf(".")) + ".xml";\n uploadContent(url, rssContent, rssPath, '', asynchronous, function (responseText) {\n if (responseText.substring(0,1) != 0) {\n alert(responseText);\n displayMessage(config.macros.upload.messages.rssFileNotUploaded.format([rssPath]));\n }\n else {\n if (config.options.txtUploadDir) {\n rssPath = config.options.txtUploadDir + "/" + basename(rssPath);\n } else {\n rssPath = basename(rssPath);\n }\n displayMessage(config.macros.upload.messages.rssFileUploaded.format([dirname(url)+"/"+rssPath]), dirname(url)+"/"+rssPath);\n }\n // for debugging store.php uncomment last line\n //DEBUG alert(responseText);\n }\n );\n }\n return;\n}\n\nfunction uploadChanges(url, toFilename, backupDir, asynchronous)\n{\n var original;\n if (document.location.toString().substr(0,4) == "http") {\n original = download(url, toFilename, backupDir, asynchronous);\n return;\n }\n else {\n // standard way : Local file\n original = loadFile(config.macros.upload.getLocalPath());\n if(window.Components)\n // it's a mozilla browser\n try {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]\n .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);\n converter.charset = /* The character encoding you want, using UTF-8 here */ "UTF-8";\n original = converter.ConvertToUnicode(original);\n }\n catch(e) {\n }\n }\n //DEBUG alert(original);\n uploadChangesFrom(url, toFilename, backupDir, original, asynchronous);\n}\n\nfunction uploadChangesFrom(url, toFilename, backupDir, original, asynchronous)\n{\n\n var startSaveArea = '<div id="' + 'storeArea">'; // Split up into two so that indexOf() of this source doesn't find it\n var endSaveArea = '</d' + 'iv>';\n // Locate the storeArea div's\n var posOpeningDiv = original.indexOf(startSaveArea);\n var posClosingDiv = original.lastIndexOf(endSaveArea);\n if((posOpeningDiv == -1) || (posClosingDiv == -1))\n {\n alert(config.messages.invalidFileError.format([document.location.toString()]));\n return;\n }\n // I think conversion is automatically done\n //var revised = original.substr(0,posOpeningDiv + startSaveArea.length) + \n // convertUnicodeToUTF8(allTiddlersAsHtml()) + "\sn\st\st" +\n // original.substr(posClosingDiv);\n \n var revised = original.substr(0,posOpeningDiv + startSaveArea.length) + \n allTiddlersAsHtml() + "\sn\st\st" +\n original.substr(posClosingDiv);\n\n // I think conversion is automatically done\n // var newSiteTitle = convertUnicodeToUTF8((getElementText("siteTitle") + " - " + getElementText("siteSubtitle")).htmlEncode());\n var newSiteTitle;\n if(version.major < 2){ //version is set in core TW code\n newSiteTitle = (getElementText("siteTitle") + " - " + getElementText("siteSubtitle")).htmlEncode();\n } else {\n newSiteTitle = (wikifyPlain ("SiteTitle") + " - " + wikifyPlain ("SiteSubtitle")).htmlEncode();\n }\n revised = revised.replace(new RegExp("<title>[^<]*</title>", "im"),"<title>"+ newSiteTitle +"</title>");\n var response = uploadContent(url, revised, toFilename, backupDir, asynchronous, function (responseText) {\n if (responseText.substring(0,1) != 0) {\n alert(responseText);\n displayMessage(config.macros.upload.messages.fileNotUploaded.format([config.macros.upload.getLocalPath()]));\n }\n else {\n if (config.options.txtUploadDir) {\n toFilename = config.options.txtUploadDir + "/" + basename(toFilename);\n } else {\n toFilename = basename(toFilename);\n }\n displayMessage(config.macros.upload.messages.mainFileUploaded.format([dirname(url)+"/"+toFilename]), dirname(url)+"/"+toFilename);\n uploadLogStatusOk();\n store.setDirty(false);\n }\n // for debugging store.php uncomment last line\n //DEBUG alert(responseText);\n }\n );\n}\n\nfunction uploadContent(url, content, toPath, backupDir, asynchronous, callbackFn) {\n var boundary = "---------------------------"+"AaB03x";\n //Create XMLHttpRequest Object\n var request;\n try {\n request = new XMLHttpRequest();\n } \n catch (e) { \n request = new ActiveXObject("Msxml2.XMLHTTP"); \n }\n try {\n // Needed for Mozilla if local file tries to access an http URL\n if (document.location.toString().substr(0,4) == "http") {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n }\n else {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n }\n } catch (e) { }\n \n //DEBUG alert("user["+config.options.txtUploadUserName+"] password[" + config.options.pasUploadPassword + "]");\n // compose headers data\n var sheader = "\sr\sn";\n sheader += "--" + boundary + "\sr\snContent-disposition: form-data;name=\s"" + config.macros.upload.formName +"\s"\sr\sn\sr\sn";\n sheader += "backupDir="+backupDir\n +";user=" + config.options.txtUploadUserName \n +";password=" + config.options.pasUploadPassword\n +";uploaddir=" + config.options.txtUploadDir\n + ";;\sr\sn"; \n sheader += "\sr\sn" + "--" + boundary + "\sr\sn";\n sheader += "Content-disposition: form-data;name=\s"userfile\s";filename=\s""+toPath+"\s"\sr\sn";\n sheader += "Content-Type: " + config.macros.upload.contentType + "\sr\sn";\n sheader += "Content-Length: " + content.length + "\sr\sn\sr\sn";\n // compose trailer data\n var strailer = new String();\n strailer = "\sr\sn--" + boundary + "--\sr\sn";\n var data;\n data = sheader + content + strailer;\n request.open("POST",url,asynchronous, config.options.txtUploadUserName, config.options.pasUploadPassword);\n if (asynchronous) {\n request.onreadystatechange = function () {\n if (request.readyState == 4) {\n if(request.status == 200)\n callbackFn(request.responseText);\n else\n alert(config.macros.upload.messages.errorUploadingContent);\n }\n };\n }\n request.setRequestHeader("Content-Length",data.length);\n request.setRequestHeader("Content-Type","multipart/form-data; boundary="+boundary);\n request.send(data); \n if (! asynchronous) {\n if(request.status == 200)\n callbackFn(request.responseText);\n else\n alert(config.macros.upload.messages.errorUploadingContent);\n }\n\n}\n\n//}}}\n\n/***\n\n\n----\nPasswordTweak implements the PasswordOption\n----\n\n\n***/\n/***\n|''Name:''|PasswordTweak|\n|''Type:''|tweak|\n|''Version:''|1.0.1 (22/02/2006)|\n|''Source:''|[[TiddlyWiki.BidiX.info/#PasswordTweak|http://tiddlywiki.BidiX.info/#PasswordTweak]]|\n|''Author:''|BidiX[at]BidiX.info|\n|''Compatibility:''|TW1.2 & TW2 & FF1.5.0.1|\n!Description\n*a password option has {{{pas}}} as prefix\n*in a tiddler the {{{<<option pasXXXX>>}}} provide a password input field a checkbox and a text ("Save this password on this computer")\n*when the password field changes ''or'' the checkbox changes the password is saved in a cookie, but only when the associated checkbox is checked\n*config.options.pasPassword is defined for general use. You could put it in OptionsPanel\n*add an optional size parameter for a txt or a pas option (size in characters) .\n!Exemple\n''Password : '' <<option pasPassword>>\n\n!Usage \n{{{\n<<option <prefix><Rest> [size]>>\n*prefix : \n** txt : texte option type\n**pas : password option type\n**chk : checkbox option type\n*Rest : rest of the name of the option\n*size : optional size of the txt or password input field in character\n}}}\n\n!Revision history\n*V1.0.1 (22/02/2006)\n**add size parameters for txt and pas options\n*V1.0.0 (14/02/2006)\n**Initial release\n\n***/\n/***\n!Configs\n***/\n//{{{\nconfig.messages.savePasswordCheckboxLabel = "Save this password on this computer";\nconfig.macros.option.passwordType = "password"; // password | text\n//}}}\n/***\n!option macro\n***/\n//{{{\nversion.extensions.PasswordTweak = {major: 1, minor: 0, revision: 0, date: new Date(2006,2,14)};\nconfig.macros.option.onChangeOption = function(e)\n{\n var opt = this.getAttribute("option");\n var elementType,valueField;\n if(opt) {\n switch(opt.substr(0,3)) {\n case "txt":\n elementType = "input";\n valueField = "value";\n break;\n case "pas":\n elementType = "input";\n valueField = "value";\n break;\n case "chk":\n elementType = "input";\n valueField = "checked";\n break;\n }\n config.options[opt] = this[valueField];\n saveOptionCookie(opt);\n var nodes = document.getElementsByTagName(elementType);\n for(var t=0; t<nodes.length; t++) {\n var optNode = nodes[t].getAttribute("option");\n if(opt == optNode)\n nodes[t][valueField] = this[valueField];\n }\n }\n return(true);\n}\n\nconfig.macros.option.handler = function(place,macroName,params)\n{\n var opt = params[0];\n var size = 15;\n if (params[1])\n size = params[1];\n if(config.options[opt] == undefined)\n return;\n var c;\n switch(opt.substr(0,3)) {\n case "txt":\n c = document.createElement("input");\n c.onkeyup = this.onChangeOption;\n c.setAttribute ("option",opt);\n c.size = size;\n c.value = config.options[opt];\n place.appendChild(c);\n break;\n case "pas":\n // input password\n c = document.createElement ("input");\n c.setAttribute("type",config.macros.option.passwordType);\n c.onkeyup = this.onChangeOption;\n c.setAttribute("option",opt);\n c.size = size;\n c.value = config.options[opt];\n place.appendChild(c);\n // checkbox link with this password "save this password on this computer"\n c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick = this.onChangeOption;\n c.setAttribute("option","chk"+opt);\n place.appendChild(c);\n c.checked = config.options["chk"+opt];\n // text savePasswordCheckboxLabel\n place.appendChild(document.createTextNode(config.messages.savePasswordCheckboxLabel));\n break;\n case "chk":\n c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick = this.onChangeOption;\n c.setAttribute("option",opt);\n place.appendChild(c);\n c.checked = config.options[opt];\n break;\n }\n}\n//}}}\n/***\n! Option cookie stuff\n***/\n//{{{\nwindow.loadOptionsCookie = function()\n{\n var cookies = document.cookie.split(";");\n for(var c=0; c<cookies.length; c++) {\n var p = cookies[c].indexOf("=");\n if(p != -1) {\n var name = cookies[c].substr(0,p).trim();\n var value = cookies[c].substr(p+1).trim();\n switch(name.substr(0,3)) {\n case "txt":\n config.options[name] = unescape(value);\n break;\n case "pas":\n config.options[name] = unescape(value);\n break;\n case "chk":\n config.options[name] = value == "true";\n break;\n }\n }\n }\n}\n\nwindow.saveOptionCookie = function(name)\n{\n var c = name + "=";\n switch(name.substr(0,3)) {\n case "txt":\n c += escape(config.options[name].toString());\n break;\n case "chk":\n c += config.options[name] ? "true" : "false";\n // is there an option link with this chk ?\n if (config.options[name.substr(3)]) {\n saveOptionCookie(name.substr(3));\n }\n break;\n case "pas":\n if (config.options["chk"+name]) {\n c += escape(config.options[name].toString());\n } else {\n c += "";\n }\n break;\n }\n c += "; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";\n document.cookie = c;\n}\n//}}}\n/***\n! config.options.pasPassword \n***/\n//{{{\nconfig.options.pasPassword = 'defaultPassword';\nwindow.loadOptionsCookie();\n//}}}\n
/***\n\n\n----\nUploadPluginMsgFR provides the french translation for UploadPlugin.\n----\n\n\n***/\n/***\n|''Name:''|UploadPluginMsgFR|\n|''Type:''|Translation|\n|''Version:''|UploadPlugin 3.1.x (12/02/2006)|\n|''Source:''|[[TiddlyWiki.BidiX.info|http://tiddlywiki.BidiX.info/#UploadPluginFR]]|\n|''Author:''|BidiX[at]BidiX.info|\n|''Compatibility:''|TW1.2 & TW2|\n!Usage : \nFor a french translation of UploadPlugin Message, import this tiddler in the TiddlyWiki. Make sure it is tagged with {{{systemConfig}}}. \nComments and suggestions are welcome.\n***/\n//{{{\nconfig.macros.upload.messages = {\n aboutToUpload: "Préparation du téléchargement le TiddlyWiki vers %0",\n errorDownloading: "Erreur de téléchargement de %0 depuis le serveur",\n errorUploadingContent: "Erreur de téléchargement vers le serveur du contenu",\n fileNotFound: "Fichier à télécharger vers le serveur non trouvé",\n fileNotUploaded: "Le fichier %0 N'A PAS été téléchargé vers le serveur",\n mainFileUploaded: "Le fichier TiddlyWiki a été téléchargé vers le serveur %0",\n urlParamMissing: "Paramètre URL manquant",\n rssFileNotUploaded: "Le fichier Rss %0 N'A PAS été téléchargé vers le serveur",\n rssFileUploaded: "Le fichier RSS a été téléchargé vers %0"\n};\n\nconfig.macros.upload.label = {\n promptOption: "Save and Upload this TiddlyWiki with UploadOptions",\n promptParamMacro: "Sauvegarde et télécharge ce TiddlyWiki vers %0",\n saveLabel: "sauvegarde sur le web", \n saveToDisk: "sauvegarde sur le disque",\n uploadLabel: "Télécharge vers le web"\n};\n\nconfig.macros.saveChanges.label = config.macros.upload.label.saveToDisk;\n//}}}\n
Within the main story column you can click on bold links to read a linked tiddler. Click on italic links to create a new tiddler. When you hover the mouse over a tiddler several ToolbarButtons appear. You can edit the text of any tiddler by double-clicking on it (or selecting 'edit' from the toolbar), but your changes won't get saved permanently until you make your own copy of TiddlyWiki, as described in SaveChanges.
Right click and "save as" the following links:\n[[1.0.4|/gtdtw-archive/gtdtw1.0.4.html]]\n[[1.0.3|/gtdtw-archive/gtdtw1.0.3.html]]\n[[1.0.2|/gtdtw-archive/gtdtw1.0.2.html]]\n[[1.0.1|/gtdtw-archive/gtdtw1.0.1.html]]\n[[1.0.0|/gtdtw-archive/gtdtw1.0.0.html]]
<div class='toolbar'>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged plugins toggleTag systemConfig"></span>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged groceries toggleTag hasCoupon"></span>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged groceries toggleTag onGroceryList"></span>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged project toggleTag done"></span>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged project toggleTag somedayMaybe"></span>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged action toggleTag done"></span>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged action toggleTag next"></span>\n <span style="padding-right:0.75em;" class='fakeButton' macro="runMacroIfTagged action toggleTag somedayMaybe"></span>\n <span macro='runMacroIfTagged action MatchToggleTag !Projects "Toggle a Project" "^![^ ]+$"'><span macro='runMacroIfTagged action MatchToggleTag @Contexts "Toggle a Context" "^@[^ ]+$"'><span macro='MatchToggleTag GTD "Toggle a GTD tag" "^([@!][^ ]+|action|context|done|next|project|somedayMaybe)$"'><span macro='runMacroIfTagged groceries MatchToggleTag $Groceries "Toggle a Grocery Type" "^\s$[^ ]+$"'><span macro='MatchToggleTag tags "Toggle a non-GTD or non-Grocery tag" "^([@!$][^ ]+|action|context|done|next|project|somedayMaybe|hasCoupon|onGroceryList)$" not'></span></span></span></span></span><br />\n <span macro='newFromTemplatePopup label:"new here <arrow>" tooltip:"Add a tiddler tagged with this tiddler." templateTag:"TiddlerTemplates" hereMode:"true"'></span>\n <span macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></span>\n</div>\n<div class='title' macro='view title'></div></div>\n<div class='subtitle'>by <span macro='view modifier link'></span>, <span macro='view modified date [[DD MMM YYYY]]'></span> (created <span macro='view created date [[DD MMM YYYY]]'></span>)</div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='footer' macro='tags'></div>
Putting TiddlyWiki on a USB thumb drive lets you carry around a SelfContained notebook that you can update wherever there's a reasonably modern computer, whether it's a Mac, Linux or a PC. (To be even more independent you can [[install FireFox on the drive|http://www.mozilla.org/support/firefox/tips#oth_usb]] as well).
A Wiki is a popular way of building collaborative websites. It's based on the ideas of easy editing of pages and the use of special WikiWord notation to automagically create links between pages. See Wikipedia for [[more details|http://en.wikipedia.org/wiki/Wiki]]. TiddlyWiki is different from a conventional Wiki because it is not based on entire pages of content, but rather items of MicroContent that are referred to as 'tiddlers'.
A WikiWord is a word composed of a bunch of other words slammed together with each of their first letters capitalised. WikiWord notation in a conventional WikiWikiWeb is used to name individual pages while TiddlyWiki uses WikiWord titles for smaller chunks of MicroContent. Referring to a page with a WikiWord automatically creates a link to it. Clicking on a link jumps to that page or, if it doesn't exist, to an editor to create it. This ThirdVersion of TiddlyWiki also adds NonWikiWordLinks.
I'm hoping that after using TiddlyWiki for a while a new WritingStyle will emerge that is appropriate for this medium. Jakob Neilsen wrote an article about [[writing styles|http://www.useit.com/alertbox/980906.html]] for MicroContent back in 1998 that still seems surprisingly relevant.
/***\n|''Name:''|YourSearchPlugin|\n|''Version:''|2.0.2 (2006-02-13)|\n|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|2.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n<<tiddler [[YourSearch Introduction]]>>\nFor more information see [[Help|YourSearch Help]].\n\n!Compatibility\nThis plugin requires TiddlyWiki 2.0. \nUse http://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1 for older TiddlyWiki versions.\n\n!Revision history\n* v2.0.2 (2006-02-13)\n** Bugfix for Firefox 1.5.0.1 related to the "Show prefix" checkbox. Thanks to Ted Pavlic for reporting and to BramChen for fixing. \n** Internal\n*** Make "JSLint" conform\n* v2.0.1 (2006-02-05)\n** Support "Exact Word Match" (use '=' to prefix word)\n** Support default filter settings (when no filter flags are given in search term)\n** Rework on the "less than 3 chars search text" feature (thanks to EricShulman)\n** Better support SinglePageMode when doing "Open all tiddlers" (thanks to EricShulman)\n** Support Firefox 1.5.0.1\n** Bug: Fixed a hilite bug in "classic search mode" (thanks to EricShulman)\n* v2.0.0 (2006-01-16)\n** Add User Interface\n* v1.0.1 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.0 (2005-12-28)\n** initial version\n!Code\nThe code is compressed. \n\nYou can retrieve a readable source code version from http://tiddlywiki.abego-software.de/#YourSearchPlugin-src.\n/%\n***/\nif(!version.extensions.YourSearchPlugin){version.extensions.YourSearchPlugin={major:2,minor:0,revision:2,date:new Date(2006,2,13),type:"plugin",source:"http://tiddlywiki.abego-software.de/#YourSearchPlugin"};var alertAndThrow=function(_1){alert(_1);throw _1;};if(!window.abego){window.abego={};}if(abego.YourSearch){alertAndThrow("abego.YourSearch already defined");}abego.YourSearch={};if(version.major<2){alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.0 or newer.\sn\snGet YourSearch 1.0.1 to use YourSearch with older versions of TiddlyWiki.\sn\snhttp://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1");}var STQ=function(_2,_3,_4,_5){this.queryText=_2;this.caseSensitive=_3;if(_5){this.regExp=new RegExp(_2,_3?"mg":"img");return;}this.terms=[];var re=/\ss*(\s-)?([#%!=]*)(?:(?:("(?:(?:\s\s")|[^"])*")|(\sS+)))(?:\ss+((?:[aA][nN][dD])|(?:[oO][rR]))(?!\sS))?/mg;var _7=re.exec(_2);while(_7!=null&&_7.length==6){var _8="-"==_7[1];var _9=_7[2];var _a=_9.indexOf("!")>=0;var _b=_9.indexOf("%")>=0;var _c=_9.indexOf("#")>=0;var _d=_9.indexOf("=")>=0;if(!_a&&!_b&&!_c){_a=config.options.chkSearchInTitle;_b=config.options.chkSearchInText;_c=config.options.chkSearchInTags;if(!_a&&!_b&&!_c){_a=_b=_c=true;}}if(_4){_b=false;_c=false;}var _e;if(_7[3]){try{_e=eval(_7[3]);}catch(ex){}}else{_e=_7[4];}if(!_e){throw "Invalid search expression: %0".format([_2]);}var _f=_7[5]&&_7[5].charAt(0).toLowerCase()=="o";this.terms.push(new STQ.Term(_e,_a,_b,_c,_8,_f,_3,_d));_7=re.exec(_2);}};var me=STQ.prototype;me.getMatchingTiddlers=function(_10){var _11=[];for(var i in _10){var t=_10[i];if((t instanceof Tiddler)&&this.matchesTiddler(t)){_11.push(t);}}return _11;};me.matchesTiddler=function(_14){if(this.regExp){return this.regExp.test(_14.title)||this.regExp.test(_14.text);}var n=this.terms.length;if(n==0){return false;}var _16=this.terms[0].matchesTiddler(_14);for(var i=1;i<this.terms.length;i++){if(this.terms[i-1].orFollows){if(!_16){_16|=this.terms[i].matchesTiddler(_14);}}else{if(_16){_16&=this.terms[i].matchesTiddler(_14);}}}return _16;};me.getOnlyMatchTitleQuery=function(){if(!this.onlyMatchTitleQuery){this.onlyMatchTitleQuery=new STQ(this.queryText,this.caseSensitive,true,this.useRegExp);}return this.onlyMatchTitleQuery;};me.getMarkRegExp=function(){if(this.regExp){return "".search(this.regExp)>=0?null:this.regExp;}var _18={};var n=this.terms.length;for(var i=0;i<this.terms.length;i++){var _1b=this.terms[i];if(!_1b.negate){_18[_1b.text]=true;}}var _1c=[];for(var t in _18){_1c.push("("+t.escapeRegExp()+")");}if(_1c.length==0){return null;}var _1e=_1c.join("|");return new RegExp(_1e,this.caseSensitive?"mg":"img");};me.toString=function(){if(this.regExp){return this.regExp.toString();}var _1f="";for(var i=0;i<this.terms.length;i++){_1f+=this.terms[i].toString();}return _1f;};STQ.Term=function(_21,_22,_23,_24,_25,_26,_27,_28){this.text=_21;this.inTitle=_22;this.inText=_23;this.inTag=_24;this.negate=_25;this.orFollows=_26;this.caseSensitive=_27;this.wordMatch=_28;var _29=_21.escapeRegExp();if(this.wordMatch){_29="\s\sb"+_29+"\s\sb";}this.regExp=new RegExp(_29,"m"+(_27?"":"i"));};STQ.Term.prototype.toString=function(){return (this.negate?"-":"")+(this.inTitle?"!":"")+(this.inText?"%":"")+(this.inTag?"#":"")+(this.wordMatch?"=":"")+"\s""+this.text+"\s""+(this.orFollows?" OR ":" AND ");};STQ.Term.prototype.matchesTiddler=function(_2a){if(!_2a){return false;}if(this.inTitle&&this.regExp.test(_2a.title)){return !this.negate;}if(this.inText&&this.regExp.test(_2a.text)){return !this.negate;}if(this.inTag){var _2b=_2a.tags;if(_2b){for(var i=0;i<_2b.length;i++){if(this.regExp.test(_2b[i])){return !this.negate;}}}}return this.negate;};var stringToInt=function(s,_2e){if(!s){return _2e;}var n=parseInt(s);return (n==NaN)?_2e:n;};var getIntAttribute=function(_30,_31,_32){return stringToInt(_30.getAttribute(_31));};var isDescendantOrSelf=function(_33,e){while(e!=null){if(_33==e){return true;}e=e.parentNode;}return false;};var getMatchCount=function(s,re){var m=s.match(re);return m?m.length:0;};var createEllipsis=function(_38){var e=createTiddlyElement(_38,"span");e.innerHTML="&hellip;";};var isWordChar=function(c){return (c>="a"&&c<="z")||(c>="A"&&c<="Z")||c=="_";};var getWordBounds=function(s,_3c){if(!isWordChar(s[_3c])){return null;}for(var i=_3c-1;i>=0&&isWordChar(s[i]);i--){}var _3e=i+1;var n=s.length;for(i=_3c+1;i<n&&isWordChar(s[i]);i++){}return {start:_3e,end:i};};var removeTextDecoration=function(s){var _41=["''","{{{","}}}","//","<<<","/***","***/"];var _42="";for(var i=0;i<_41.length;i++){if(i!=0){_42+="|";}_42+="("+_41[i].escapeRegExp()+")";}return s.replace(new RegExp(_42,"mg"),"").trim();};var logText="";var lastLogTime=null;var logMessage=function(_44,s){var now=new Date();var _47=lastLogTime?(now-lastLogTime).toString():"";logText+="<tr><td>"+now.convertToYYYYMMDDHHMMSSMMM()+"</td><td align='right'>"+_47+"</td><td>"+_44+"</td><td>"+s.htmlEncode()+"</td></tr>\sn";lastLogTime=now;};function writeLog(){var t=" <<JsDoIt 'WriteLog' 'WriteLog' 'javascript:writeLog();story.closeTiddler(\s"Log\s");story.displayTiddler(null,\s"Log\s");'>>"+"<html><table><tbody><tr><th>Time</th><th>Delta (ms)</th><th>Kind</th><th>Message</th></tr>\sn"+logText+"</tbody></table></html>";store.saveTiddler("Log","Log",t,config.options.txtUserName,new Date(),["System","Log"]);logText="";lastLogTime=null;}var yourSearchResultID="yourSearchResult";var yourSearchResultItemsID="yourSearchResultItems";var maxCharsInTitle=80;var maxCharsInTags=50;var maxCharsInText=250;var maxPagesInNaviBar=10;var itemsPerPageDefault=25;var itemsPerPageWithPreviewDefault=10;var minMatchWithContextSize=40;var maxMovementForWordCorrection=4;var matchInTitleWeight=4;var precisionInTitleWeight=10;var matchInTagsWeight=2;var resultElement;var lastResults;var lastQuery;var lastSearchText;var searchInputField;var searchButton;var firstIndexOnPage=0;var currentTiddler;var indexInPage;var indexInResult;var getItemsPerPage=function(){var n=(config.options.chkPreviewText)?stringToInt(config.options.txtItemsPerPageWithPreview,itemsPerPageWithPreviewDefault):stringToInt(config.options.txtItemsPerPage,itemsPerPageDefault);return (n>0)?n:1;};var standardRankFunction=function(_4a,_4b){var _4c=_4b.getMarkRegExp();if(!_4c){return 1;}var _4d=_4a.title.match(_4c);var _4e=_4d?_4d.length:0;var _4f=getMatchCount(_4a.getTags(),_4c);var _50=_4d?_4d.join("").length:0;var _51=_4a.title.length>0?_50/_4a.title.length:0;var _52=_4e*matchInTitleWeight+_4f*matchInTagsWeight+_51*precisionInTitleWeight+1;return _52;};var findMatches=function(_53,_54,_55,_56,_57,_58){lastSearchText=_54;var _59=_53.reverseLookup("tags",_58,false);var _5a=new STQ(_54,_55,false,_56);lastQuery=_5a;var _5b=_5a.getMatchingTiddlers(_59);var _5c=abego.YourSearch.getRankFunction();for(var i=0;i<_5b.length;i++){var _5e=_5b[i];var _5f=_5c(_5e,_5a);_5e.searchRank=_5f;}if(!_57){_57="title";}var _60=function(a,b){var _63=a.searchRank-b.searchRank;if(_63==0){if(a[_57]==b[_57]){return (0);}else{return (a[_57]<b[_57])?-1:+1;}}else{return (_63>0)?-1:+1;}};_5b.sort(_60);lastResults=_5b;return _5b;};var moveToWordBorder=function(s,_65,_66){var _67;if(_66){_67=getWordBounds(s,_65);}else{if(_65<=0){return _65;}_67=getWordBounds(s,_65-1);}if(!_67){return _65;}if(_66){if(_67.start>=_65-maxMovementForWordCorrection){return _67.start;}if(_67.end<=_65+maxMovementForWordCorrection){return _67.end;}}else{if(_67.end<=_65+maxMovementForWordCorrection){return _67.end;}if(_67.start>=_65-maxMovementForWordCorrection){return _67.start;}}return _65;};var getContextRangeAround=function(s,_69,_6a,_6b,_6c){var _6d=Math.max(Math.floor(_6c/(_6b+1)),minMatchWithContextSize);var _6e=Math.max(_6d-(_6a-_69),0);var _6f=Math.min(Math.floor(_6a+_6e/3),s.length);var _70=Math.max(_6f-_6d,0);_70=moveToWordBorder(s,_70,true);_6f=moveToWordBorder(s,_6f,false);return {start:_70,end:_6f};};var getTextAndMatchArray=function(s,_72){var _73=[];if(_72){var _74=0;var n=s.length;var _76=0;do{_72.lastIndex=_74;var _77=_72.exec(s);if(_77){if(_74<_77.index){var t=s.substring(_74,_77.index);_73.push({text:t});}_73.push({text:_77[0],isMatch:true});_74=_77.index+_77[0].length;}else{_73.push({text:s.substr(_74)});break;}}while(true);}else{_73.push({text:s});}return _73;};var simpleCreateLimitedTextWithMarks=function(_79,s,_7b){if(!lastQuery){return;}var _7c=getTextAndMatchArray(s,lastQuery.getMarkRegExp());var _7d=0;for(var i=0;i<_7c.length&&_7d<_7b;i++){var t=_7c[i];var _80=t.text;if(t.isMatch){createTiddlyElement(_79,"span",null,"marked",_80);}else{var _81=_7b-_7d;if(_81<_80.length){_80=_80.substring(0,_81)+"...";}createTiddlyText(_79,_80);}_7d+=_80.length;}};var addRange=function(_82,_83,_84){var n=_82.length;if(n==0){_82.push({start:_83,end:_84});return;}var i=0;for(;i<n;i++){var _87=_82[i];if(_87.start<=_84&&_83<=_87.end){var r;var _89=i+1;for(;_89<n;_89++){r=_82[_89];if(r.start>_84||_83>_87.end){break;}}var _8a=_83;var _8b=_84;for(var j=i;j<_89;j++){r=_82[j];_8a=Math.min(_8a,r.start);_8b=Math.max(_8b,r.end);}_82.splice(i,_89-i,{start:_8a,end:_8b});return;}if(_87.start>_84){break;}}_82.splice(i,0,{start:_83,end:_84});};var getTotalRangesSize=function(_8d){var _8e=0;for(var i=0;i<_8d.length;i++){var _90=_8d[i];_8e+=_90.end-_90.start;}return _8e;};var writeTextAndMatchRange=function(_91,s,_93,_94,_95){var t;var _97;var pos=0;var i=0;var _9a=0;for(;i<_93.length;i++){t=_93[i];_97=t.text;if(_94<pos+_97.length){_9a=_94-pos;break;}pos+=_97.length;}var _9b=_95-_94;for(;i<_93.length&&_9b>0;i++){t=_93[i];_97=t.text.substr(_9a);_9a=0;if(_97.length>_9b){_97=_97.substr(0,_9b);}if(t.isMatch){createTiddlyElement(_91,"span",null,"marked",_97);}else{createTiddlyText(_91,_97);}_9b-=_97.length;}if(_95<s.length){createEllipsis(_91);}};var getMatchedTextCount=function(_9c){var _9d=0;for(var i=0;i<_9c.length;i++){if(_9c[i].isMatch){_9d++;}}return _9d;};var getMatchedTextWithContextRanges=function(_9f,s,_a1){var _a2=[];var _a3=getMatchedTextCount(_9f);var pos=0;for(var i=0;i<_9f.length;i++){var t=_9f[i];var _a7=t.text;if(t.isMatch){var _a8=getContextRangeAround(s,pos,pos+_a7.length,_a3,_a1);addRange(_a2,_a8.start,_a8.end);}pos+=_a7.length;}return _a2;};var fillUpRanges=function(s,_aa,_ab){var _ac=_ab-getTotalRangesSize(_aa);while(_ac>0){if(_aa.length==0){addRange(_aa,0,moveToWordBorder(s,_ab,false));return;}else{var _ad=_aa[0];var _ae;var _af;if(_ad.start==0){_ae=_ad.end;if(_aa.length>1){_af=_aa[1].start;}else{addRange(_aa,_ae,moveToWordBorder(s,_ae+_ac,false));return;}}else{_ae=0;_af=_ad.start;}var _b0=Math.min(_af,_ae+_ac);addRange(_aa,_ae,_b0);_ac-=(_b0-_ae);}}};var writeRanges=function(_b1,s,_b3,_b4,_b5){if(_b4.length==0){return;}if(_b4[0].start>0){createEllipsis(_b1);}var _b6=_b5;for(var i=0;i<_b4.length&&_b6>0;i++){var _b8=_b4[i];var len=Math.min(_b8.end-_b8.start,_b6);writeTextAndMatchRange(_b1,s,_b3,_b8.start,_b8.start+len);_b6-=len;}};var createLimitedTextWithMarksAndContext=function(_ba,s,_bc){if(!lastQuery){return;}if(s.length<_bc){_bc=s.length;}var _bd=getTextAndMatchArray(s,lastQuery.getMarkRegExp());var _be=getMatchedTextWithContextRanges(_bd,s,_bc);fillUpRanges(s,_be,_bc);writeRanges(_ba,s,_bd,_be,_bc);};var createLimitedTextWithMarks=function(_bf,s,_c1){return createLimitedTextWithMarksAndContext(_bf,s,_c1);};var myStorySearch=function(_c2,_c3,_c4){highlightHack=new RegExp(_c4?_c2:_c2.escapeRegExp(),_c3?"mg":"img");var _c5=findMatches(store,_c2,_c3,_c4,"title","excludeSearch");firstIndexOnPage=0;showResult();highlightHack=null;};var myMacroSearchHandler=function(_c6,_c7,_c8){var _c9="";var _ca=null;var _cb=function(txt){if(config.options.chkUseYourSearch){myStorySearch(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}else{story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}_c9=txt.value;};var _cd=function(e){_cb(searchInputField);return false;};var _cf=function(e){if(!e){var e=window.event;}switch(e.keyCode){case 13:_cb(this);break;case 27:if(isResultOpen()){closeResult();}else{this.value="";clearMessage();}break;}if(String.fromCharCode(e.keyCode)==this.accessKey||e.altKey){reopenResultIfApplicable();}if(this.value.length<3&&_ca){clearTimeout(_ca);}if((this.value.length>2)&&(this.value!=_c9)){if(!config.options.chkUseYourSearch||config.options.chkSearchAsYouType){if(_ca){clearTimeout(_ca);}var txt=this;_ca=setTimeout(function(){_cb(txt);},500);}}if(this.value.length==0){closeResult();}};var _d3=function(e){this.select();reopenResultIfApplicable();};var btn=createTiddlyButton(_c6,this.label,this.prompt,_cd);var txt=createTiddlyElement(_c6,"input",null,null,null);if(_c8[0]){txt.value=_c8[0];}txt.onkeyup=_cf;txt.onfocus=_d3;txt.setAttribute("size",this.sizeTextbox);txt.setAttribute("accessKey",this.accessKey);txt.setAttribute("autocomplete","off");if(config.browser.isSafari){txt.setAttribute("type","search");txt.setAttribute("results","5");}else{txt.setAttribute("type","text");}searchInputField=txt;searchButton=btn;};var isResultOpen=function(){return resultElement!=null&&resultElement.parentNode==document.body;};var closeResult=function(){if(isResultOpen()){document.body.removeChild(resultElement);}};var openAllFoundTiddlers=function(){closeResult();if(lastResults){var _d7=[];for(var i=0;i<lastResults.length;i++){_d7.push(lastResults[i].title);}story.displayTiddlers(null,_d7);}};var refreshResult=function(){if(!resultElement||!searchInputField){return;}var _d9=store.getTiddlerText("YourSearchResultTemplate");if(!_d9){_d9="<b>Tiddler YourSearchResultTemplate not found</b>";}resultElement.innerHTML=_d9;firstIndexOnPage=Math.floor(firstIndexOnPage/getItemsPerPage())*getItemsPerPage();applyHtmlMacros(resultElement,null);refreshElements(resultElement,null);if(lastResults&&lastResults.length>0){var _da=store.getTiddlerText("YourSearchItemTemplate");if(!_da){alertAndThrow("YourSearchItemTemplate not found");}var _db=document.getElementById(yourSearchResultItemsID);if(!_db){_db=createTiddlyElement(resultElement,"div",yourSearchResultItemsID);}var _dc=Math.min(firstIndexOnPage+getItemsPerPage(),lastResults.length);indexInPage=-1;for(var i=firstIndexOnPage;i<_dc;i++){currentTiddler=lastResults[i];indexInPage++;indexInResult=i;var _de=createTiddlyElement(_db,"div",null,"yourSearchItem");_de.innerHTML=_da;applyHtmlMacros(_de,null);refreshElements(_de,null);}}currentTiddler=null;ensureResultIsDisplayedNicely();};var ensureResultIsDisplayedNicely=function(){adjustResultPositionAndSize();scrollVisible();};var scrollVisible=function(){if(resultElement){window.scrollTo(0,ensureVisible(resultElement));}if(searchInputField){window.scrollTo(0,ensureVisible(searchInputField));}};var adjustResultPositionAndSize=function(){if(!searchInputField){return;}var _df=searchInputField;var _e0=findPosX(_df);var _e1=findPosY(_df);var _e2=_df.offsetHeight;var _e3=_e0;var _e4=_e1+_e2;var _e5=findWindowWidth();if(_e5<resultElement.offsetWidth){resultElement.style.width=(_e5-100)+"px";_e5=findWindowWidth();}var _e6=resultElement.offsetWidth;if(_e3+_e6>_e5){_e3=_e5-_e6-30;}if(_e3<0){_e3=0;}resultElement.style.left=_e3+"px";resultElement.style.top=_e4+"px";resultElement.style.display="block";};var showResult=function(){if(!resultElement){resultElement=createTiddlyElement(document.body,"div",yourSearchResultID,"yourSearchResult");}else{if(resultElement.parentNode!=document.body){document.body.appendChild(resultElement);}}refreshResult();};var reopenResultIfApplicable=function(){if(searchInputField==null||!config.options.chkUseYourSearch){return;}if((searchInputField.value==lastSearchText)&&lastSearchText&&!isResultOpen()){if(resultElement&&(resultElement.parentNode!=document.body)){document.body.appendChild(resultElement);ensureResultIsDisplayedNicely();}else{showResult();}}};var setFirstIndexOnPage=function(_e7){if(!lastResults||lastResults.length==0){return;}firstIndexOnPage=Math.min(Math.max(0,_e7),lastResults.length-1);refreshResult();};var onDocumentClick=function(e){if(e.target==searchInputField){return;}if(e.target==searchButton){return;}if(resultElement&&isDescendantOrSelf(resultElement,e.target)){return;}closeResult();};var onDocumentKeyup=function(e){if(e.keyCode==27){closeResult();}};addEvent(document,"click",onDocumentClick);addEvent(document,"keyup",onDocumentKeyup);config.macros.yourSearch={label:"yourSearch",prompt:"Gives access to the current/last YourSearch result",funcs:{},tests:{"true":function(){return true;},"false":function(){return false;},"found":function(){return lastResults&&lastResults.length>0;},"previewText":function(){return config.options.chkPreviewText;}}};config.macros.yourSearch.handler=function(_ea,_eb,_ec,_ed,_ee,_ef){if(_ec.length==0){return;}var _f0=_ec[0];var _f1=config.macros.yourSearch.funcs[_f0];if(_f1){_f1(_ea,_eb,_ec,_ed,_ee,_ef);}};config.macros.yourSearch.funcs.itemRange=function(_f2){if(lastResults){var _f3=Math.min(firstIndexOnPage+getItemsPerPage(),lastResults.length);var s="%0 - %1".format([firstIndexOnPage+1,_f3]);createTiddlyText(_f2,s);}};config.macros.yourSearch.funcs.count=function(_f5){if(lastSearchText){createTiddlyText(_f5,lastResults.length.toString());}};config.macros.yourSearch.funcs.query=function(_f6){if(lastResults){createTiddlyText(_f6,lastSearchText);}};config.macros.yourSearch.funcs.version=function(_f7){var t="YourSearch %0.%1.%2".format([version.extensions.YourSearchPlugin.major,version.extensions.YourSearchPlugin.minor,version.extensions.YourSearchPlugin.revision]);var e=createTiddlyElement(_f7,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#YourSearchPlugin");e.innerHTML="<font color=\s"black\s" face=\s"Arial, Helvetica, sans-serif\s">"+t+"<font>";};config.macros.yourSearch.funcs.copyright=function(_fa){var e=createTiddlyElement(_fa,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\s"black\s" face=\s"Arial, Helvetica, sans-serif\s">&copy; 2005-2006 <b><font color=\s"red\s">abego</font></b> Software<font>";};config.macros.yourSearch.funcs.linkButton=function(_fc,_fd,_fe,_ff,_100,_101){if(_fe<2){return;}var _102=_fe[1];var text=_fe<3?_102:_fe[2];var _104=_fe<4?text:_fe[3];var _105=_fe<5?null:_fe[4];var btn=createTiddlyButton(_fc,text,_104,closeResultAndDisplayTiddler,null,null,_105);btn.setAttribute("tiddlyLink",_102);};config.macros.yourSearch.funcs.closeButton=function(_107,_108,_109,_10a,_10b,_10c){var _10d=createTiddlyButton(_107,"close","Close the Search Results (Shortcut: ESC)",closeResult);};config.macros.yourSearch.funcs.openAllButton=function(_10e,_10f,_110,_111,_112,_113){if(!lastResults){return;}var n=lastResults.length;if(n==0){return;}var _115=n==1?"open tiddler":"open all %0 tiddlers".format([n]);var _116=createTiddlyButton(_10e,_115,"Open all found tiddlers (Shortcut: Alt-O)",openAllFoundTiddlers);_116.setAttribute("accessKey","O");};var onNaviButtonClick=function(e){if(!e){var e=window.event;}var _119=getIntAttribute(this,"page");setFirstIndexOnPage(_119*getItemsPerPage(),0);};config.macros.yourSearch.funcs.naviBar=function(_11a,_11b,_11c,_11d,_11e,_11f){if(!lastResults||lastResults.length==0){return;}var _120;var _121=Math.floor(firstIndexOnPage/getItemsPerPage());var _122=Math.floor((lastResults.length-1)/getItemsPerPage());if(_121>0){_120=createTiddlyButton(_11a,"Previous","Go to previous page (Shortcut: Alt-'<')",onNaviButtonClick,"prev");_120.setAttribute("page",(_121-1).toString());_120.setAttribute("accessKey","<");}for(var i=-maxPagesInNaviBar;i<maxPagesInNaviBar;i++){var _124=_121+i;if(_124<0){continue;}if(_124>_122){break;}var _125=(i+_121+1).toString();var _126=_124==_121?"currentPage":"otherPage";_120=createTiddlyButton(_11a,_125,"Go to page %0".format([_125]),onNaviButtonClick,_126);_120.setAttribute("page",(_124).toString());}if(_121<_122){_120=createTiddlyButton(_11a,"Next","Go to next page (Shortcut: Alt-'>')",onNaviButtonClick,"next");_120.setAttribute("page",(_121+1).toString());_120.setAttribute("accessKey",">");}};config.macros.yourSearch.funcs["if"]=function(_127,_128,_129,_12a,_12b,_12c){if(_129.length<2){return;}var _12d=_129[1];var _12e=(_12d=="not");if(_12e){if(_129.length<3){return;}_12d=_129[2];}var test=config.macros.yourSearch.tests[_12d];var _130=false;try{if(test){_130=test(_127,_128,_129,_12a,_12b,_12c)!=_12e;}else{_130=(!eval(_12d))==_12e;}}catch(ex){}if(!_130){_127.style.display="none";}};var createOptionWithRefresh=function(_131,_132,_133,_134){invokeMacro(_131,"option",_132,_133,_134);var elem=_131.lastChild;var _136=elem.onclick;elem.onclick=function(e){var _138=_136.apply(this,arguments);refreshResult();return _138;};return elem;};config.macros.yourSearch.funcs.chkPreviewText=function(_139,_13a,_13b,_13c,_13d,_13e){var _13f=_13b.slice(1).join(" ");var elem=createOptionWithRefresh(_139,"chkPreviewText",_13c,_13e);elem.setAttribute("accessKey","P");elem.title="Show text preview of found tiddlers (Shortcut: Alt-P)";return elem;};config.macros.foundTiddler={label:"foundTiddler",prompt:"Provides information on the tiddler currently processed on the YourSearch result page",funcs:{}};config.macros.foundTiddler.handler=function(_141,_142,_143,_144,_145,_146){if(!currentTiddler){return;}var name=_143[0];var func=config.macros.foundTiddler.funcs[name];if(func){func(_141,_142,_143,_144,_145,_146);}};var closeResultAndDisplayTiddler=function(e){closeResult();var _14a=this.getAttribute("tiddlyLink");if(_14a){var _14b=this.getAttribute("withHilite");var _14c=highlightHack;if(_14b&&_14b=="true"&&lastQuery){highlightHack=lastQuery.getMarkRegExp();}story.displayTiddler(this,_14a);highlightHack=_14c;}return (false);};var getShortCutNumber=function(){if(!currentTiddler){return -1;}if(indexInPage>=0&&indexInPage<=9){return indexInPage<9?(indexInPage+1):0;}else{return -1;}};config.macros.foundTiddler.funcs.title=function(_14d,_14e,_14f,_150,_151,_152){if(!currentTiddler){return;}var _153=getShortCutNumber();var _154=_153>=0?"Open tiddler (Shortcut: Alt-%0)".format([_153.toString()]):"Open tiddler";var btn=createTiddlyButton(_14d,null,_154,closeResultAndDisplayTiddler,null);btn.setAttribute("tiddlyLink",currentTiddler.title);btn.setAttribute("withHilite","true");createLimitedTextWithMarks(btn,currentTiddler.title,maxCharsInTitle);if(_153>=0){btn.setAttribute("accessKey",_153.toString());}};config.macros.foundTiddler.funcs.tags=function(_156,_157,_158,_159,_15a,_15b){if(!currentTiddler){return;}createLimitedTextWithMarks(_156,currentTiddler.getTags(),maxCharsInTags);};config.macros.foundTiddler.funcs.text=function(_15c,_15d,_15e,_15f,_160,_161){if(!currentTiddler){return;}createLimitedTextWithMarks(_15c,removeTextDecoration(currentTiddler.text),maxCharsInText);};config.macros.foundTiddler.funcs.number=function(_162,_163,_164,_165,_166,_167){var _168=getShortCutNumber();if(_168>=0){var text="%0)".format([_168.toString()]);createTiddlyElement(_162,"span",null,"shortcutNumber",text);}};function scrollToAnchor(name){return false;}if(config.options.chkUseYourSearch==undefined){config.options.chkUseYourSearch=true;}if(config.options.chkPreviewText==undefined){config.options.chkPreviewText=true;}if(config.options.chkSearchAsYouType==undefined){config.options.chkSearchAsYouType=true;}if(config.options.chkSearchInTitle==undefined){config.options.chkSearchInTitle=true;}if(config.options.chkSearchInText==undefined){config.options.chkSearchInText=true;}if(config.options.chkSearchInTags==undefined){config.options.chkSearchInTags=true;}if(config.options.txtItemsPerPage==undefined){config.options.txtItemsPerPage=itemsPerPageDefault;}if(config.options.txtItemsPerPageWithPreview==undefined){config.options.txtItemsPerPageWithPreview=itemsPerPageWithPreviewDefault;}config.shadowTiddlers.AdvancedOptions+="\sn<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]])//";config.shadowTiddlers["YourSearch Introduction"]="!About YourSearch\sn"+"\sn"+"YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!\sn"+"\sn"+"''May the '~Alt-F' be with you.''\sn"+"\sn"+"\sn"+"!Features\sn"+"* YourSearch searches for tiddlers that match your query ''as you type'' into the 'search' field. It presents a list of the ''\s"Top Ten\s"'' tiddlers in a ''popup-like window'': the ''[[YourSearch Result]]''. The tiddlers currently displayed in your TiddlyWiki are not affected.\sn"+"* Using ''~TiddlerRank technology'' the [[YourSearch Result]] lists the ''most interesting tiddlers first''.\sn"+"* Through ''Filtered Search'' and ''Boolean Search'' you can easily refining your search, like excluding words or searching for multiple words. This way less tiddlers are displayed in the [[YourSearch Result]] and you can faster scan the result for the tiddler you are looking for.\sn"+"* The [[YourSearch Result]] lists the found tiddlers ''page-wise'', e.g. 10 per page. Use the ''Result Page Navigation Bar'' to navigate between pages if the result does not fit on one page.\sn"+"* The [[YourSearch Result]] states the ''total number of found tiddlers''. This way you can quickly decide if you want to browse the result list or if you want to refine your search first to shorten the result list.\sn"+"* Beside the ''title of the found tiddlers'' the [[YourSearch Result]] also ''displays tags'' and ''tiddler text previews''. The ''tiddler text preview'' is an extract of the tiddler's content, showing the most interesting parts related to your query (e.g. the texts around the words you are looking for).\sn"+"* The words you are looking for are hilited in the titles, tags and text previews of the [[YourSearch Result]].\sn"+"* If you are not interested in the tiddler text previews but prefer to get longer lists of tiddlers on one result page you may ''switch of the text preview''.\sn"+"* If the [[YourSearch Result]] contains the tiddler you are looking for you can just ''click its title to display'' it in your TiddlyWiki. Alternatively you may also ''open all found tiddlers'' at once. \sn"+"* Use [[YourSearch Options]] to customize YourSearch to your needs. E.g. depending on the size of your screen you may change the number of tiddlers displayed in the [[YourSearch Result]]. In the [[YourSearch Options]] and the AdvancedOptions you may also switch off YourSearch in case you temporarily want to use the standard search.\sn"+"* For the most frequently actions ''access keys'' are defined so you can perform your search without using the mouse.\sn"+"\sn";config.shadowTiddlers["YourSearch Help"]="<<tiddler [[YourSearch Introduction]]>>"+"\sn"+"!Filtered Search<html><a name='Filtered'/></html>\sn"+"Using the Filtered Search you can restrict your search to certain parts of a tiddler, e.g only search the tags or only the titles.\sn"+"|!What you want|!What you type|!Example|\sn"+"|Search ''titles only''|start word with ''!''|{{{!jonny}}}|\sn"+"|Search ''contents only''|start word with ''%''|{{{%football}}}|\sn"+"|Search ''tags only''|start word with ''#''|{{{#Plugin}}}|\sn"+"\sn"+"You may use more than one filter for a word. E.g. {{{!#Plugin}}} finds tiddlers containing \s"Plugin\s" either in the title or in the tags (but does not look for \s"Plugin\s" in the content).\sn"+"\sn"+"!Boolean Search<html><a name='Boolean'/></html>\sn"+"The Boolean Search is useful when searching for multiple words.\sn"+"|!What you want|!What you type|!Example|\sn"+"|''All words'' must exist|List of words|{{{jonny jeremy}}}|\sn"+"|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\sn"+"|A word ''must not exist''|Start word with ''-''|{{{-jonny}}}|\sn"+"\sn"+"''Note:'' When you specify two words, separated with a space, YourSearch finds all tiddlers that contain both words, but not necessarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need to put the words into quotes. I.e. you type: {{{\s"john brown\s"}}}.\sn"+"\sn"+"!'Exact Word' Search<html><a name='Exact'/></html>\sn"+"By default a search result all matches that 'contain' the searched text. \sn"+" E.g. if you search for 'Task' you will get all tiddlers containing 'Task', but also 'CompletedTask', 'TaskForce' etc.\sn"+"\sn"+"If you only want to get the tiddlers that contain 'exactly the word' you need to prefix it with a '='. E.g. typing '=Task' will the tiddlers that contain the word 'Task', ignoring words that just contain 'Task' as a substring.\sn"+"\sn"+"!Combined Search<html><a name='Combined'/></html>\sn"+"You are free to combine the various search options. \sn"+"\sn"+"''Examples''\sn"+"|!What you type|!Result|\sn"+"|{{{!jonny !jeremy -%football}}}| all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its titles, but no {{{football}}} in content.|\sn"+"|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact word). Tags named 'CompletedTask', 'TaskForce' etc. are not considered.|\sn"+"\sn"+"!~CaseSensitiveSearch and ~RegExpSearch<html><a name='Case'/></html>\sn"+"The standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearch. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\sn"+"\sn"+"!Access Keys<html><a name='Access'/></html>\sn"+"You are encouraged to use the access keys (also called \s"shortcut\s" keys) for the most frequently used operations. For quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\sn"+"\sn"+"|!Key|!Operation|\sn"+"|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search input field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the previous search result. This way you can quickly display multiple tiddlers using \s"Press {{{Alt-F}}}. Select tiddler.\s" sequences.|\sn"+"|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Result]] is already closed and the cursor is in the search input field the field's content is cleared so you start a new query.|\sn"+"|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second etc. tiddler from the result list.|\sn"+"|{{{Alt-O}}}|Opens all found tiddlers.|\sn"+"|{{{Alt-P}}}|Toggles the 'Preview Text' mode.|\sn"+"|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[YourSearch Result]].|\sn"+"|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the {{{Return}}} key actually starts the search (as does pressing the 'search' button).|\sn"+"\sn";config.shadowTiddlers["YourSearch Options"]="|>|!YourSearch Options|\sn"+"|>|<<option chkUseYourSearch>> Use 'Your Search'|\sn"+"|!|<<option chkPreviewText>> Show Text Preview|\sn"+"|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required to start search)|\sn"+"|!|Default Search Filter:<<option chkSearchInTitle>>Titles ('!') <<option chkSearchInText>>Texts ('%') <<option chkSearchInTags>>Tags ('#') <html><br><font size=\s"-2\s">The parts of a tiddlers that are searched when you don't explicitly specify a filter in the search text (using a '!', '%' or '#' prefix).</font></html>|\sn"+"|!|Number of items on search result page: <<option txtItemsPerPage>>|\sn"+"|!|Number of items on search result page with preview text: <<option txtItemsPerPageWithPreview>>|\sn";config.shadowTiddlers["YourSearchStyleSheet"]="/***\sn"+"!~YourSearchResult Stylesheet\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchResult {\sn"+"\stposition: absolute;\sn"+"\stwidth: 800px;\sn"+"\sn"+"\stpadding: 0.2em;\sn"+"\stlist-style: none;\sn"+"\stmargin: 0;\sn"+"\sn"+"\stbackground: White;\sn"+"\stborder: 1px solid DarkGray;\sn"+"}\sn"+"\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Summary Section\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchResult .summary {\sn"+"\stborder-bottom-width: thin;\sn"+"\stborder-bottom-style: solid;\sn"+"\stborder-bottom-color: #999999;\sn"+"\stpadding-bottom: 4px;\sn"+"}\sn"+"\sn"+".yourSearchRange, .yourSearchCount, .yourSearchQuery {\sn"+"\stfont-weight: bold;\sn"+"}\sn"+"\sn"+".yourSearchResult .summary .button {\sn"+"\stfont-size: 10px;\sn"+"\sn"+"\stpadding-left: 0.3em;\sn"+"\stpadding-right: 0.3em;\sn"+"}\sn"+"\sn"+".yourSearchResult .summary .chkBoxLabel {\sn"+"\stfont-size: 10px;\sn"+"\sn"+"\stpadding-right: 0.3em;\sn"+"}\sn"+"\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Items Area\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchResult .marked {\sn"+"\stbackground: none;\sn"+"\stfont-weight: bold;\sn"+"}\sn"+"\sn"+".yourSearchItem {\sn"+"\stmargin-top: 2px;\sn"+"}\sn"+"\sn"+".yourSearchNumber {\sn"+"\stcolor: #808080;\sn"+"}\sn"+"\sn"+"\sn"+".yourSearchTags {\sn"+"\stcolor: #008000;\sn"+"}\sn"+"\sn"+".yourSearchText {\sn"+"\stcolor: #808080;\sn"+"\stmargin-bottom: 6px;\sn"+"}\sn"+"\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Footer\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchFooter {\sn"+"\stmargin-top: 8px;\sn"+"\stborder-top-width: thin;\sn"+"\stborder-top-style: solid;\sn"+"\stborder-top-color: #999999;\sn"+"}\sn"+"\sn"+".yourSearchFooter a:hover{\sn"+"\stbackground: none;\sn"+"\stcolor: none;\sn"+"}\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Navigation Bar\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchNaviBar a {\sn"+"\stfont-size: 16px;\sn"+"\stmargin-left: 4px;\sn"+"\stmargin-right: 4px;\sn"+"\stcolor: black;\sn"+"\sttext-decoration: underline;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar a:hover {\sn"+"\stbackground-color: none;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar .prev {\sn"+"\stfont-weight: bold;\sn"+"\stcolor: blue;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar .currentPage {\sn"+"\stcolor: #FF0000;\sn"+"\stfont-weight: bold;\sn"+"\sttext-decoration: none;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar .next {\sn"+"\stfont-weight: bold;\sn"+"\stcolor: blue;\sn"+"}\sn"+"/*}}}*/\sn";config.shadowTiddlers["YourSearchResultTemplate"]="<!--\sn"+"{{{\sn"+"-->\sn"+"<span macro=\s"yourSearch if found\s">\sn"+"<!-- The Summary Header ============================================ -->\sn"+"<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+" <tr>\sn"+"\st<td align=\s"left\s">\sn"+"\st\stYourSearch Result <span class=\s"yourSearchRange\s" macro=\s"yourSearch itemRange\s"></span>\sn"+"\st\st&nbsp;of&nbsp;<span class=\s"yourSearchCount\s" macro=\s"yourSearch count\s"></span>\sn"+"\st\stfor&nbsp;<span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>\sn"+"\st</td>\sn"+"\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+"\st\st<span macro=\s"yourSearch chkPreviewText\s"></span><span class=\s"chkBoxLabel\s">preview text</span>\sn"+"\st\st<span macro=\s"yourSearch openAllButton\s"></span>\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+"\st</td>\sn"+" </tr>\sn"+"</tbody></table>\sn"+"\sn"+"<!-- The List of Found Tiddlers ============================================ -->\sn"+"<div id=\s"yourSearchResultItems\s" itemsPerPage=\s"25\s" itemsPerPageWithPreview=\s"10\s"></div>\sn"+"\sn"+"<!-- The Footer (with the Navigation) ============================================ -->\sn"+"<table class=\s"yourSearchFooter\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+" <tr>\sn"+"\st<td align=\s"left\s">\sn"+"\st\stResult page: <span class=\s"yourSearchNaviBar\s" macro=\s"yourSearch naviBar\s"></span>\sn"+"\st</td>\sn"+"\st<td align=\s"right\s"><span macro=\s"yourSearch version\s"></span>, <span macro=\s"yourSearch copyright\s"></span>\sn"+"\st</td>\sn"+" </tr>\sn"+"</tbody></table>\sn"+"<!-- end of the 'tiddlers found' case =========================================== -->\sn"+"</span>\sn"+"\sn"+"\sn"+"<!-- The \s"No tiddlers found\s" case =========================================== -->\sn"+"<span macro=\s"yourSearch if not found\s">\sn"+"<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+" <tr>\sn"+"\st<td align=\s"left\s">\sn"+"\st\stYourSearch Result: No tiddlers found for <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>.\sn"+"\st</td>\sn"+"\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+"\st</td>\sn"+" </tr>\sn"+"</tbody></table>\sn"+"</span>\sn"+"\sn"+"\sn"+"<!--\sn"+"}}}\sn"+"-->\sn";config.shadowTiddlers["YourSearchItemTemplate"]="<!--\sn"+"{{{\sn"+"-->\sn"+"<span class='yourSearchNumber' macro='foundTiddler number'></span>\sn"+"<span class='yourSearchTitle' macro='foundTiddler title'/></span>&nbsp;-&nbsp;\sn"+"<span class='yourSearchTags' macro='foundTiddler tags'/></span>\sn"+"<span macro=\s"yourSearch if previewText\s"><div class='yourSearchText' macro='foundTiddler text'/></div></span>\sn"+"<!--\sn"+"}}}\sn"+"-->";config.shadowTiddlers["YourSearch"]="<<tiddler [[YourSearch Help]]>>";config.shadowTiddlers["YourSearch Result"]="The popup-like window displaying the result of a YourSearch query.";setStylesheet(store.getTiddlerText("YourSearchStyleSheet"),"yourSearch");var origMacros_search_handler=config.macros.search.handler;config.macros.search.handler=myMacroSearchHandler;var ownsOverwrittenFunctions=function(){var _16b=(config.macros.search.handler==myMacroSearchHandler);return _16b;};var checkForOtherHijacker=function(){if(!ownsOverwrittenFunctions()){alert("Message from YourSearchPlugin:\sn\sn\sn"+"Another plugin has disabled the 'Your Search' features.\sn\sn\sn"+"You may disable the other plugin or change the load order of \sn"+"the plugins (by changing the names of the tiddlers)\sn"+"to enable the 'Your Search' features.");}};setTimeout(checkForOtherHijacker,5000);abego.YourSearch.getStandardRankFunction=function(){return standardRankFunction;};abego.YourSearch.getRankFunction=function(){return abego.YourSearch.getStandardRankFunction();};abego.YourSearch.getCurrentTiddler=function(){return currentTiddler;};}\n/***\n%/\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005-2006 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/
* @@{{{leadtime:NUMBER}}}@@ or @@{{{leadtime:NUMBER...NUMBER}}}@@ - Use this to specify a lower and upper bound for reminders that will be shown. If only one number is specified, then it is treated as the upper bound, and zero is assumed for the lower bound. These bounds can be negative, in order to show past due reminders. For example, {{{leadtime:-5...-1}}} will show all reminders that matched in the last five days. If reminders specify a leadtime, then they may show up, even when they don't fit into showReminder's leadtime bounds. Use the limit argument to showReminders to override this behavior. If the leadtime parameter is missing, then {{{leadtime:0...14}}} will be assumed.\n\n* @@{{{nolinks}}}@@ - Deprecated. Override the format argument to control what the output looks like.\n\n* @@{{{limit}}}@@ - By default, individual reminders can override the leadtime specified by showReminders. Use this argument to override that behavior.\n\n* @@{{{tag:"STRING"}}}@@ - This filters out tiddlers based on the tag applied to them. Supply a space-separated list of tags. If a tag name begins with an {{{!}}}, then only tiddlers which do not have that tag will be considered. For example {{{tag:"examples holidays"}}} will search for reminders in any tiddlers that are tagged with examples or holidays and {{{tag:"!examples !holidays"}}} will search for reminders in any tiddlers that are not tagged with examples or holidays.\n\n* @@{{{format:"STRING"}}}@@ - Use this argument to override the default string used for display. You can put standard TiddlyWiki formatting in the format. The following substitutions will be made in the string before it is displayed.\n** DIFF will be replaced with the one of the strings "Today", "Tommorrow", or "N days", where N is the number of days between now and the date of the reminder. \n** TITLE will be replaced with the title of the reminder\n** DATE will be replaced with the matched date of the reminder.\n** ANNIVERSARY will be replaced with the number of years since between the matched date and firstyear\n** TIDDLER will be replaced with a link to the tiddler that contains the reminder.\nThe default string is "DIFF: TITLE on DATE ANNIVERSARY -- TIDDLER"
<?php\n/***\n! User settings\nEdit these lines according to your need\n***/\n//{{{\n$AUTHENTICATE_USER = true; // true | false\n$USER = 'UsernameToCheck'; // set a Username\n$PASSWORD = 'PasswordToCheck'; // set a strong password\n$DEBUG = false; // true | false\n//}}}\n/***\n!Code\nNo change needed under\n***/\n//{{{\n\n/***\n * store.php - upload a file in this directory\n * version :1.2 - 12/02/2006 - BidiX@BidiX.info\n * \n * see : \n * http://tiddlywiki.bidi.info/#UploadPlugin for usage\n * http://www.php.net/manual/en/features.file-upload.php \n * for détails on uploading files\n * usage : \n * POST \n * UploadPlugin[backupDir=<backupdir>;user=<user>;password=<password>;]\n * userfile <file>\n * GET\n *\n * Revision history\n * v 1.2 - 12/02/2006 : \n * POST \n * UploadPlugin[backupDir=<backupdir>;user=<user>;password=<password>;]\n * userfile <file>\n* if $AUTHENTICATE_USER\n * presence and value of user and password are checked with \n * $USER and $PASSWORD\n * v 1.1 - 23/12/2005 : \n * POST UploadPlugin[backupDir=<backupdir>] userfile <file>\n * v 1.0 - 12/12/2005 : \n * POST userfile <file>\n *\n * Copyright (c) BidiX@BidiX.info 2005-2006\n ***/\n//}}}\n\n//{{{\n\nif ($_SERVER['REQUEST_METHOD'] == 'GET') {\n?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n <head>\n <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >\n <title>BidiX.info - TiddlyWiki UploadPlugin - Store script</title>\n </head>\n <body>\n <p>\n <p>store.php V 1.2\n <p>BidiX@BidiX.info\n <p>&nbsp;</p>\n <p>&nbsp;</p>\n <p>&nbsp;</p>\n <p align="center">This page is designed to upload a <a href="http://www.tiddlywiki.com/">TiddlyWiki<a>.</p>\n <p align="center">for details see : <a href="http://www.bidix.info/TiddlyWiki/BidiXTW.html#HowToUpload">www.bidix.info/TiddlyWiki/BidiXTW.html#HowToUpload<a>.</p> \n </body>\n</html>\n<?php\n}\nelse {\n $uploaddir = './';\n $backuperror = false;\n $optionStr = $_POST['UploadPlugin'];\n $optionArr=explode(';',$optionStr);\n $options = array();\n $backupFilename = '';\n foreach($optionArr as $o) {\n list($key, $value) = split('=', $o);\n $options[$key] = $value;\n }\n if ((!$AUTHENTICATE_USER) \n || (($options['user']) && ($options['user'] == $USER) && ($options['password']) && ($options['password'] == $PASSWORD))) {\n if (file_exists($uploaddir . $_FILES['userfile']['name']) && ($options['backupDir'] != '')) {\n if (! file_exists($options['backupDir'])) {\n mkdir($options['backupDir']) or ($backuperror = "mkdir error");\n }\n $filename = $_FILES['userfile']['name'];\n $backupFilename = $options['backupDir'].'/'.substr($filename, 0, strpos($filename, '.'))\n .date('.Ymd.His').substr($filename,strpos($filename,'.'));\n rename($filename, $backupFilename) or ($backuperror = "rename error");\n }\n if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir . $_FILES['userfile']['name'])) {\n if (!$backuperror) {\n if($DEBUG) {\n echo "debug mode \sn\sn";\n }\n echo "0 - File successfully loaded in " .$uploaddir . $_FILES['userfile']['name']. "\sn";\n if ($backupFilename)\n echo "backupFile=$backupFilename;\sn";\n } else {\n echo "BackupError : $backuperror - File successfully loaded in " .$uploaddir . $_FILES['userfile']['name']. "\sn";\n }\n } \n else {\n echo "Error : " . $_FILES['error']." - File NOT uploaded !\sn";\n }\n }\n else {\n echo "Error : UserName or Password do not match \sn";\n echo "UserName : [".$options['user']. "] Password : [". $options['password'] . "]\sn";\n }\n if ($DEBUG) {\n echo '\snHere is some more debugging info : \sn';\n print ("\s$_FILES : \sn");\n print_r($_FILES);\n print ("\s$options : \sn");\n print_r($options);\n }\n}\n//}}}\n?>