//Par ''Akhad''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>Petite option pour déterminer les dégâts en combat à l'aide du jet pour toucher lorsque 3d6 sont utilisés à la place du d20.>>\nSi le jet de compétence est réussi (somme des 3d6), les dégâts sont déterminés ainsi :\n*à 1d6 de dégâts, on prend le dé médian\n*à 2d6 de dégâts, on prend le dé le plus faible et le plus fort\n*à 3d6 de dégâts, on prend les 3 dés.\nBien-sûr, si les dés pris en comptes sont explosifs, ils sont relancés.\nEn outre, ce système fonctionne aussi pour n'importe quel test dont les effets sont quantifiés par des d6 (soins...).
This notebook attempts to capture the essence of a [["kinkless" GTD system|http://www.kinkless.com]] using TiddlyWiki. It is using the <<gtdVersion>> version of the GTD plugins, by Tom Otvos, and is based on version <<version>> of the [[TiddlyWiki|http://www.tiddlywiki.com]] stand-alone wiki project, by Jeremy Ruston. For customization info, see [[GTD TiddlyWiki|http://groups.google.com/group/GTD-TiddlyWiki]] and [[TiddlyWikiDev|http://www.tiddlywiki.com/dev/]].
!Welcome to version 1.0.10 of d-cubed.\nThis is a hasty bug-fix release to the previous 1.0.9 version, with the following fixes:\n* fixed [[Action Review]] to once again show project-less actions\n* fixed GTDStyleSheet to have a smaller menu width for non-fancy styles (see below).\nBecause this release is hot on the heels of the 1.0.9 release, here are the notes for that (in case you are just arriving to the party).\n\n!Welcome to version 1.0.9 of d-cubed.\nIn this release, there are the following changes:\n* changed all action lists to allow direct access to associated projects and contexts\n* added optional "floating" parameter to {{{<<gtdAction>>}}} to support creating actions that don't have to be strictly "next" to show up in action lists, as in:\n{{{\n<<gtdAction actionTitle @context floating>>\n}}}\n* added support for single-click updates of the ~TiddlyWiki core in [[Check for Updates|UpdateApplication]]\n* fixed a bug that caused odd tiddler behaviour when editing a "reference" tiddler and the main Reference tiddler was open\n* changed the default style rules to the popular GTDTW+ style, using the new GTDTWStyleSheet; to use this style, please note that:\n** this stylesheet is loaded automatically (you do not need to edit the StyleSheet tiddler)\n** if you are updating your d-cubed installation and have a custom PageTemplate, you will need to edit your PageTemplate to have a gradient of #000 to #464646 for the full effect\n** if you want to revert to the plain d-cubed style, or have your own style variations, simply disable the "fancy" style from the [[Configuration Options]]\n\n!Please do the survey\nIf you have not already done so (and you are an active user of d-cubed), please take a moment to fill in a short [[user survey|http://www.surveymonkey.com/s.asp?u=626142022640]]. It will help me to craft future releases of d-cubed knowing what you think about it.\n\n//This tiddler will only open automatically the first time you run d-cubed after an update. After that, you can freely delete it, or save it for future reference.//
!Welcome to version 1.0.11 of d-cubed\nThis version has a number of enhancements over the previous release, both in terms of performance and functionality. A couple of bug fixes, a couple of feature requests. All for the better, one hopes.\n\nWhat's fixed:\n* printing page breaks fixed, including ~IE6 hack from Clint Checketts\n* marking an action as done now updates the modification date of the action\n* if an action accidentally does not have a context, the action context picker now allows you to assign a context\n* added some minor performance optimizations when related tiddlers are updated as an action is changed\n\nWhat's new:\n* project actions using ".." notation now trim leading/trailing spaces around action name and context, allowing for more airy {{{.. action | @context}}} syntax\n* added hook function to allow advanced users to trap action completions; to use this feature, you must create a Javascript function with the following prototype:\n{{{\nfunction gtdActionDoneHook(tiddler) { /* do something here */ }\n}}}\n* added [[reviewViewTemplate]] to create a cleaner action and project review\n* added timed update (every minute) of review tiddlers, to allow reviews with reminders to stay current\n* removed user/created/modified from context view template, and user from project and action view template\n* added "review mode" view of contexts that show "next" actions only\n* changed sorting in context view to better organize/prioritize actions\n** project actions appear before non-project actions, and project actions appear in sequence within project\n* added ability to create "important" projects that affect action sorting in contexts\n** important projects appear before normal projects\n* added "noproject" and "projectonly" qualifiers on {{{gtdActionList}}} macro to filter actions based on project association, to enable creation of custom context/review views\n* added Summary Review to gather all review tiddlers in place for quick at-a-glance reviews\n* added the ability to "defer" an ongoing project into "someday"\n* updated date and calendar plugins to latest versions, and provided some additional configuration to make calendar look better in enhanced GTD style\n* minor UI enhancements to ReminderMacros\n\nEnjoy!\n\n//This tiddler will only open automatically the first time you run d-cubed after an update. After that, you can freely delete it, or save it for future reference.//\n
!Welcome to version 1.1.0 of d-cubed\nIn this release, d-cubed embraces the new 2.1 version of ~TiddlyWiki, taking advantage of some of what it has to offer, and allowing the more adventurous user to add on any of the new 2.1-centric plugins to further enhance their d-cubed setup.\n\n''Note that to fully upgrade d-cubed, you must first update the core GTD plugins //and then// update ~TiddlyWiki. If you are reading this, then you have already done the first step. If you have not updated ~TiddlyWiki, the easiest way is to click on "Check for Updates" in the menu at left, and then click on the "Update ~TiddlyWiki" button. For your information, you are currently running version <<version>> of ~TiddlyWiki.''\n\nAlso note that you do not need to update ~TiddlyWiki to use this version of d-cubed. It is nicer if you do, but you get some bang just from this release, as detailed below.\n\nThis release has the following changes:\n* project actions are no longer tagged by the project name, dramatically reducing the pollution of the "tag space" -- this is feature is limited to TW 2.1 or greater\n* changed update frequency of review tiddlers to avoid unnecessary processing since reminders are never intra-day\n** direct changes to actions, projects, and contexts still updated immediately\n* added timed autosave of dirty document to avoid performance overhead of having TW AutoSave turned on\n** can turn off or configure interval using [[Configuration Options]]\n** can hook into processing by defining {{{gtdAutoSaveHook()}}} function\n* more flexible project list in GTDMenu by indirect reference to ProjectList tiddler\n* added delete buttons to action and project view templates to allow quick delete without editing action or project\n* added archive button to project view template to allow selective archiving of projects\n* added reference to [[Ticklers]] to GTDMenu\n** to avoid clobbering existing "Ticklers" tiddlers, a SampleTicklers is provided for those new to using these reminders\n* added listing of projects with no open actions to [[Project Review]] to aid in weekly review\n* projects with no open actions are now automatically tagged as "done", for easy identification and filtering\n* prompt for deletion of action when completed if it is not part of a project\n* fixed bug with floating actions remaining highlighted after they are done\n\n//This tiddler will only open automatically the first time you run d-cubed after an update. After that, you can freely delete it, or save it for future reference.//\n\n!Welcome to Tiddlyspot\n<<tiddler 'Welcome to your tiddlyspot.com site!'>>
Bienvenue sur le site (presque) officiel du ''dK system''. \n\nLe dK est configurable à l’infini et il existe des tas de dKrunch auxquels nous n’avons pas pensé. Mais vous si, très certainement ! Matrice dK est votre site de configuration du dK system, entièrement dédié à toutes les idées géniales qui sortent de vos cerveaux.\nCe site est un tiddlywiki qui regroupera tous les articles finis, corrigés et validés par vos soins sur le [[forum de travail de la Matrice dK|http://legrumph.org/dK/forum]]. Inscrivez-vous sur le forum, postez vos propositions, réagissez sur celles des autres membres. Lorsque vous estimerez que les modules que vous proposez sont impeccables, ils seront montés ici et organisés pour que vous puissiez les consulter aisément.\n\nNous espérons que ce site correspondra à vos attentes et à vos besoins. \nBon jeu !
! Next actions for active contexts\n<<gtdActionList @>>
config.options.chkHttpReadOnly = false;\n
//Par ''Kobal''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>Voici les ~PNJs de la Guerre des Ombres, le premier volume de la campagne Archipels, au format dK. Commentaires et corrections bienvenus !>>\n!~PNJs de la guerre des ombres\n!!!Chien errant - niveau 1\nFOR : 5 INT : 0\nDEX : 3 SAG : 0\nCON : 4 CHA : 0\nAtt : +5 PV : 14\nDef : +3 PE : 5\nSvg : +4\nAtouts : armure naturelle , animal, odorat\nCompétences : acrobaties 11, discrétion 6\nArme : Dents (1d6)\nProtection : 2\n!!!Dallya - niveau 3\nFOR : 2 INT : 4\nDEX : 5 SAG : 3\nCON : 1 CHA : 0\nAtt : +7 PV : 23\nDef : +6 PE : 21\nSvg : +4\nAtouts : armes et armure de brutasse, boîte de conserve,\nmagicien, compétences, compteurs x2, talentueux (style), avantages, âme\nde chef, talentueux (équitation)\nCompétences : acrobaties 6, discrétion 8, dressage 6, Intimidation 5,\nstyle(religion) 7, métier (guérisseur) 12, équitation(guêpe) 10.\nArme : Arc long (2d6), Cimeterre (2d6)\nProtection : 4\nDomaines : Corps, Air\n!!!Nemedienne - niveau 2\nFOR : 4 INT : 2\nDEX : 5 SAG : 1\nCON : 3 CHA : 0\nAtt : +6 PV : 28\nDef : +5 PE : 15\nSvg : +4\nAtouts : armes et armure de brutasse, boîte de conserve,\nattaque en finesse, compteurs x2\nCompétences : acrobaties 7, discrétion 4, dressage 2, Intimidation 5,\néquitation(guêpe) 10.\nArme : Arc long (2d6), Cimeterre (2d6)\nProtection : 4\n!!!Guêpe géante - niveau 4\nFOR : 2 INT : 0\nDEX : 6 SAG : 0\nCON : 5 CHA : 0\nAtt : +8 PV : 55\nDef : +6 (+10 en vol) PE : 14\nSvg : +5\nAtouts : compteurs x4, vol x4, armure naturelle, armes naturelles.\nCompétences : acrobaties 10 (sans cavalier : 15)\nArme : Aiguillon (2d6), Poison : svg 16 (1d6)\n!!!Ivrogne standard - niveau 1\nFOR : 2 INT : 1\nDEX : 1 SAG : 1\nCON : 1 CHA : 1\nAtt : +3 PV : 11\nDef : +2 PE : 11\nSvg : +2\nAtouts : Talentueux (marin)\nCompétences : acrobaties 4, perception 3, Métier (marin) 7\nArme : coutelas (1d6), poings (1d6)\n!!!Doug le pirate - niveau 1\nFOR : 2 INT : 1\nDEX : 1 SAG : 1\nCON : 3 CHA : 1\nAtt : +4 PV : 21\nDef : +3 PE : 13\nSvg : +4\nAtouts : compteurs, avantages, talentueux (marin)\nCompétences : acrobaties 4, perception 3, Métier (marin) 7\nArme : coutelas (1d6), poings (1d6)\n!!!Artilleur du clan Sarkhamir - niveau 1\nFOR : 3 INT : 4\nDEX : 5 SAG : 2\nCON : 2 CHA : 1\nAtt : +8 PV : 12\nDef : +7 PE : 12\nSvg : +4\nAtouts : magicien, armes de pro, talentueux (style), avantages\nCompétences : acrobaties 7, perception 5, Métier (marin) 12, style (occultisme) 10\nArme : rapière (2d6) ou hache de bataille (2d6)\narmure : 2\n!!!Obert le balafré - niveau 3\nFOR : 2 INT : 1\nDEX : 5 SAG : 1\nCON : 2 CHA : 1\nAtt : +5 PV : 19\nDef : +8 PE : 13\nSvg : +3\nAtouts : armes de pro, attaque en finesse, tir de loin, compteurs, avantages x2, compétences x2\nCompétences : acrobaties 9, bluff 5,déguisement 9, escalade 7, escamotage 9, évasion 10, discrétion 9, perception 5, psychologie 5 \nArme : épée courte (2d6) ou arbalète (2d6)\n!!!Malandrin, assassin débutant - niveau 1\nFOR : 1 INT : 1\nDEX : 5 SAG : 1\nCON : 2 CHA : 1\nAtt : +2 PV : 19\nDef : +6 PE : 13\nSvg : +3\nAtouts : armes de pro, attaque en finesse, tir de loin, compteurs\nCompétences : acrobaties 7, bluff 3,déguisement 7, escalade 7, escamotage 7, évasion 7, discrétion 7, perception 3 \nArme : dague (1d6) ou arbalète (2d6)\n!!!Tassel, agent de l'Oracle - niveau 5\nFOR : 5 INT : 5\nDEX : 1 SAG : 2\nCON : 3 CHA : 1\nAtt : +13 PV : 33\nDef : +5 (+9) PE : 25\nSvg : +5\nAtouts : magicien, caractéristiques, sorts discrets, magie rapide, sorts de brutasse, talentueux (style), armes de brutasse, compteurs x3, attaque dévastatrice x2, avantages x3, enchaînement, parade en force, attaques multiples, spécialisation (masse 2M)\nCompétences : style (religion) 9, acrobaties 11, bluff 11,déguisement 7, diplomatie 11, escalade 11, discrétion 11, perception 12, psychologie 12, renseignements 7 \nArme : Masse à deux mains (3d6)\n!!!Baptiste Delyl, anti-héros maladroit - niveau 1\nFOR : 1 INT : 2 \nDEX : 4 SAG : 0\nCON : 3 CHA : 5\nAtt : +3 PV :21\nDef : +10 PE : 11\nSvg : +4\nAtouts : Talentueux (commerçant), compteurs, Attendrissant, Avantages\nCompétences : Bluff 8, Connaissances (Vendrest) 3, Métier (commerçant) 11, équitation 5, natation 5, Métier (troubadour) 6\nArme : épée longue (1d6) \n!!!Trennock Rougeface, capitaine intrépide - niveau 3\nFOR : 5 INT : 1\nDEX : 3 SAG :1\nCON : 4 CHA : 4 \nAtt : +8 PV :32 \nDef : +7 PE : 12\nSvg : +7\nAtouts :Avantages x2, Compteurs x2, Armes de pro, Armes de brutasse, Attaque sournoise, Boussole vivante, Spécialisation\nCompétences : Métier(Marin) 7, escalade 3, natation 3 \nArme : Hache de bataille (3d6)\nProtection : Armure d'écailles (4), Targette (2)\n!!!Sargis, guerisseuse taciturne - niveau 3\nFOR : 1 INT : 5 \nDEX : 4 SAG : 2\nCON : 3 CHA : 0\nAtt : +9 PV :29\nDef : +5 PE : 29\nSvg : +7\nAtouts : Magicien, Talentueux (style - Potions), Talentueux (style - Calligraphie), sorts discrets, compteurs x3, avantages x3, sorts de pro, style supplémentaire \nCompétences : Métier (Alchimiste), Métier (Marin), Connaissance (mystères), Métier (guérisseur), Métier (scribe)\nStyle : Potions - Métier (Alchimiste), Calligraphie - Métier (scribe)\nDomaines : Corps (Potions), Enchantement (Calligraphie) \nArme : canne (1d6)\n!!!Mirghun Iorelistani, génie de l'invention - niveau 3\nFOR : 1 INT : 5 \nDEX : 4 SAG : 2\nCON : 3 CHA : 0\nAtt : +9 PV :29\nDef : +5 PE : 29\nSvg : +7\nAtouts : \nCompétences : \nStyle : \nArme :
To make this system operate more efficiently, you should periodically archive completed projects and actions. When a project or action is archived, it is merely tagged in a special way to get it "out of sight", but all the information in the project and action tiddlers is preserved. This is important if you need to go back and find something. Click one of these buttons to view the current <<tag project-archive>> or <<tag action-archive>>.\n\n** Click <<gtdArchive archive>> if you would like to archive all completed projects and actions now.\n** Click <<gtdArchive unarchive>> if you would like to unarchive all previously archived projects and actions now.\n\nIf you are sure that you do not want to retain archived projects and actions, you can purge them completely from the system. //Once these archived items are removed, the only way they can be put back in is through manual importing or copy/paste.// ''For your safety, your file will be saved and a backup file will be automatically generated before an archive purge is performed.''\n\n** Click <<gtdArchive purge>> if you would like to purge your archive now.
Vous trouverez dans la fenêtre Tagging, à droite, la liste des atouts proposés par les utilisateurs de la Matrice.
/***\n|''Name:''|CalendarPlugin|\n|''Source:''|http://www.TiddlyTools.com/#CalendarPlugin|\n|''Author:''|SteveRumsby|\n|''License:''|unknown|\n|''~CoreVersion:''|2.0.10|\n\n// // updated by Jeremy Sheeley to add cacheing for reminders\n// // see http://www.geocities.com/allredfaq/reminderMacros.html\n// // ''Changes by ELS 2006.08.23:''\n// // added handling for weeknumbers (code supplied by Martin Budden. see "wn**" comment marks)\n// // ''Changes by ELS 2005.10.30:''\n// // config.macros.calendar.handler()\n// // ^^use "tbody" element for IE compatibility^^\n// // ^^IE returns 2005 for current year, FF returns 105... fix year adjustment accordingly^^\n// // createCalendarDays()\n// // ^^use showDate() function (if defined) to render autostyled date with linked popup^^\n// // calendar stylesheet definition\n// // ^^use .calendar class-specific selectors, add text centering and margin settings^^\n\n\n!!!!!Configuration:\n<<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//\n|''First day of week:''|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|\n|''First day of weekend:''|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|\n\n!!!!!Syntax:\n|{{{<<calendar>>}}}|Produce a full-year calendar for the current year|\n|{{{<<calendar year>>}}}|Produce a full-year calendar for the given year|\n|{{{<<calendar year month>>}}}|Produce a one-month calendar for the given month and year|\n|{{{<<calendar thismonth>>}}}|Produce a one-month calendar for the current month|\n|{{{<<calendar lastmonth>>}}}|Produce a one-month calendar for last month|\n|{{{<<calendar nextmonth>>}}}|Produce a one-month calendar for next month|\n\n***/\n// //Modify 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//{{{\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"];\n\nconfig.macros.calendar.weekendbg = "#c0c0c0";\nconfig.macros.calendar.monthbg = "#e0e0e0";\nconfig.macros.calendar.holidaybg = "#ffc0c0";\n\n//}}}\n// //''Code section:''\n// (you should not need to alter anything below here)//\n//{{{\nif(config.options.txtCalFirstDay == undefined)\n config.options.txtCalFirstDay = 0;\nif(config.options.txtCalStartOfWeekend == undefined)\n config.options.txtCalStartOfWeekend = 5;\nif(config.options.chkDisplayWeekNumbers == undefined)//wn**\n config.options.chkDisplayWeekNumbers = false;\nif(config.options.chkDisplayWeekNumbers)\n config.options.txtCalFirstDay = 0;\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: 6, revision: 0, date: new Date(2006, 1, 22)};\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// ELS 2006.05.29: add journalDateFmt handling//\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 \n // get format for journal link by reading from SideBarOptions (ELS 5/29/06 - based on suggestion by Martin Budden)\n var text = store.getTiddlerText("SideBarOptions");\n this.journalDateFmt = "DD-MMM-YYYY";\n var re = new RegExp("<<(?:newJournal)([^>]*)>>","mg"); var fm = re.exec(text);\n if (fm && fm[1]!=null) { var pa=fm[1].readMacroParams(); if (pa[0]) this.journalDateFmt = pa[0]; }\n\n if (params[0] == "thismonth")\n {\n cacheReminders(new Date(year, today.getMonth(), 1, 0, 0), 31);\n createCalendarOneMonth(tbody, year, today.getMonth());\n } \n else if (params[0] == "lastmonth") {\n var month = today.getMonth()-1; if (month==-1) { month=11; year--; }\n cacheReminders(new Date(year, month, 1, 0, 0), 31);\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 cacheReminders(new Date(year, month, 1, 0, 0), 31);\n createCalendarOneMonth(tbody, year, month);\n }\n else {\n if (params[0]) year = params[0];\n if(params[1])\n {\n cacheReminders(new Date(year, params[1]-1, 1, 0, 0), 31);\n createCalendarOneMonth(tbody, year, params[1]-1);\n }\n else\n {\n cacheReminders(new Date(year, 0, 1, 0, 0), 366);\n createCalendarYear(tbody, year);\n }\n }\n window.reminderCacheForCalendar = null;\n}\n//}}}\n//{{{\n//This global variable is used to store reminders that have been cached\n//while the calendar is being rendered. It will be renulled after the calendar is fully rendered.\nwindow.reminderCacheForCalendar = null;\n//}}}\n//{{{\nfunction cacheReminders(date, leadtime)\n{\n if (window.findTiddlersWithReminders == null)\n return;\n window.reminderCacheForCalendar = {};\n var leadtimeHash = [];\n leadtimeHash [0] = 0;\n leadtimeHash [1] = leadtime;\n var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);\n for(var i = 0; i < t.length; i++) {\n //just tag it in the cache, so that when we're drawing days, we can bold this one.\n window.reminderCacheForCalendar[t[i]["matchedDate"]] = "reminder:" + t[i]["params"]["title"]; \n }\n}\n//}}}\n//{{{\nfunction createCalendarOneMonth(calendar, year, mon)\n{\n var row = createTiddlyElement(calendar, "tr", null, null, null);\n createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);\n row = createTiddlyElement(calendar, "tr", null, null, 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, "<", "Previous year", 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 yearHeader.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?22:19);//wn**\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, ">", "Next year", 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 back.align = "center";\n back.style.background = config.macros.calendar.monthbg;\n\n/*\n back.setAttribute("colSpan", 2);\n\n var backYearHandler = function() {\n var newyear = year-1;\n removeChildren(cal);\n cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, mon);\n };\n createTiddlyButton(back, "<<", "Previous year", backYearHandler);\n*/\n var backMonHandler = function() {\n var newyear = year;\n var newmon = mon-1;\n if(newmon == -1) { newmon = 11; newyear = newyear-1;}\n removeChildren(cal);\n cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, newmon);\n };\n createTiddlyButton(back, "<", "Previous month", backMonHandler);\n\n\n month = createTiddlyElement(row, "td", null, "calendarMonthname", name)\n// month.setAttribute("colSpan", 3);\n// month.setAttribute("colSpan", 5);\n month.setAttribute("colSpan", config.options.chkDisplayWeekNumbers?6:5);//wn**\n\n var fwd = createTiddlyElement(row, "td", null, null, null);\n fwd.align = "center";\n fwd.style.background = config.macros.calendar.monthbg; \n\n// fwd.setAttribute("colSpan", 2);\n var fwdMonHandler = function() {\n var newyear = year;\n var newmon = mon+1;\n if(newmon == 12) { newmon = 0; newyear = newyear+1;}\n removeChildren(cal);\n cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, newmon);\n };\n createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);\n/*\n var fwdYear = createTiddlyElement(row, "td", null, null, null);\n var fwdYearHandler = function() {\n var newyear = year+1;\n removeChildren(cal);\n cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, mon);\n };\n createTiddlyButton(fwd, ">>", "Next year", fwdYearHandler);\n*/\n } else {\n month = createTiddlyElement(row, "td", null, "calendarMonthname", name)\n //month.setAttribute("colSpan", 7);\n month.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?8:7);//wn**\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 if (config.options.chkDisplayWeekNumbers) createTiddlyElement(row, "td");//wn**\n for(var j = 0; j < 7; j++) {\n var d = j + (config.options.txtCalFirstDay - 0);\n if(d > 6) d = d - 7;\n cell = createTiddlyElement(row, "td", null, null, config.macros.calendar.daynames[d]);\n if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))\n cell.style.background = config.macros.calendar.weekendbg;\n }\n }\n}\n//}}}\n\n//{{{\nfunction createCalendarDays(row, col, first, max, year, mon)\n{\n var i;\n if (config.options.chkDisplayWeekNumbers){\n if (first<=max) {\n var ww = new Date(year,mon,first);\n createTiddlyElement(row, "td", null, null, "w"+ww.getWeek());//wn**\n }\n else createTiddlyElement(row, "td", null, null, null);//wn**\n }\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.options.txtCalFirstDay - 0);\n if(d > 6) d = d - 7;\n var daycell = createTiddlyElement(row, "td", null, null, null);\n var isaWeekend = ((d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+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",config.macros.calendar.journalDateFmt,true, isaWeekend); // ELS 5/29/06 - use journalDateFmt \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,14], null, 1);\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.options.txtCalFirstDay-0);\n if(first1 < 0) first1 = first1 + 7;\n var day1 = -first1 + 1;\n var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);\n if(first2 < 0) first2 = first2 + 7;\n var day2 = -first2 + 1;\n var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);\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.options.txtCalFirstDay-0);\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 { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }", "calendarStyles");\n//}}}\n
These configuration options enable you to customize the default behaviour of this wiki. They are saved locally as cookies, just like other TiddlyWiki configuration options.\n\nThis is the tag used for the "reference" context, used to identify tiddlers that show up in the [[Reference]] list: \n<<option txtGTDReferenceContext>>\n\nThis is the tag used for the "someday-maybe" context, used to identify tiddlers that show up in the [[Someday-Maybe]] list:\n<<option txtGTDSomedayContext>>\n\nThis is the tag used for the "unfiled" context, used to tag actions when the context is not known (such as a deleted context):\n<<option txtGTDUnfiledContext>>\n\nThis value, if specified, is the number of days to keep completed actions in context and review action lists (leave blank to show all unarchived, completed actions):\n<<option txtGTDActionAging>>\n\n<<option chkGTDFancyStyle>> Use this checkbox to enable or disable the extended (fancy) GTD style specified by the GTDTWStyleSheet (you will need to reload the page to see your change)\n\n<<option chkGTDLazyAutoSave>> Use this checkbox to enable or disable "lazy" autosaving of changes to your document. If turned on, then the autosave will fire every <<option txtGTDLazyAutoSaveInterval>> seconds.\n
/***\n|''Name:''|DatePlugin|\n|''Source:''|http://www.TiddlyTools.com/#DatePlugin|\n|''Author:''|Eric Shulman - ELS Design Studios|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|''~CoreVersion:''|2.0.10|\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\nThis plugin display formatted dates, for the specified year, month, day using number values or mathematical expressions such as (Y+1) or (D+30). Optionally, you can create a link from the formatted output to a 'dated tiddler' for quick blogging or create a popup menu that includes the dated tiddler link plus links to changes made on that date as well as links to any pending reminders for the coming 31 days (if the RemindersPlugin is installed). This plugin also provides a public API for easily incorporating formatted date output (with or without the links/popups) into other plugins, such as calendar generators, etc.\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.05.09 [2.2.1]'' added "todaybg" handling to set background color of current date. Also, honor excludeLists tag when getting lists of tiddlers. Based on suggestions by Mark Hulme.\n''2006.05.05 [2.2.0]'' added "linkedbg" handling to set background color when a 'dated tiddler' exists. Based on a suggestion by Mark Hulme.\n''2006.03.08 [2.1.2]'' add 'override leadtime' flag param in call to findTiddlersWithReminders(), and add "Enter a title" default text to new reminder handler. Thanks to Jeremy Sheeley for these additional tweaks.\n''2006.03.06 [2.1.0]'' hasReminders() nows uses window.reminderCacheForCalendar[] when present. If calendar cache is not present, indexReminders() now uses findTiddlersWithReminders() with a 90-day look ahead to check for reminders. Also, switched default background colors for autostyled dates: reminders are now greenish ("c0ffee") and holidays are now reddish ("ffaace").\n''2006.02.14 [2.0.5]'' when readOnly is set (by TW core), omit "new reminders..." popup menu item and, if a "dated tiddler" does not already exist, display the date as simple text instead of a link.\n''2006.02.05 [2.0.4]'' added 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]'' In 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]'' correct 'weekend' override detection logic in showDate()\n''2006.01.10 [2.0.1]'' allow 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]'' Update for TW2.0\nAdded parameter handling for 'linkformat'\n''2005.12.21 [1.2.2]'' FF'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]'' added support for "tiddler" dynamic date parameter\n''2005.11.06 [1.2.0]'' added support for "tiddler:title" dynamic date parameter\n''2005.11.03 [1.1.2]'' when 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]'' Temporarily 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]'' corrected 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]'' documentation and code cleanup\n''2005.10.31 [1.0.0]'' initial public release\n''2005.10.30 [0.9.0]'' pre-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: 2, revision: 1, date: new Date(2006,5,9)};\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 linkedbg: "#babb1e", // "babble"\n todaybg: "#ffab1e", // "fable"\n weekendbg: "#c0c0c0", // "cocoa"\n holidaybg: "#ffaace", // "face"\n modifiedsbg: "#bbeeff", // "beef"\n remindersbg: "#c0ffee", // "coffee"\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 (store.tiddlerExists(linkto)&&(config.macros.date.linkedbg!=""))\n { place.style.background = config.macros.date.linkedbg; }\n if (hasReminders(date)&&(config.macros.date.remindersbg!=""))\n { place.style.background = config.macros.date.remindersbg; }\n if(isToday(date)&&(config.macros.date.todaybg!=""))\n { place.style.background = config.macros.date.todaybg; }\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 (or just date, if readOnly) at the top...\n if (!readOnly || store.tiddlerExists(this.date.formatString(this.linkformat)))\n createTiddlyLink(popup,this.date.formatString(this.linkformat),true);\n else\n createTiddlyText(popup,this.date.formatString(this.linkformat));\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","excludeLists");\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(date,leadtime) // build list of tiddlers with reminders, hash indexed by reminder date\n{\n var reminders = { };\n if(window.findTiddlersWithReminders!=undefined) { // reminder plugin is installed\n // DEBUG var starttime=new Date();\n var t = findTiddlersWithReminders(date, [0,leadtime], null, null, 1);\n for(var i=0; i<t.length; i++) reminders[t[i].matchedDate]=true;\n // DEBUG var out="Found "+t.length+" reminders in "+((new Date())-starttime+1)+"ms\sn";\n // DEBUG out+="startdate: "+date.toLocaleDateString()+"\sn"+"leadtime: "+leadtime+" days\sn\sn";\n // DEBUG for(var i=0; i<t.length; i++) { out+=t[i].matchedDate.toLocaleDateString()+" "+t[i].params.title+"\sn"; }\n // DEBUG alert(out);\n }\n return reminders;\n}\n\nfunction hasReminders(date) // returns true if date has reminders\n{\n if (window.reminderCacheForCalendar)\n return window.reminderCacheForCalendar[date]; // use calendar cache\n if (!config.macros.date.reminders)\n config.macros.date.reminders = indexReminders(date,90); // create a 90-day leadtime reminder cache\n return (config.macros.date.reminders[date]);\n}\n\nfunction addRemindersToPopup(popup,when,format)\n{\n if(window.findTiddlersWithReminders==undefined) return; // reminder plugin not installed\n\n var indent = String.fromCharCode(160)+String.fromCharCode(160);\n var reminders=findTiddlersWithReminders(when, [0,31],null,null,1);\n var e=createTiddlyElement(popup,"div",null,null,"reminders:"+(!reminders.length?" none":""));\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<1)?"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 if (readOnly) return; // omit "new reminder..." link\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";\n c[i].value += " day:"+when.getDate();\n c[i].value += " month:"+(when.getMonth()+1);\n c[i].value += " year:"+when.getFullYear();\n c[i].value += ' title:"Enter a title" >>';\n }\n };\n}\n//}}}\n
//{{{\n\nconfig.macros.date.holidays=[ ]; // use reminders instead\n\nif (config.options.chkGTDFancyStyle) {\n // these colours are somewhat friendlier to the default d3 menu colour scheme\n config.macros.calendar.weekendbg= "seagreen";\n config.macros.calendar.monthbg = "transparent";\n\n config.macros.date.weekendbg="seagreen";\n config.macros.date.holidaybg="seagreen";\n config.macros.date.modifiedsbg="transparent";\n config.macros.date.remindersbg="red";\n}\n\n\n//}}}
[[Accueil]]
//par Yvan « Arkha » B.// \nLa gestion de la défense peut être simplifiée ou amplifiée de bien des manières.\n!Défense passive\nA la place d'une défense aléatoire (au d20), il est possible d'utiliser une défense fixe pour fluidifier le jeu. C'est notamment préférable pour le conteur lorsqu'il a de nombreux adversaires à opposer aux personnages.\nLa défense utile est alors égale à Défense+10.\n//Atout possible// : ''Prescience de combat'' - Vous avez parfois le sentiment d'avoir un temps d'avance sur vos adversaires. Votre défense passive est égale à Défense + 12. Si vous reprenez cet atout, vous gagnez +2 à chaque fois.\n!Esquive\nSi vous utilisez généralement la défense fixe, vous pouvez décider d'esquiver volontairement un coup en lançant 1d20. \n!Parade\nLa parade est une défense spéciale qui s'effectue en utilisant une arme ou un bouclier. Vous pouvez alors faire un jet d'Attaque à la place du jet de défense. Plusieurs subtilités s'appliquent alors :\n*Une parade est une action qui occupe l'arme. Vous perdez une action avec cette arme - comme la possibilité d'attaquer par exemple, ou le bonus de défense dans le cas d'un bouclier. \n*Si vous combattez à deux armes ou avec une arme double comme le bâton, vous perdez l'une de vos attaques et la parade a un malus de -2 (comme l'attaque équivalente).\n*Si vous avez des attaques supplémentaires, les malus cumulatifs s'appliquent à la ou les parades effectuées.\n*Les armes de professionnel ont un bonus de +2 à la parade ; les armes de brutasse ont un bonus de +4 à la parade ; les boucliers offrent leur bonus de défense aux différentes parades mais le perdent pour les autres défenses du tour.\n*Bien entendu, si vous vous battez à mains nues, vous ne pouvez pas parer une arme à moins d'accepter de subir 1d6 points de dégâts (en cas de parade réussie). Bien entendu, toute les protections s'appliquent sur ces dégâts.\n
//Par ''Poulpy''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>Voici un petit article sur ce qui me semble nécessaire d'adapter pour pouvoir jouer dans l'univers d'Eberron avec le dK.\nL'idée principale est de simplifier, quitte à trancher dans le tas (comme je l'ai fait avec les Shifters), et d'adapter afin de garder le coté pulp et fun du dK sans risquer de le diluer en voulant tout retranscrire.>>\n!Eberron dK \nLe monde de Eberron est je pense très facilement adaptable au dK - après tout il a été créé par Keith Baker pour être vraiment le nouvel univers « standard » pour D&D3. \nDu coup, les adaptations techniques à effectuer sont relativement mineures : une liste des peuples jouable, un atout pour représenter les dragonmarks, une petite synthèse des styles de magie utilisables et c’est parti ! Je pense qu’on peut, à partir de ce moment-là, utiliser tel quel le Eberron Campaign Setting (je rajouterai sûrement un petit bestiaire plus tard).\n!!Les peuples\nVoici les caractéristiques des atouts de peuple disponibles dans Eberron.\n!!!Changelins\n*''Cents visages'' : un changelin peut utiliser cet atout sans aucun équipement particulier de déguisement, étant naturellement capable de modifier ses traits, sa taille et sa pigmentation (pour utiliser ce pouvoir efficacement pour copier quelqu’un, le changelin devra bien sûr prendre au moins un rang dans la compétence Déguisement).\n*Psychologie +2.\n>''Commentaires'' : Facile a adapter, le don Cents visages semble spécialement là pour émuler leur capacités de métamorphe. J’ai gardé le bonus de Psychologie plutôt que celui sur les jets de résistance aux pouvoirs mentaux afin d’éviter de faire redondant avec la capacités des elfes et pour renforcer leur coté caméléon sociaux.\n!!!Nains\n*Constitution +1, Charisme -1\n*Vision thermique.\n*Métier (forgeron ou mineur) à +4.\n!!!Elfes\n*Dextérité +1, Constitution -1.\n*Vision nocturne.\n*Réfractaire aux sorts affectant l’esprit (+4 aux jet de sauvegarde).\n!!!Gnomes\n*Constitution +1, Force -1.\n*Petit.\n*Réfractaire aux illusions (+4 aux jets de sauvegarde).\n>''Commentaires'' : J’ai enlevé le défaut de ne pas être pris au sérieux par les grandes personnes, les gnomes de Khorvaire étant reconnus comme de très grands savants et ingénieurs.\n!!!Demi-elfe\n>''Commentaires'' : Je n’ai pas fait d’adaptation technique des demi-elfes, ceux-ci étant trop proche des humains. Un joueur souhaitant en jouer un devra simplement l’indiquer dans son background, éventuellement avec l’atout Peuple : elfe s'il veut en jouer un chez qui l’héritage elfique est particulièrement présent. Le personnage peut prétendre aux marques draconiques des orages et à celles de la détection.\n!!!Demi-orques\n*Force +1, Charisme -1\n*Vision thermique.\n*Grand.\n>''Commentaires'' : j’ai rééquilibré le demi-orque que je trouve furieusement mal équilibré en d20.\n!!!Halflings\n*Dextérité +1, Sagesse -1.\n*Petit.\n*Bonus de +4 en Métier (cuisinier) ou de +2 en survie.\n>''Commentaires'' : le bonus de compétence à choisir permet à la fois de simuler les halflings citadins souvent guérisseurs, aubergistes ou simplement bons vivants et ceux vivant en nomades dans les plaines de Talenta.\n!!!Kalashtar\n*Peut lancer naturellement et gratuitement des sorts du domaine esprit et du style psi de difficulté maximum 10 et niveau amateur.\n*Réfractaire aux sorts affectant l’esprits (+4 aux jet de sauvegarde).\n>''Commentaires'' : facile à adapter, je pense que cette adaptation fait bien ressortir le coté psi naturel du Kalashtar. Pour ce qui est du tabou associé a leurs pouvoir, je verrai bien un truc du style : « ne jamais venir en aide a un être des cauchemars (Quori) ».\n!!!Shifters\n*Dextérité +1, Intelligence -1.\n*Vision nocturne.\n*Une capacité au choix parmi: armes naturelles (griffes ou crocs, dégâts 2d6), armure naturelle de 4 (non cumulable avec une armure, le personnage profite de la meilleure des deux protections), +2 en Escalade, peut se déplacer de 3 mètres de plus par tour ou l’atout //Sixième sens//. De plus, quand le personnage gagne un niveau, il peut choisir une autre de ces capacités à la place d’un atout.\n>''Commentaires'' : j’ai fait sauter le malus de charisme car je pense que le coté animal du shifter peut donner un coté attirant au personnage. J’ai fait sauter le nombre d’utilisations par jour et la limite dans le temps des capacités afin d’en simplifier l’utilisation, mais pour compenser, elle ne donne plus un bonus de caractéristiques.\n!!!Warforged\n*Construction vivante : immunités aux poisons, maladie, fatigue, faim et soif. Ne récupère par ses points de vie normalement (doit être réparer avec un métier correspondant, jet diff 15, guérit de 1d6 par degrés de compétences). Il est affecté par les sorts ou effets affectant spécifiquement les objets (tel qu’un sort faisant rouiller le métal).\n*Constitution +1, Charisme -1\n*Armure naturelle de 4, ne peut pas porter d’autre armure.\n*Ajoute sa Force aux dégâts et peut causer des blessures graves a mains nues.\n*Renforcement vital.\n>''Commentaires'' : Je doit avouer que c’est celui qui m’a donné le plus de mal, mais je pense que ça peut coller comme cela - reste à le tester en jeu.\n!!Nouveaux atouts\n''Marque draconique'' (atout héroïque) - Votre personnage porte une marque draconique, l’un de ces tatouages mystiques qui apparaissent spontanément chez certains. Cela permet à votre personnage de choisir une maison draconique et d’avoir une marque conférant un pouvoir magique.\nCe pouvoir est créé de la manière suivante : il doit avoir un rapport avec le thème de la maison choisie, il doit être de niveau amateur et avoir une difficulté hors incantation (toutes les marques s’activent en une action) de 20 maximum. Ce sort est gratuit à utiliser, mais un personnage ne peut s’en servir qu’un nombre de fois par jour égal a son score de sagesse +1 et il est considéré comme ayant un score égal à son niveau dans la compétence de style (avec un bonus égale aux deux caractéristiques les plus hautes du personnages) pour tous les paramètres et jets de sauvegardes associés.\nDe plus, le porteur d’une marque gagne un bonus de +2 dans une compétence en fonction de sa maison.\nLes maisons sont :\n*Medani (demi-elfes, marque de la détection, Perception +2).\n*Tharashk (demi-orques et humains, marque de la recherche, Fouille +2).\n*Vadalis (humains, marque du dressage, Dressage +2).\n*Jorasco (halflings, marque de la guérison, Métier (guérisseur) +2).\n*Ghallanda (halflings, marque de l’hospitalité, Diplomatie +2).\n*Cannith (humains, marque de la création, un métier d’artisanat +2).\n*Orien (humains, marque du passage, Survie +2).\n*Sivis (gnomes, marque de l’écriture, une compétence de connaissance +2).\n*Deneith (humains, marque de la sentinelle, Psychologie +2).\n*Phiarlan (elfes, marque de l’ombre, Renseignements +2).\n*Thuranni (elfes, marque de l’ombre, Renseignements +2).\n*Lyrandar (demi-elfes, marque de l’orage, Acrobaties +2).\n*Kundarak (nains, marque de la garde, Fouille +2).\nLe personnage peut reprendre cet atout a partir du niveau 5 pour gagner un nouveau pouvoir mais conçu cette fois comme un sort de professionnel avec une difficulté maximum de 30. Il est encore une fois possible de reprendre cet atout a partir du niveau 9 pour avoir cette fois l’équivalent d’un sort de brutasse de difficulté maximale 40.\nCommentaires : J’ai un peu boosté cet atout afin de le rendre intéressant par rapport a la magie, il n’y a donc pas de dépense de PE et il est utilisable plusieurs fois par jour. Il reste cependant complètement a tester \n!!La Magie\nVoici une petite liste des styles de magie que je pense utilisables dans l’univers d’Eberron et le type de personnage généralement associé.\n''Occultisme'' : la magie de base, celle qui est enseigné par les Twelve ou le Arcane congress, c’est sûrement la plus répandue sur le continent de Khorvaire.\n''Prière'' : là aussi très répandue, généralement pratiquée par les prêtres et paladins des diverses religions de Khorvaire, ainsi que par certains croyants choisis par les dieux.\n''Calligraphie'' : cette magie, très proche visuellement des exorcistes shintos, utilise des formules inscrites sur des ofudas (des bouts de papiers sacrés) et peut très bien être utilisée par ceux qui ont étudié la magie de l’ancien empire gobelinoïde (qui est à plusieurs reprises décrites comme asiatisant). On peut aussi imaginer que les Gnomes de Zilargo ait développé une magie basée sur l’écriture étant donné leur amour pour les livres et textes.\n''Danse'' : je vois bien ce style de magie être pratiqué par des danseurs sacrés au sein de certaines cultures « primitives » comme les halflings des plaines de Talenta ou certains guerriers sacrés de la tribu Maruk qui garde le passage vers les Demon Wastes.\n''Graveur'' : la magie des runes est traditionnellement associée avec les nains, mais sur Khorvaire, elle est aussi pratiquée par les artificiers, ces magiciens qui se spécialisent dans l’enchantement et la création d’objets magiques, profitant ainsi du bonus de ce style.\n''Katas'' : là encore, c’est un style que je verrait bien pratiquer par les guerriers magiciens de l’ancien empire gob, ainsi que par certains ordres de moines (comme un monastère de la Silver Flame qui formerait des moines exorcistes, styles Kata et domaines : feu et conjuration par exemple).\n''Lames'' : c’est un style de magie que l’on peut retrouver dans tout les pays, pratiqué par des ordres de combattants magiciens comme les lames-sorcières des elfes de Valenar ou des ~Chevaliers-Necromantiques de Karrnath.\n''Musique'' : simple et efficace pour retranscrire les bardes dans l’univers d’Eberron.\n''Nature'' : je pense que c’est un style qui convient parfaitement aux druides du continent de Khorvaire (entre autres, ceux qui agissent dans les Eldeen Reaches).\n''Psi'' : les psioniques existent dans le monde de Eberron - il s’agit en général de Kalashtar ou de personnes qui, pour une raison ou une autre, ont des liens avec le plan des rêves et des cauchemars.\n''Sacrifice'' : le style de magie idéal pour ses tarés du culte de Blood of Vol.
<<gradient horiz #bbbbbb #eeeeee #ffffff>>Comment gérer le stress et la folie dans un environnement que l'on souhaite dur et implacable ? Voici une solution...>>\nL'équilibre est une caractéristique secondaire qui commence à zéro et peut être positive ou négative. Elle représente votre état d’esprit d'un point de vue clinique et sanitaire. Un équilibre positif indique que votre personnage est sain et en pleine possession de ses moyens. Quand la raison défaille, le personnage commence à être de plus en plus détaché, isolé… de moins en moins humain. L’un des plus sûrs moyens de perdre de la raison est de fricoter avec les horreurs de ce monde.\nL'équilibre donne un bonus ou un malus équivalent à tous les jets de sauvegarde et à la plupart des jets d’interaction sociale (Diplomatie, Bluff - et à l'inverse, Intimidation).\nIl y a plusieurs situations qui peuvent vous faire perdre de l'équilibre : apprendre des sortilèges complexes ou horrifiques, voir des créatures monstrueuses sans y être préparé (et, parfois, même en y étant préparé), vivre des situations de stress intense dans un environnement extrêmement violent (zone de guerre, attentat terroriste, violence routière exacerbée...)\nDans ces situations, vous devez faire un test de sauvegarde contre 20 ou perdre un point d'équilibre. Un modificateur (ou des dK) peut être appliqué à la difficulté selon les situations (ou les créatures - croiser un dieu ancien et affamé peut donner une bonne poignée de dK de modificateurs de circonstance). Des amis peuvent vous aider à passer cette épreuve en vous accordant des bonus au jet (voir les règles sur l'amitié).\nVous regagnez de l'équilibre à chaque fois que vous gagnez un point de caractéristique - bien que vous ne puissiez pas dépasser zéro par ce biais. Vous pouvez regagner un point et passer éventuellement en positif lorsque vous êtes sincèrement amoureux ou quand des amis proches vous entourent et vous aident (voir les règles sur l'amitié). Chaque semaine passée avec des gens qui ont au moins un point d'amitié, ou pour qui vous avez au moins un point d'amour, vous permet de faire un jet de sauvegarde contre 25. En cas de succès, vous regagnez un point d'équilibre, y compris pour passer au dessus de 0. Vous ne pouvez pas avoir plus de deux points d'équilibre positif.\nDes traitements sont disponibles pour les personnages souffrant de la perte de leur équilibre, mais ce n’est pas une option facile. Les psychiatres compétents sont peu nombreux et leurs méthodes parfois délicates. Il faut un mois de traitement dans un centre de soin adapté (ou un lieu calme) pour regagner un point d'équilibre, sans pouvoir dépasser 0. \nL'équilibre peut être un bon guide pour jouer les personnages. À -1 le héros est nerveux et agité. À -2, la pauvre âme commence à être aisément distraite, elle s’énerve facilement et connaît des crises de violence. À -3, le personnage est froid et peu empathique, il connaît des accès de violence émotionnelle. Au-delà, le personnage devient violent et imprévisible. Il commence à se parler à lui-même ou à des gens invisibles et frôle la folie pure et simple.
/***\n''Export Tiddlers Plugin for TiddlyWiki version 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#ExportTiddlersPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nWhen many people edit copies of the same TiddlyWiki document, the ability to easily copy and share these changes so they can then be redistributed to the entire group is very important. This ability is also 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\nExportTiddlersPlugin let you ''select and extract tiddlers from your ~TiddlyWiki documents and save them to a local file'' or a remote server (requires installation of compatible server-side scripting, still under development...). An interactive control panel lets you specify a destination, and then select which tiddlers to export. A convenient 'selection filter' helps you pick desired tiddlers by specifying a combination of modification dates, tags, or tiddler text to be matched or excluded. ''Tiddler data can be output as ~TiddlyWiki "storeArea ~DIVs" that can be imported into another ~TiddlyWiki or as ~RSS-compatible XML that can be published for RSS syndication.''\n\n!!!!!Inline interface (live)\n<<<\n<<exportTiddlers inline>>\n<<<\n!!!!!Usage\n<<<\nOptional "special tiddlers" used by this plugin:\n* SiteUrl^^\nURL for official server-published version of document being viewed\ndefault: //none//^^\n* SiteHost^^\nhost name/address for remote server (e.g., "www.server.com" or "192.168.1.27")\ndefault: //none//^^\n* SitePost^^\nremote path/filename for submitting changes (e.g., "/cgi-bin/submit.cgi")\ndefault: //none//^^\n* SiteParams^^\narguments (if any) for server-side receiving script\ndefault: //none//^^\n* SiteID^^\nusername or other authorization identifier for login-controlled access to remote server\ndefault: current TiddlyWiki username (e.g., "YourName")^^\n* SiteDate^^\nstored date/time stamp for most recent published version of document\ndefault: current document.modified value (i.e., the 'file date')^^\n<<<\n!!!!!Example\n<<<\n<<exportTiddlers>>\n<<<\n!!!!!Installation\n<<<\nImport (or copy/paste) the following tiddlers into your document:\n''ExportTiddlersPlugin'' (tagged with <<tag systemConfig>>)\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add "< < exportTiddlers > >" macro^^\n<<<\n!!!!!Revision History\n<<<\n''2006.02.12 [2.1.2]''^^\nadded var to unintended global 'tags' in matchTags(). Avoids FF1501 bug when filtering by tags. (based on report by TedPavlic)\n''2006.02.04 [2.1.1]''^^\nadded var to variables that were unintentionally global. Avoids FireFox 1.5.0.1 crash bug when referencing global variables\n''2006.02.02 [2.1.0]''^^\nAdded support for output of complete TiddlyWiki documents. Let's you use ExportTiddlers to generate 'starter' documents from selected tiddlers.^^\n''2006.01.21 [2.0.1]''^^\nDefer initial panel creation and only register a notification function when panel first is created\nin saveChanges 'hijack', create panel as needed. Note: if window.event is not available to identify the click location, the export panel is positioned relative to the 'tiddlerDisplay' element of the TW document.\n^^\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^^\n''2005.12.24 [0.9.5]''^^\nMinor adjustments to CSS to force correct link colors regardless of TW stylesheet selection\n^^\n''2005.12.16 [0.9.4]''^^\nDynamically create/remove exportPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding.\n^^\n''2005.11.15 [0.9.2]''^^\nadded non-Ajax post function to bypass javascript security restrictions on cross-domain I/O. Moved AJAX functions to separate tiddler (no longer needed here). Generalized HTTP server to support UnaWiki servers\n^^\n+++[previous releases...]\n''2005.11.08 [0.9.1]''^^\nmoved HTML, CSS and control initialization into exportInit() function and call from macro handler instead of at load time. This allows exportPanel to be placed within the same containing element as the "export tiddlers" button, so that relative positioning can be achieved.\n^^\n''2005.10.28 [0.9.0]''^^\nadded 'select opened tiddlers' feature\nBased on a suggestion by Geoff Slocock\n^^\n''2005.10.24 [0.8.3]''^^\nCorrected hijack of 'save changes' when using http:\n^^\n''2005.10.18 [0.8.2]''^^\nadded AJAX functions\n^^\n''2005.10.18 [0.8.1]''^^\nCorrected timezone handling when filtering for date ranges.\nImproved error checking/reporting for invalid filter values and filters that don't match any tiddlers.\nExporting localfile-to-localfile is working for IE and FF\nExporting server-to-localfile works in IE (after ActiveX warnings), but has security issues in FF\nCross-domain exporting (localfile/server-to-server) is under development\nCookies to remember filter settings - coming soon\nMore style tweaks, minor text changes and some assorted layout cleanup.\n^^\n''2005.10.17 [0.8.0]''^^\nFirst pre-release.\n^^\n''2005.10.16 [0.7.0]''^^\nfilter by tags\n^^\n''2005.10.15 [0.6.0]''^^\nfilter by title/text\n^^\n''2005.10.14 [0.5.0]''^^\nexport to local file (DIV or XML)\n^^\n''2005.10.14 [0.4.0]''^^\nfilter by start/end date\n^^\n''2005.10.13 [0.3.0]''^^\npanel interaction\n^^\n''2005.10.11 [0.2.0]''^^\npanel layout\n^^\n''2005.10.10 [0.1.0]''^^\ncode framework\n^^\n''2005.10.09 [0.0.0]''^^\ndevelopment started\n^^\n===\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n// // +++[version]\n//{{{\nversion.extensions.exportTiddlers = {major: 2, minor: 1, revision: 2, date: new Date(2006,2,12)};\n//}}}\n// //===\n\n// // +++[macro handler]\n//{{{\nconfig.macros.exportTiddlers = {\n label: "export tiddlers",\n prompt: "Copy selected tiddlers to an export document",\n datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss" // for "filter date/time" edit fields\n};\n\nconfig.macros.exportTiddlers.handler = function(place,macroName,params) {\n if (params[0]!="inline")\n { createTiddlyButton(place,this.label,this.prompt,onClickExportMenu); return; }\n var panel=createExportPanel(place);\n panel.style.position="static";\n panel.style.display="block";\n}\n\nfunction createExportPanel(place) {\n var panel=document.getElementById("exportPanel");\n if (panel) { panel.parentNode.removeChild(panel); }\n setStylesheet(config.macros.exportTiddlers.css,"exportTiddlers");\n panel=createTiddlyElement(place,"span","exportPanel",null,null)\n panel.innerHTML=config.macros.exportTiddlers.html;\n exportShowPanel(document.location.protocol);\n exportInitFilter();\n refreshExportList(0);\n store.addNotification(null,refreshExportList); // refresh listbox after every tiddler change\n return panel;\n}\n\nfunction onClickExportMenu(e)\n{\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("exportPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=createExportPanel(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\n// // +++[Hijack saveChanges] diverts 'notFileUrlError' to display export control panel instead\n//{{{\nwindow.coreSaveChanges=window.saveChanges;\nwindow.saveChanges = function()\n{\n if (document.location.protocol=="file:") { coreSaveChanges(); return; }\n var e = window.event;\n var parent=e?resolveTarget(e).parentNode:document.body;\n var panel = document.getElementById("exportPanel");\n if (panel==undefined || panel.parentNode!=parent) panel=createExportPanel(parent);\n exportShowPanel(document.location.protocol);\n if (parent==document.body) { panel.style.left="30%"; panel.style.top="30%"; }\n panel.style.display = "block" ;\n}\n//}}}\n// //===\n\n// // +++[IE needs explicit scoping] for functions called by browser events\n//{{{\nwindow.onClickExportMenu=onClickExportMenu;\nwindow.onClickExportButton=onClickExportButton;\nwindow.exportShowPanel=exportShowPanel;\nwindow.exportShowFilterFields=exportShowFilterFields;\nwindow.refreshExportList=refreshExportList;\n//}}}\n// //===\n\n// // +++[CSS] for floating export control panel\n//{{{\nconfig.macros.exportTiddlers.css = '\s\n#exportPanel {\s\n display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;\s\n background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\s\n padding: 0.5em; margin:0em; -moz-border-radius:1em;\s\n}\s\n#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\s\n#exportPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\s\n#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\s\n#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\s\n#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\s\n#exportPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\s\n#exportPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\s\n#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\s\n#exportPanel .rad { width:auto; }\s\n#exportPanel .chk { width:auto; }\s\n#exportPanel .btn { width:auto; }\s\n#exportPanel .btn1 { width:98%; }\s\n#exportPanel .btn2 { width:48%; }\s\n#exportPanel .btn3 { width:32%; }\s\n#exportPanel .btn4 { width:24%; }\s\n#exportPanel .btn5 { width:19%; }\s\n';\n//}}}\n// //===\n\n// // +++[HTML] for export control panel interface\n//{{{\nconfig.macros.exportTiddlers.html = '\s\n<!-- output target and format -->\s\n<table cellpadding="0" cellspacing="0"><tr><td width=50%>\s\n export to\s\n <select size=1 id="exportTo" onchange="exportShowPanel(this.value);">\s\n <option value="file:" SELECTED>this computer</option>\s\n <option value="http:">web server (http)</option>\s\n <option value="https:">secure web server (https)</option>\s\n <option value="ftp:">file server (ftp)</option>\s\n </select>\s\n</td><td width=50%>\s\n output format\s\n <select id="exportFormat" size=1>\s\n <option value="DIV">TiddlyWiki export file</option>\s\n <option value="TW">TiddlyWiki document</option>\s\n <option value="XML">RSS feed (XML)</option>\s\n </select>\s\n</td></tr></table>\s\n\s\n<!-- export to local file -->\s\n<div id="exportLocalPanel" style="margin-bottom:5px;margin-top:5px;">\s\nlocal path/filename<br>\s\n<input type="file" id="exportFilename" size=56 style="width:100%"><br>\s\n</div><!--panel-->\s\n\s\n<!-- export to http server -->\s\n<div id="exportHTTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;">\s\ndocument URL<br>\s\n<input type="text" id="exportHTTPSiteURL" onfocus="this.select()"><br>\s\nserver script / parameters<br>\s\n<input type="text" id="exportHTTPServerURL" onfocus="this.select()"><br>\s\n</div><!--panel-->\s\n\s\n<!-- export to ftp server -->\s\n<div id="exportFTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;">\s\n<table cellpadding="0" cellspacing="0" width="33%"><tr valign="top"><td>\s\n host server<br>\s\n <input type="text" id="exportFTPHost" onfocus="this.select()"><br>\s\n</td><td width="33%">\s\n username<br>\s\n <input type="text" id="exportFTPID" onfocus="this.select()"><br>\s\n</td><td width="33%">\s\n password<br>\s\n <input type="password" id="exportFTPPW" onfocus="this.select()"><br>\s\n</td></tr></table>\s\nFTP path/filename<br>\s\n<input type="text" id="exportFTPFilename" onfocus="this.select()"><br>\s\n</div><!--panel-->\s\n\s\n<!-- list of tiddlers -->\s\n<table><tr align="left"><td>\s\n select:\s\n <a href="JavaScript:;" id="exportSelectAll"\s\n onclick="onClickExportButton(this)" title="select all tiddlers">\s\n all </a>\s\n <a href="JavaScript:;" id="exportSelectChanges"\s\n onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\s\n changes </a> \s\n <a href="JavaScript:;" id="exportSelectOpened"\s\n onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\s\n opened </a> \s\n <a href="JavaScript:;" id="exportToggleFilter"\s\n onclick="onClickExportButton(this)" title="show/hide selection filter">\s\n filter </a> \s\n</td><td align="right">\s\n <a href="JavaScript:;" id="exportListSmaller"\s\n onclick="onClickExportButton(this)" title="reduce list size">\s\n – </a>\s\n <a href="JavaScript:;" id="exportListLarger"\s\n onclick="onClickExportButton(this)" title="increase list size">\s\n + </a>\s\n</td></tr></table>\s\n<select id="exportList" multiple size="10" style="margin-bottom:5px;"\s\n onchange="refreshExportList(this.selectedIndex)">\s\n</select><br>\s\n\s\n<!-- selection filter -->\s\n<div id="exportFilterPanel" style="display:none">\s\n<table><tr align="left"><td>\s\n selection filter\s\n</td><td align="right">\s\n <a href="JavaScript:;" id="exportHideFilter"\s\n onclick="onClickExportButton(this)" title="hide selection filter">hide</a>\s\n</td></tr></table>\s\n<div class="box">\s\n<input type="checkbox" class="chk" id="exportFilterStart" value="1"\s\n onclick="exportShowFilterFields(this)"> starting date/time<br>\s\n<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\s\n <select size=1 id="exportFilterStartBy" onchange="exportShowFilterFields(this);">\s\n <option value="0">today</option>\s\n <option value="1">yesterday</option>\s\n <option value="7">a week ago</option>\s\n <option value="30">a month ago</option>\s\n <option value="site">SiteDate</option>\s\n <option value="file">file date</option>\s\n <option value="other">other (mm/dd/yyyy hh:mm)</option>\s\n </select>\s\n</td><td width="50%">\s\n <input type="text" id="exportStartDate" onfocus="this.select()"\s\n onchange="document.getElementById(\s'exportFilterStartBy\s').value=\s'other\s';">\s\n</td></tr></table>\s\n<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\s\n onclick="exportShowFilterFields(this)"> ending date/time<br>\s\n<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\s\n <select size=1 id="exportFilterEndBy" onchange="exportShowFilterFields(this);">\s\n <option value="0">today</option>\s\n <option value="1">yesterday</option>\s\n <option value="7">a week ago</option>\s\n <option value="30">a month ago</option>\s\n <option value="site">SiteDate</option>\s\n <option value="file">file date</option>\s\n <option value="other">other (mm/dd/yyyy hh:mm)</option>\s\n </select>\s\n</td><td width="50%">\s\n <input type="text" id="exportEndDate" onfocus="this.select()"\s\n onchange="document.getElementById(\s'exportFilterEndBy\s').value=\s'other\s';">\s\n</td></tr></table>\s\n<input type="checkbox" class="chk" id=exportFilterTags value="1"\s\n onclick="exportShowFilterFields(this)"> match tags<br>\s\n<input type="text" id="exportTags" onfocus="this.select()">\s\n<input type="checkbox" class="chk" id=exportFilterText value="1"\s\n onclick="exportShowFilterFields(this)"> match titles/tiddler text<br>\s\n<input type="text" id="exportText" onfocus="this.select()">\s\n</div> <!--box-->\s\n</div> <!--panel-->\s\n\s\n<!-- action buttons -->\s\n<div style="text-align:center">\s\n<input type=button class="btn3" onclick="onClickExportButton(this)"\s\n id="exportFilter" value="apply filter">\s\n<input type=button class="btn3" onclick="onClickExportButton(this)"\s\n id="exportStart" value="export tiddlers">\s\n<input type=button class="btn3" onclick="onClickExportButton(this)"\s\n id="exportClose" value="close">\s\n</div><!--center-->\s\n';\n//}}}\n// //===\n\n// // +++[initialize interface]>\n// // +++[exportShowPanel(which)]\n//{{{\nfunction exportShowPanel(which) {\n var index=0; var panel='exportLocalPanel';\n switch (which) {\n case 'file:':\n case undefined:\n index=0; panel='exportLocalPanel'; break;\n case 'http:':\n index=1; panel='exportHTTPPanel'; break;\n case 'https:':\n index=2; panel='exportHTTPPanel'; break;\n case 'ftp:':\n index=3; panel='exportFTPPanel'; break;\n default:\n alert("Sorry, export to "+which+" is not yet available");\n break;\n }\n exportInitPanel(which);\n document.getElementById('exportTo').selectedIndex=index;\n document.getElementById('exportLocalPanel').style.display='none';\n document.getElementById('exportHTTPPanel').style.display='none';\n document.getElementById('exportFTPPanel').style.display='none';\n document.getElementById(panel).style.display='block';\n}\n//}}}\n// //===\n\n// // +++[exportInitPanel(which)]\n//{{{\nfunction exportInitPanel(which) {\n switch (which) {\n case "file:": // LOCAL EXPORT PANEL: file/path:\n // ** no init - security issues in IE **\n break;\n case "http:": // WEB EXPORT PANEL\n case "https:": // SECURE WEB EXPORT PANEL\n // url\n var siteURL=store.getTiddlerText("SiteUrl");\n if (store.tiddlerExists("unawiki_download")) {\n var theURL=store.getTiddlerText("unawiki_download");\n theURL=theURL.replace(/\s[\s[download\s|/,'').replace(/\s]\s]/,'');\n var title=(store.tiddlerExists("unawiki_host"))?"unawiki_host":"SiteHost";\n var theHost=store.getTiddlerText(title);\n if (!theHost || !theHost.length) theHost=document.location.host;\n if (!theHost || !theHost.length) theHost=title;\n siteURL=which+"//"+theHost+theURL\n }\n if (!siteURL) siteURL="SiteUrl";\n document.getElementById("exportHTTPSiteURL").value=siteURL;;\n // server script/params\n var title=(store.tiddlerExists("unawiki_host"))?"unawiki_host":"SiteHost";\n var theHost=store.getTiddlerText(title);\n if (!theHost || !theHost.length) theHost=document.location.host;\n if (!theHost || !theHost.length) theHost=title;\n // get POST\n var title=(store.tiddlerExists("unawiki_post"))?"unawiki_post":"SitePost";\n var thePost=store.getTiddlerText(title);\n if (!thePost || !thePost.length) thePost="/"+title;\n // get PARAMS\n var title=(store.tiddlerExists("unawiki_params"))?"unawiki_params":"SiteParams";\n var theParams=store.getTiddlerText(title);\n if (!theParams|| !theParams.length) theParams=title;\n var serverURL = which+"//"+theHost+thePost+"?"+theParams;\n document.getElementById("exportHTTPServerURL").value=serverURL;\n break;\n case "ftp:": // FTP EXPORT PANEL\n // host\n var siteHost=store.getTiddlerText("SiteHost");\n if (!siteHost || !siteHost.length) siteHost=document.location.host;\n if (!siteHost || !siteHost.length) siteHost="SiteHost";\n document.getElementById("exportFTPHost").value=siteHost;\n // username\n var siteID=store.getTiddlerText("SiteID");\n if (!siteID || !siteID.length) siteID=config.options.txtUserName;\n document.getElementById("exportFTPID").value=siteID;\n // password\n document.getElementById("exportFTPPW").value="";\n // file/path\n document.getElementById("exportFTPFilename").value="";\n break;\n }\n}\n//}}}\n// //===\n\n// // +++[exportInitFilter()]\n//{{{\nfunction exportInitFilter() {\n // TBD: persistent settings via local cookies\n // start date\n document.getElementById("exportFilterStart").checked=false;\n document.getElementById("exportStartDate").value="";\n // end date\n document.getElementById("exportFilterEnd").checked=false;\n document.getElementById("exportEndDate").value="";\n // tags\n document.getElementById("exportFilterTags").checked=false;\n document.getElementById("exportTags").value="not excludeExport";\n // text\n document.getElementById("exportFilterText").checked=false;\n document.getElementById("exportText").value="";\n // show/hide filter input fields\n exportShowFilterFields();\n}\n//}}}\n// //===\n\n// // +++[exportShowFilterFields(which)]\n//{{{\nfunction exportShowFilterFields(which) {\n var show;\n\n show=document.getElementById('exportFilterStart').checked;\n document.getElementById('exportFilterStartBy').style.display=show?"block":"none";\n document.getElementById('exportStartDate').style.display=show?"block":"none";\n var val=document.getElementById('exportFilterStartBy').value;\n document.getElementById('exportStartDate').value\n =getFilterDate(val,'exportStartDate').formatString(config.macros.exportTiddlers.datetimefmt);\n if (which && (which.id=='exportFilterStartBy') && (val=='other'))\n document.getElementById('exportStartDate').focus();\n\n show=document.getElementById('exportFilterEnd').checked;\n document.getElementById('exportFilterEndBy').style.display=show?"block":"none";\n document.getElementById('exportEndDate').style.display=show?"block":"none";\n var val=document.getElementById('exportFilterEndBy').value;\n document.getElementById('exportEndDate').value\n =getFilterDate(val,'exportEndDate').formatString(config.macros.exportTiddlers.datetimefmt);\n if (which && (which.id=='exportFilterEndBy') && (val=='other'))\n document.getElementById('exportEndDate').focus();\n\n show=document.getElementById('exportFilterTags').checked;\n document.getElementById('exportTags').style.display=show?"block":"none";\n\n show=document.getElementById('exportFilterText').checked;\n document.getElementById('exportText').style.display=show?"block":"none";\n}\n//}}}\n// //===\n// //===\n\n// // +++[onClickExportButton(which): control interactions]\n//{{{\nfunction onClickExportButton(which)\n{\n // DEBUG alert(which.id);\n var theList=document.getElementById('exportList'); if (!theList) return;\n var count = 0;\n var total = store.getTiddlers('title').length;\n switch (which.id)\n {\n case 'exportFilter':\n count=filterExportList();\n var panel=document.getElementById('exportFilterPanel');\n if (count==-1) { panel.style.display='block'; break; }\n theList.options[0].text=formatExportListHeader(count,total);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage("filtered "+theList.options[0].text);\n if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }\n break;\n case 'exportStart':\n exportTiddlers();\n break;\n case 'exportHideFilter':\n case 'exportToggleFilter':\n var panel=document.getElementById('exportFilterPanel')\n panel.style.display=(panel.style.display=='block')?'none':'block';\n break;\n case 'exportSelectChanges':\n var lastmod=new Date(document.lastModified);\n for (var t = 0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;\n theList.options[t].selected=(tiddler.modified>lastmod);\n count += (tiddler.modified>lastmod)?1:0;\n }\n theList.options[0].text=formatExportListHeader(count,total);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(theList.options[0].text);\n if (count==0) alert("There are no unsaved changes");\n break;\n case 'exportSelectAll':\n for (var t = 0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=true;\n count += 1;\n }\n theList.options[0].text=formatExportListHeader(count,count);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(theList.options[0].text);\n break;\n case 'exportSelectOpened':\n for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;\n var tiddlerDisplay = document.getElementById("tiddlerDisplay");\n for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {\n var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);\n for (var i = 0; i < theList.options.length; i++) {\n if (theList.options[i].value!=tiddler) continue;\n theList.options[i].selected=true; count++; break;\n }\n }\n theList.options[0].text=formatExportListHeader(count,total);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(theList.options[0].text);\n if (count==0) alert("There are no tiddlers currently opened");\n break;\n case 'exportListSmaller': // decrease current listbox size\n var min=5;\n theList.size-=(theList.size>min)?1:0;\n break;\n case 'exportListLarger': // increase current listbox size\n var max=(theList.options.length>25)?theList.options.length:25;\n theList.size+=(theList.size<max)?1:0;\n break;\n case 'exportClose':\n document.getElementById('exportPanel').style.display='none';\n break;\n }\n}\n//}}}\n// //===\n\n// // +++[list display]\n//{{{\nfunction formatExportListHeader(count,total)\n{\n var txt=total+' tiddler'+((total!=1)?'s':'')+" - ";\n txt += (count==0)?"none":(count==total)?"all":count;\n txt += " selected for export";\n return txt;\n}\n\nfunction refreshExportList(selectedIndex)\n{\n var theList = document.getElementById("exportList");\n var sort;\n if (!theList) return;\n // get the sort order\n if (!selectedIndex) selectedIndex=0;\n if (selectedIndex==0) sort='modified';\n if (selectedIndex==1) sort='title';\n if (selectedIndex==2) sort='modified';\n if (selectedIndex==3) sort='modifier';\n\n // get the alphasorted list of tiddlers\n var tiddlers = store.getTiddlers('title');\n // unselect headings and count number of tiddlers actually selected\n var count=0;\n for (var i=0; i<theList.options.length; i++) {\n if (theList.options[i].value=="") theList.options[i].selected=false;\n count+=theList.options[i].selected?1:0;\n }\n // disable "export" button if no tiddlers selected\n document.getElementById("exportStart").disabled=(count==0);\n // update listbox heading to show selection count\n if (theList.options.length)\n theList.options[0].text=formatExportListHeader(count,tiddlers.length);\n\n // if a [command] item, reload list... otherwise, no further refresh needed\n if (selectedIndex>3) return;\n\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++]=\n new Option(formatExportListHeader(0,tiddlers.length), "",false,false);\n theList.options[i++]=\n new Option(((sort=="title" )?">":indent)+' [by title]', "",false,false);\n theList.options[i++]=\n new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);\n theList.options[i++]=\n new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);\n // output the tiddler list\n switch(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 "modifier":\n case "modified":\n var tiddlers = store.getTiddlers(sort);\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });\n var lastSection = "";\n for(var t = 0; t < tiddlers.length; t++)\n {\n var tiddler = tiddlers[t];\n var theSection = "";\n if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();\n if (sort=="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 break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n}\n//}}}\n// //===\n\n// // +++[list filtering]\n//{{{\nfunction getFilterDate(val,id)\n{\n var result=0;\n switch (val) {\n case 'site':\n var timestamp=store.getTiddlerText("SiteDate");\n if (!timestamp) timestamp=document.lastModified;\n result=new Date(timestamp);\n break;\n case 'file':\n result=new Date(document.lastModified);\n break;\n case 'other':\n result=new Date(document.getElementById(id).value);\n break;\n default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31\n var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;\n var oneday=86400000;\n if (id=='exportStartDate')\n result=new Date((Math.floor(now/oneday)-val)*oneday+tz);\n else\n result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);\n break;\n }\n // DEBUG alert('getFilterDate('+val+','+id+')=='+result+"\snnow="+now);\n return result;\n}\n\nfunction filterExportList()\n{\n var theList = document.getElementById("exportList"); if (!theList) return -1;\n\n var filterStart=document.getElementById("exportFilterStart").checked;\n var val=document.getElementById("exportFilterStartBy").value;\n var startDate=getFilterDate(val,'exportStartDate');\n\n var filterEnd=document.getElementById("exportFilterEnd").checked;\n var val=document.getElementById("exportFilterEndBy").value;\n var endDate=getFilterDate(val,'exportEndDate');\n\n var filterTags=document.getElementById("exportFilterTags").checked;\n var tags=document.getElementById("exportTags").value;\n\n var filterText=document.getElementById("exportFilterText").checked;\n var text=document.getElementById("exportText").value;\n\n if (!(filterStart||filterEnd||filterTags||filterText)) {\n alert("Please set the selection filter");\n document.getElementById('exportFilterPanel').style.display="block";\n return -1;\n }\n if (filterStart&&filterEnd&&(startDate>endDate)) {\n var msg="starting date/time:\sn"\n msg+=startDate.toLocaleString()+"\sn";\n msg+="is later than ending date/time:\sn"\n msg+=endDate.toLocaleString()\n alert(msg);\n return -1;\n }\n\n // scan list and select tiddlers that match all applicable criteria\n var total=0;\n var count=0;\n for (var i=0; i<theList.options.length; i++) {\n // get item, skip non-tiddler list items (section headings)\n var opt=theList.options[i]; if (opt.value=="") continue;\n // get tiddler, skip missing tiddlers (this should NOT happen)\n var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; \n var sel=true;\n if ( (filterStart && tiddler.modified<startDate)\n || (filterEnd && tiddler.modified>endDate)\n || (filterTags && !matchTags(tiddler,tags))\n || (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))\n sel=false;\n opt.selected=sel;\n count+=sel?1:0;\n total++;\n }\n return count;\n}\n//}}}\n\n//{{{\nfunction matchTags(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 var 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("Error in tag filter '" + e + "'" ); }\n return false;\n}\n//}}}\n// //===\n\n// // +++[output data formatting]>\n// // +++[exportHeader(format)]\n//{{{\nfunction exportHeader(format)\n{\n switch (format) {\n case "TW": return exportTWHeader();\n case "DIV": return exportDIVHeader();\n case "XML": return exportXMLHeader();\n }\n}\n//}}}\n// //===\n\n// // +++[exportFooter(format)]\n//{{{\nfunction exportFooter(format)\n{\n switch (format) {\n case "TW": return exportDIVFooter();\n case "DIV": return exportDIVFooter();\n case "XML": return exportXMLFooter();\n }\n}\n//}}}\n// //===\n\n// // +++[exportTWHeader()]\n//{{{\nfunction exportTWHeader()\n{\n // Get the URL of the document\n var originalPath = document.location.toString();\n // Check we were loaded from a file URL\n if(originalPath.substr(0,5) != "file:")\n { alert(config.messages.notFileUrlError); return; }\n // Remove any location part of the URL\n var hashPos = originalPath.indexOf("#"); if(hashPos != -1) 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 // Load the original file\n var original = loadFile(localPath);\n if(original == null)\n { alert(config.messages.cantSaveError); return; }\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 { alert(config.messages.invalidFileError.format([localPath])); return; }\n return original.substr(0,posOpeningDiv+startSaveArea.length)\n}\n//}}}\n// //===\n\n// // +++[exportDIVHeader()]\n//{{{\nfunction exportDIVHeader()\n{\n var out=[];\n var now = new Date();\n var u = store.getTiddlerText("SiteUrl",null);\n var title = wikifyPlain("SiteTitle").htmlEncode();\n var subtitle = wikifyPlain("SiteSubtitle").htmlEncode();\n var user = config.options.txtUserName.htmlEncode();\n var twver = version.major+"."+version.minor+"."+version.revision;\n var pver = version.extensions.exportTiddlers.major+"."\n +version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;\n out.push("<html><body>");\n out.push("<style type=\s"text/css\s">");\n out.push("#storeArea {display:block;margin:1em;}");\n out.push("#storeArea div");\n out.push("{padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}");\n out.push("#javascriptWarning");\n out.push("{width:100%;text-align:left;background-color:#eeeeee;padding:1em;}");\n out.push("</style>");\n out.push("<div id=\s"javascriptWarning\s">");\n out.push("TiddlyWiki export file<br>");\n out.push("Source: <b>"+document.location+"</b><br>");\n out.push("Title: <b>"+title+"</b><br>");\n out.push("Subtitle: <b>"+subtitle+"</b><br>");\n out.push("Created: <b>"+now.toLocaleString()+"</b> by <b>"+user+"</b><br>");\n out.push("TiddlyWiki "+twver+" / "+"ExportTiddlersPlugin "+pver+"<br>");\n out.push("</div>");\n out.push("<div id=\s"storeArea\s">");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportDIVFooter()]\n//{{{\nfunction exportDIVFooter()\n{\n var out=[];\n out.push("</div></body></html>");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportXMLHeader()]\n//{{{\nfunction exportXMLHeader()\n{\n var out=[];\n var now = new Date();\n var u = store.getTiddlerText("SiteUrl",null);\n var title = wikifyPlain("SiteTitle").htmlEncode();\n var subtitle = wikifyPlain("SiteSubtitle").htmlEncode();\n var user = config.options.txtUserName.htmlEncode();\n var twver = version.major+"."+version.minor+"."+version.revision;\n var pver = version.extensions.exportTiddlers.major+"."\n +version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;\n out.push("<" + "?xml version=\s"1.0\s"?" + ">");\n out.push("<rss version=\s"2.0\s">");\n out.push("<channel>");\n out.push("<title>" + title + "</title>");\n if(u) out.push("<link>" + u.htmlEncode() + "</link>");\n out.push("<description>" + subtitle + "</description>");\n out.push("<language>en-us</language>");\n out.push("<copyright>Copyright " + now.getFullYear() + " " + user + "</copyright>");\n out.push("<pubDate>" + now.toGMTString() + "</pubDate>");\n out.push("<lastBuildDate>" + now.toGMTString() + "</lastBuildDate>");\n out.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");\n out.push("<generator>TiddlyWiki "+twver+" plus ExportTiddlersPlugin "+pver+"</generator>");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportXMLFooter()]\n//{{{\nfunction exportXMLFooter()\n{\n var out=[];\n out.push("</channel></rss>");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportData()]\n//{{{\nfunction exportData(theList,theFormat)\n{\n // scan export listbox and collect DIVs or XML for selected tiddler content\n var out=[];\n for (var i=0; i<theList.options.length; i++) {\n // get item, skip non-selected items and section headings\n var opt=theList.options[i]; if (!opt.selected||(opt.value=="")) continue;\n // get tiddler, skip missing tiddlers (this should NOT happen)\n var thisTiddler=store.getTiddler(opt.value); if (!thisTiddler) continue; \n if (theFormat=="TW") out.push(thisTiddler.saveToDiv());\n if (theFormat=="DIV") out.push(thisTiddler.title+"\sn"+thisTiddler.saveToDiv());\n if (theFormat=="XML") out.push(thisTiddler.saveToRss());\n }\n return out;\n}\n//}}}\n// //===\n// //===\n\n// // +++[exportTiddlers(): output selected data to local or server]\n//{{{\nfunction exportTiddlers()\n{\n var theList = document.getElementById("exportList"); if (!theList) return;\n\n // get the export settings\n var theProtocol = document.getElementById("exportTo").value;\n var theFormat = document.getElementById("exportFormat").value;\n\n // assemble output: header + tiddlers + footer\n var theData=exportData(theList,theFormat);\n var count=theData.length;\n var out=[]; var txt=out.concat(exportHeader(theFormat),theData,exportFooter(theFormat)).join("\sn");\n var msg="";\n switch (theProtocol) {\n case "file:":\n var theTarget = document.getElementById("exportFilename").value.trim();\n if (!theTarget.length) msg = "A local path/filename is required\sn";\n if (!msg && saveFile(theTarget,txt))\n msg=count+" tiddler"+((count!=1)?"s":"")+" exported to local file";\n else if (!msg)\n msg+="An error occurred while saving to "+theTarget;\n break;\n case "http:":\n case "https:":\n var theTarget = document.getElementById("exportHTTPServerURL").value.trim();\n if (!theTarget.length) msg = "A server URL is required\sn";\n if (!msg && exportPost(theTarget+encodeURIComponent(txt)))\n msg=count+" tiddler"+((count!=1)?"s":"")+" exported to "+theProtocol+" server";\n else if (!msg)\n msg+="An error occurred while saving to "+theTarget;\n break;\n case "ftp:":\n default:\n msg="Sorry, export to "+theLocation+" is not yet available";\n break;\n }\n clearMessage(); displayMessage(msg,theTarget);\n}\n//}}}\n// //===\n\n// // +++[exportPost(url): cross-domain post] uses hidden iframe to submit url and capture responses\n//{{{\nfunction exportPost(url)\n{\n var f=document.getElementById("exportFrame"); if (f) document.body.removeChild(f);\n f=document.createElement("iframe"); f.id="exportFrame";\n f.style.width="0px"; f.style.height="0px"; f.style.border="0px";\n document.body.appendChild(f);\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 d.location.replace(url);\n return true;\n}\n//}}}\n// //===\n
//Par ''Poulpy''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>
+++(gtdProjectsSliderState)[Projects]<<tiddler ProjectList>>===\n+++(gtdActionsSliderState)[Actions]<<list tagged context>>===\n+++(gtdReviewSliderState)[Review]\n*[[Summary Review]]\n*[[Project Review]]\n*[[Action Review]]\n*[[Reminders]]\n===\n\n<<newerTiddler button:"Create new project" name:"NewProject" tags:"project" template:"NewProjectTemplate">> <<newerTiddler button:"Create new context" name:"NewContext" tags:"context" template:"NewContextTemplate">> <<newerTiddler button:"Create new action" name:"NewAction" tags:"action" template:"NewActionTemplate">>\n[[Ticklers]] [[Reference]] [[Someday-Maybe]]\n+++[Calendar|Show a calendar]<<calendar thismonth>>===\n\n[[Configuration|Configuration Options]] [[Check for Updates|UpdateApplication]] [[Archives]]
/***\n|''Name:''|GTDPlugins|\n|''Description:''|Plugin to support Getting Things Done|\n|''Version:''|<<gtdVersion>>|\n|''Date:''|December 15, 2006|\n|''Source:''|http://www.dcubed.ca/|\n|''Author:''|Tom Otvos|\n|''~CoreVersion:''|2.0.11|\n|''Browser:''|Firefox 1.5+; InternetExplorer 6.0+|\n***/\n\n/***\n''Macros:''\n*{{{<<gtdAction "}}}//title//{{{" "}}}//context list//{{{">>}}}\n*{{{<<gtdActionList {"}}}//context list//{{{" | "*" | "@" {"all" | "noproject" | "projectonly"} }>>}}}\n** //if no parameters are specified, current context or project is used//\n** //specify "*" for actions across all projects, "@" for incomplete actions across all contexts (or "all" for all actions)//\n** //use "projectonly" or "noproject" to filter actions by project association//\n*{{{<<list tagged "}}}//tag list//{{{" {any | all}>>}}}\n** //if no parameters are specified, all tags are necessary//\n*{{{<<gtdActionCompleted>>}}}\n*{{{<<gtdToggleTag>>}}}\n*{{{<<gtdToggleState>>}}}\n*{{{<<importUpdates "}}}//url//{{{" {updates | all} "}}}//buttonTitle//{{{" "}}}//buttonHelp//{{{" "}}}//importTiddlers params...//{{{">>}}}\n*{{{<<gtdArchive { archive | unarchive | purge }>>}}}\n\n''Commands:''\n*{{{newAction}}}\n*{{{newProjectAction}}}\n*{{{changeContext}}}\n*{{{deleteAction}}}\n*{{{deleteContext}}}\n*{{{deleteProject}}}\n*{{{deleteProjectAll}}}\n*{{{projectify}}}\n\n''Wiki formatting:''\n*{{{..new action title|context}}}\n\n***/\n//{{{\n\nversion.extensions.GTDPlugins = {major: 1, minor: 1, revision: 0, patch: 0 };\n\nvar _GTD = {\n\n lazyAutoSave: 0,\n contextCache: null,\n usingProjectTags: true,\n\n initialize: function ()\n {\n var d = new Date();\n\n if (config.options.txtGTDReferenceContext == undefined) config.options.txtGTDReferenceContext = "reference";\n if (config.options.txtGTDSomedayContext == undefined) config.options.txtGTDSomedayContext = "someday";\n if (config.options.txtGTDUnfiledContext == undefined) config.options.txtGTDUnfiledContext = "unfiled";\n if (config.options.txtGTDActionAging == undefined) config.options.txtGTDActionAging = "";\n if (config.options.chkGTDFancyStyle == undefined) config.options.chkGTDFancyStyle = true;\n if (config.options.chkGTDLazyAutoSave == undefined) config.options.chkGTDLazyAutoSave = true;\n if (config.options.txtGTDLazyAutoSaveInterval == undefined) config.options.txtGTDLazyAutoSaveInterval = "60";\n \n // some tricks to work when our script is loaded from an external file...\n if (!store) config.notifyTiddlers.push( {name: "GTDStyleSheet", notify: refreshStyles} );\n if (!store && config.options.chkGTDFancyStyle) config.notifyTiddlers.push( {name: "GTDTWStyleSheet", notify: refreshStyles} );\n if (!store) config.notifyTiddlers.push( {name: null, notify: _GTD.refreshActionViews} );\n \n this.setReviewUpdate();\n this.setLazyAutoSave();\n \n if (!store) return;\n \n if ((version.major == 2 && version.minor < 1) || !store.tiddlerExists("d3 settings")) {\n // we force a changed() call on all projects, contexts, and actions, to enable them to set up their cross-references\n var tiddlers = [];\n tiddlers = tiddlers.concat(store.getTaggedTiddlers("project"), store.getTaggedTiddlers("context"), store.getTaggedTiddlers("action"));\n for (var i = 0; i < tiddlers.length; i++)\n tiddlers[i].changed();\n \n // if we have tiddler meta data, rebuild it\n if (version.major > 2 || version.minor > 0)\n this.rebuildMetaData();\n }\n else {\n this.initializeFromMetaData();\n this.usingProjectTags = false;\n }\n \n store.addNotification("GTDStyleSheet", refreshStyles);\n if (config.options.chkGTDFancyStyle) store.addNotification("GTDTWStyleSheet", refreshStyles);\n store.addNotification(null, _GTD.refreshActionViews);\n \n // force a display of release notes, if required\n var v = version.extensions.GTDPlugins;\n var releaseNotesTiddler = "About version " + v.major + '.' + v.minor + '.' + v.revision;\n if ((config.options.chkGTDReleaseNotes || config.options.chkGTDReleaseNotes == undefined) && store.tiddlerExists(releaseNotesTiddler)) {\n params = "open:\s"" + releaseNotesTiddler + "\s"";\n params = params.parseParams("open",null,false);\n config.options.chkGTDReleaseNotes = false;\n saveOptionCookie("chkGTDReleaseNotes");\n }\n\n if (version.major > 2 || version.minor > 0)\n pluginInfo.log.push('Initialized in ' + ((new Date()).getTime() - d.getTime()) + ' milliseconds');\n },\n \n rebuildMetaData: function()\n {\n pluginInfo.log.push('Rebuilding action metadata...');\n\n store.suspendNotifications();\n var tiddlers = store.getTaggedTiddlers("action");\n for (var i = 0; i < tiddlers.length; i++) {\n var t = tiddlers[i];\n store.setValue(t, "gtd");\n store.setValue(t, "gtd.context", t.gtdContextName);\n if (t.gtdProject) store.setValue(t, "gtd.project", t.gtdProject.title);\n if (t.gtdProject) store.setValue(t, "gtd.projectindex", t.gtdProject.gtdActions.indexOf(t));\n // booo...scary...strip out project tag\n if (t.gtdProject) t.tags.remove(t.gtdProject.title);\n }\n store.resumeNotifications();\n \n var tiddler = store.createTiddler("d3 conversion");\n var s = "Completed document conversion. Do not delete this tiddler unless you want to rebuild the action metadata.\sn\snThis tiddler also contains document-specific preferences which, if deleted, will revert to default settings.";\n tiddler.assign("d3 settings", s, config.options.txtUserName, new Date(), ["excludeLists"]);\n },\n \n initializeFromMetaData: function()\n {\n var tiddlers = store.getTaggedTiddlers("action");\n // ??? one possible optimization is to sort action list by project, to avoid repeatedly fetching project tiddler\n for (var i = 0; i < tiddlers.length; i++) {\n var t = tiddlers[i];\n t.gtdActionName = store.getValue(t, "title");\n t.gtdActionDone = this.tiddlerHasTag(t, "done");\n t.gtdProjectName = store.getValue(t, "gtd.project");\n t.gtdContextName = store.getValue(t, "gtd.context");\n if (t.gtdProjectName) {\n t.gtdProject = store.getTiddler(t.gtdProjectName);\n if (t.gtdProject) {\n if (t.gtdProject.gtdActions == undefined) t.gtdProject.gtdActions = [];\n t.gtdProject.gtdActions.push(t);\n }\n }\n }\n \n tiddlers = store.getTaggedTiddlers("project");\n for (i = 0; i < tiddlers.length; i++) {\n t = tiddlers[i];\n if (t.gtdActions) {\n t.gtdActions.sort( \n function(a,b) { var ai = parseInt(store.getValue(a, "gtd.projectindex")), bi = parseInt(store.getValue(b, "gtd.projectindex")); return (ai < bi) ? -1 : +1; }\n );\n }\n else\n t.gtdActions = [];\n this.setNextAction(t);\n }\n \n tiddlers = this.getCachedContexts();\n for (i = 0; i < tiddlers.length; i++)\n tiddlers[i].gtdContextName = tiddlers[i].title;\n },\n \n tiddlerHasTag: function (tiddler, tag)\n {\n if (typeof(tiddler) == "string") tiddler = store.getTiddler(tiddler);\n if (tiddler.tags.length == 0) return false;\n return (tiddler.tags.find(tag) != null);\n },\n \n tiddlerSwapTag: function (tiddler, oldTag, newTag)\n {\n for (var i = 0; i < tiddler.tags.length; i++)\n if (tiddler.tags[i] == oldTag) {\n tiddler.tags[i] = newTag;\n return true;\n }\n return false;\n },\n \n setExtendedValue: function (tiddler, name, value)\n {\n // this bottleneck safely sets an extended data value, quietly ignoring the request\n // if the setValue function is not available AND it disables notifications during\n // the setValue if it is defined\n \n if (version.major > 2 || version.minor > 0) {\n store.suspendNotifications();\n store.setValue(tiddler, name, value);\n store.resumeNotifications();\n }\n },\n \n tiddlerHasChanged: function (tiddler, doSave)\n {\n tiddler.changed();\n //story.setDirty(tiddler.title, true);\n store.setDirty(true);\n if (doSave == undefined) doSave = true;\n if (doSave) tiddler.modified = new Date();\n if (config.options.chkAutoSave && doSave)\n saveChanges();\n else if (doSave)\n this.lazyAutoSave++;\n },\n \n tiddlerAgeInDays: function(tiddler)\n {\n var now = new Date();\n return (now.getTime() - tiddler.modified.getTime()) / 1000 / 86400;\n },\n \n filteredActionTags: function (tags, filterTags)\n {\n var actionTags = [], specialTags = [ "action", "done", "floating", "action-archive" ];\n specialTags = specialTags.concat(filterTags);\n for (var i = 0; i < tags.length; i++)\n if (!specialTags.contains(tags[i])) actionTags.push(tags[i]);\n return actionTags;\n },\n \n toggleTag: function (tiddler, tag, toggle)\n {\n var tagIndex = -1;\n for (var i = 0; i < tiddler.tags.length; i++)\n if (tiddler.tags[i] == tag) {\n tagIndex = i;\n break;\n }\n \n if (toggle && tagIndex == -1) {\n tiddler.tags.push(tag);\n }\n else if (!toggle && tagIndex != -1) {\n tiddler.tags.splice(tagIndex, 1);\n }\n },\n \n getTiddlerElement: function (tiddler)\n {\n return document.getElementById(story.idPrefix + tiddler.title);\n },\n \n refreshActionViews: function (tiddler)\n {\n if (tiddler) {\n if (typeof(tiddler) == "string") tiddler = store.getTiddler(tiddler);\n if (tiddler) {\n // first refresh the action tiddler\n story.refreshTiddler(tiddler.title, null, true);\n // do not do anything else if we are not an action!\n // no, we still want to do review updates below, so only do the next bit for actions\n // if (!_GTD.tiddlerHasTag(tiddler, "action")) return;\n if (_GTD.tiddlerHasTag(tiddler, "action")) {\n // now refresh all tiddlers that are tags of the action, which should be the context and project\n // no...now use explicit reference to project/context\n //for (var i = 0; i < tiddler.tags.length; i++)\n // ...of course, we don't refresh action-specific state tags\n // if (tiddler.tags[i] != "action" && tiddler.tags[i] != "done" && tiddler.tags[i] != "floating") {\n // story.refreshTiddler(tiddler.tags[i], null, true);\n // }\n if (tiddler.gtdProjectName && tiddler.gtdProjectName.length > 0) story.refreshTiddler(tiddler.gtdProjectName, null, true);\n if (tiddler.gtdContextName && tiddler.gtdContextName.length > 0) story.refreshTiddler(tiddler.gtdContextName, null, true);\n }\n }\n }\n \n var specialTiddlers = store.getTaggedTiddlers("review");\n for (var i = 0; i < specialTiddlers.length; i++)\n if (_GTD.tiddlerHasTag(specialTiddlers[i], "gtd")) { // only update GTD review tiddlers, as an optimization\n // as a further optimization, we don't refresh tiddlers that aren't actually displayed, and make sure that\n // if they are displayed, they are in view mode, not edit mode\n var el = _GTD.getTiddlerElement(specialTiddlers[i]);\n if (el && el.getAttribute("template") == "reviewViewTemplate")\n story.refreshTiddler(specialTiddlers[i].title, null, true);\n }\n\n },\n \n appendProjectActionMarkup: function(projectTiddler, actionTitle, actionContext)\n {\n var actionInsertionPoint = -1, actionLeadin = "";\n \n var reActionWikitext = "^\s\s.{2}([^|\s\sn]+)(?:\s\s|?)(.*).*$";\n var reActionMacro = "(.*)<<gtdAction ((?:[^>]|(?:>(?!>)))*)>>.*$";\n var actionRe = new RegExp("(" + reActionWikitext + ")|(" + reActionMacro + ")", "mg");\n do {\n var formatMatch = actionRe.exec(projectTiddler.text);\n if (formatMatch) {\n actionLeadin = (formatMatch[1] ? "" : formatMatch[5]);\n actionInsertionPoint = actionRe.lastIndex;\n }\n } while(formatMatch);\n \n var actionProto = "\sn" + actionLeadin + "<<gtdAction \s"" + actionTitle + "\s" \s"" + actionContext + "\s">>";\n if (actionInsertionPoint == -1)\n projectTiddler.text += actionProto;\n else\n projectTiddler.text = projectTiddler.text.substring(0, actionInsertionPoint) + actionProto + projectTiddler.text.substr(actionInsertionPoint);\n \n this.tiddlerHasChanged(projectTiddler);\n this.refreshActionViews(projectTiddler);\n },\n \n removeProjectAction: function(projectTiddler, actionTitle)\n {\n var reActionWikitext = "^(\s\s.{2})[ \s\st]*(" + actionTitle + ")[ \s\st]*((\s\s|.*\s\sn?)|(.*\s\sn?))";\n var reActionMacro = "(.*<<gtdAction [\s"\s']?)(" + actionTitle + ")([\s"\s']?\s\ss+(?:[^>]|(?:>(?!>)))*>>.*\s\sn?)";\n projectTiddler.text = projectTiddler.text.replace(new RegExp(reActionWikitext, "mg"), "");\n projectTiddler.text = projectTiddler.text.replace(new RegExp(reActionMacro, "mg"), "");\n projectTiddler.changed();\n story.refreshTiddler(projectTiddler.title, null, true);\n },\n \n setNextAction: function(project)\n {\n if (project.gtdActions == undefined) project.gtdActions = [];\n project.gtdNextAction = null;\n for (var i = 0; i < project.gtdActions.length; i++)\n if (!project.gtdActions[i].gtdActionDone) {\n project.gtdNextAction = project.gtdActions[i];\n project.gtdProjectDone = false;\n this.toggleTag(project, "done", project.gtdProjectDone);\n return;\n }\n // if we get here, project is currently complete\n if (project.gtdActions.length > 0) project.gtdProjectDone = true;\n this.toggleTag(project, "done", project.gtdProjectDone);\n },\n \n clearContextCache: function()\n {\n this.contextCache = null;\n },\n \n getCachedContexts: function()\n {\n if (!this.contextCache) this.contextCache = store.getTaggedTiddlers("context");\n return this.contextCache;\n },\n \n renameCachedContext: function(oldName, newName)\n {\n if (this.contextCache) {\n var index = this.contextCache.indexOf(oldName);\n if (index > -1) this.contextCache[index] = newName;\n }\n },\n \n findActionContext: function(action)\n {\n var context = null;\n \n var contexts = this.getCachedContexts();\n for (var i = 0; i < contexts.length; i++)\n if (_GTD.tiddlerHasTag(action, contexts[i].title)) {\n context = contexts[i].title;\n break;\n }\n \n return context;\n },\n \n saveWithForcedBackup: function()\n {\n var saveBackups = config.options.chkSaveBackups;\n config.options.chkSaveBackups = true;\n saveChanges();\n config.options.chkSaveBackups = saveBackups;\n },\n \n isNextAction: function(actionTiddler)\n {\n if (actionTiddler.gtdProject && actionTiddler == actionTiddler.gtdProject.gtdNextAction)\n return true;\n return !actionTiddler.gtdActionDone && this.tiddlerHasTag(actionTiddler, "floating");\n },\n \n setReviewUpdate: function()\n {\n window._GTD = this;\n // having a subminute review update is overkill, but it would be nice to have semi-accurate\n // clock, so we can't have it be longer than a minute between updates\n //window.setTimeout('window._GTD.doReviewUpdate()', 60 * 1000);\n var d = new Date();\n window.setTimeout('window._GTD.doReviewUpdate()', (3600 - 60*d.getMinutes() - d.getSeconds()) * 1000);\n },\n \n doReviewUpdate: function()\n {\n this.refreshActionViews(null);\n this.setReviewUpdate();\n },\n \n setLazyAutoSave: function()\n {\n window._GTD = this;\n var interval = parseInt(config.options.txtGTDLazyAutoSaveInterval, 10);\n interval = isNaN(interval) ? 60 : interval.clamp(0, Number.MAX_VALUE);\n window.setTimeout('window._GTD.doLazyAutoSave()', interval * 1000);\n },\n \n doLazyAutoSave: function()\n {\n if (config.options.chkGTDLazyAutoSave && !config.options.chkAutoSave && (this.lazyAutoSave > 0 || store.isDirty())) {\n this.lazyAutoSave = 0;\n displayMessage('Autosaving changes...');\n saveChanges();\n if (typeof(gtdAutoSaveHook) == "function")\n gtdAutoSaveHook();\n window.setTimeout('clearMessage()', 5 * 1000);\n }\n this.setLazyAutoSave();\n },\n \n actionSorter: function(a,b)\n {\n // we now have an extended sort function to try and provide a more useful list of actions, esp. in a context view\n // ... the rule now is that project actions appear before non-project actions\n // ... if two actions have projects, and either project is tagged "important", it will appear first, otherwise actions are alphabetical by project\n // ... if two actions are from the same project, they appear in project action sequence, not alphabetically\n // ... all non-project actions continue to be sorted alphabetically\n \n if (a.gtdProject && b.gtdProject) {\n var aImportance = _GTD.tiddlerHasTag(a.gtdProject, "important"), bImportance = _GTD.tiddlerHasTag(b.gtdProject, "important");\n if (a.gtdProject == b.gtdProject)\n return (a.gtdProject.gtdActions.find(a) < b.gtdProject.gtdActions.find(b)) ? -1 : +1;\n else if (aImportance && !bImportance)\n return -1; // "a" is important, "b" is not, so "a" comes first\n else if (bImportance && !aImportance)\n return +1; // "b" is important, "a" is not, so "a" comes first\n else\n return (a.gtdProject.title < b.gtdProject.title) ? -1 : +1;\n }\n else if (a.gtdProject)\n return -1; // "a" has a project, "b" doesn't, so "a" comes first\n else if (b.gtdProject)\n return +1; // "b" has a project, "a" doesn't, so "b" comes first\n else {\n var aImportance = _GTD.tiddlerHasTag(a, "important"), bImportance = _GTD.tiddlerHasTag(b, "important");\n if (aImportance && !bImportance)\n return -1; // "a" is important, "b" is not, so "a" comes first\n else if (bImportance && !aImportance)\n return +1; // "b" is important, "a" is not, so "a" comes first\n else\n return (a.title < b.title) ? -1 : +1;\n }\n }\n};\n\nconfig.macros.gtdVersion = {}\nconfig.macros.gtdVersion.handler = function(place)\n{\n var v = version.extensions.GTDPlugins;\n createTiddlyElement(place, "span", null, null, v.major + "." + v.minor + "." + v.revision + (v.patch ? "." + v.patch : "") + (v.beta ? " (beta " + v.beta + ")" : ""));\n}\n\nconfig.macros.list.tagged = {}\nconfig.macros.list.tagged.innerHandler = function(tagList, allTags)\n{\n var tiddlers = store.getTaggedTiddlers(tagList[0]);\n\n if (allTags) {\n var results = [];\n for (var i = 0; i < tiddlers.length; i++) {\n var tiddler = tiddlers[i], hasAllTags = true;\n for (var j = 1; hasAllTags && j < tagList.length; j++) {\n // hasAllTags &= _GTD.tiddlerHasTag(tiddler, tagList[j]);\n hasAllTags &= (tagList[j].charAt(0) == '-') ? !_GTD.tiddlerHasTag(tiddler, tagList[j].substr(1)) : _GTD.tiddlerHasTag(tiddler, tagList[j])\n }\n if (hasAllTags) results.push(tiddlers[i]);\n }\n return results;\n }\n else {\n for (var i = 1; i < tagList.length; i++) {\n var more = store.getTaggedTiddlers(tagList[i]);\n for (var j = 0; j < more.length; j++)\n tiddlers.pushUnique(more[j]);\n }\n return tiddlers;\n }\n}\nconfig.macros.list.tagged.handler = function(params) \n{\n var tags = params[1].readBracketedList();\n if (tags.length == 1) {\n if (config.options[tags[0]] == undefined)\n return store.getTaggedTiddlers(tags[0]);\n else\n return store.getTaggedTiddlers(config.options[tags[0]]);\n }\n else if (tags.length > 1) {\n var allTags = (params[2] == undefined || params[2] == 'all');\n var tiddlers = this.innerHandler(tags, allTags);\n tiddlers.sort(function (a,b) {if(a.title == b.title) return(0); else return (a.title < b.title) ? -1 : +1; });\n return tiddlers;\n }\n}\n\nconfig.macros.gtdActionList = {}\nconfig.macros.gtdActionList.handler = function(place,macroName,params)\n{\n var theList = createTiddlyElement(place, "ul", null, "gtdActionList");\n var parentTiddler = story.findContainingTiddler(place).getAttribute("tiddler");\n \n var allActions = (params[1] == "all");\n var noProjectActions = (params[1] == "noproject");\n var justProjectActions = (params[1] == "projectonly");\n var aging = parseInt(config.options.txtGTDActionAging, 10);\n aging = isNaN(aging) ? 0 : aging.clamp(0, Number.MAX_VALUE);\n \n if (params[0] == "*") { // review actions for all projects\n var projects = store.getTaggedTiddlers("project");\n // do an importance sort on project list first, so they bubble to the top\n projects.sort( function(a,b) {\n var aImportance = _GTD.tiddlerHasTag(a, "important"), bImportance = _GTD.tiddlerHasTag(b, "important");\n if (aImportance && !bImportance)\n return -1; // "a" is important, "b" is not, so "a" comes first\n else if (bImportance && !aImportance)\n return 1; // "b" is important, "a" is not, so "a" comes first\n else\n return (a.title < b.title) ? -1 : +1;\n }\n );\n for (var i = 0; i < projects.length; i++) {\n var project = projects[i];\n // filter projects that have been deferred\n if (_GTD.tiddlerHasTag(project, config.options.txtGTDSomedayContext)) continue;\n if (!allActions) {\n //var skipEmptyProject = true;\n //if (project.gtdActions != undefined && project.gtdActions.length > 0)\n // for (var k = 0; skipEmptyProject && k < project.gtdActions.length; k++)\n // skipEmptyProject = project.gtdActions[k].gtdActionDone;\n //if (skipEmptyProject) continue;\n if (project.gtdActions == undefined || project.gtdActions.length == 0 || project.gtdProjectDone) continue;\n }\n // this will present the actions in the same order as they appear in the project\n var theListItem = createTiddlyElement(theList, "li", null, "gtdActionListProject");\n createTiddlyLink(theListItem, project.title, true);\n if (project.gtdActions != undefined && project.gtdActions.length > 0) {\n var subList = createTiddlyElement(theList, "ul", null, "gtdActionList");\n for (var j = 0; j < project.gtdActions.length; j++) {\n var action = project.gtdActions[j];\n // if we are not displaying all actions, filter old completed actions (if specified)\n // if (!allActions && action.gtdActionDone && aging > 0 && _GTD.tiddlerAgeInDays(action) > aging) continue;\n // NEW! we are now filtering all completed actions unless we are displaying all actions\n if (!allActions && action.gtdActionDone) continue;\n var subListItem = createTiddlyElement(subList, "li");\n var el = config.macros.gtdAction.createActionElement(subListItem, action, project.title, action.tags);\n }\n }\n }\n }\n \n else if (params[0] == "@") { // review actions for all contexts\n var contexts = _GTD.getCachedContexts();\n for (var i = 0; i < contexts.length; i++) {\n var context = contexts[i];\n var actions = config.macros.list.tagged.innerHandler([context.title, "action"], true);\n if (actions.length > 0) {\n var firstAction = true, theListItem, subList;\n actions.sort(_GTD.actionSorter);\n for (var j = 0; j < actions.length; j++) {\n var currentAction = actions[j];\n // special filtering by request...\n if (noProjectActions && currentAction.gtdProject) continue;\n if (justProjectActions && typeof(currentAction.gtdProject) == 'undefined') continue;\n // if we are not displaying all actions, filter completed actions and non-next project actions\n if (!allActions && (currentAction.gtdActionDone || (currentAction.gtdProject && !_GTD.isNextAction(currentAction)))) continue;\n // filter actions for projects that have been deferred\n if (currentAction.gtdProject && _GTD.tiddlerHasTag(currentAction.gtdProject, config.options.txtGTDSomedayContext)) continue;\n if (firstAction) {\n theListItem = createTiddlyElement(theList, "li", null, "gtdActionListContext");\n createTiddlyLink(theListItem, context.title, true);\n subList = createTiddlyElement(theList, "ul", null, "gtdActionList");\n firstAction = false;\n }\n var subListItem = createTiddlyElement(subList, "li");\n var el = config.macros.gtdAction.createActionElement(subListItem, currentAction, context.title, currentAction.tags);\n }\n }\n }\n }\n \n else { // actions tagged by current tiddler name, or specified tag list as parameter\n var reviewMode = config.options['chkGTDActionListReviewMode' + escape(parentTiddler)];\n if (typeof(reviewMode) == 'undefined') reviewMode = false;\n \n // chain to our "tagged" list macro to get the tiddlers first\n var tags = (params.length == 0 || params[0] == "." ? [ parentTiddler ] : params[0].readBracketedList());\n tags.push("action");\n var results = config.macros.list.tagged.innerHandler(tags, true);\n results.sort(_GTD.actionSorter);\n for (var t = 0; t < results.length; t++) {\n var action = results[t];\n // special filtering by request...\n if (noProjectActions && action.gtdProject) continue;\n if (justProjectActions && typeof(action.gtdProject) == 'undefined') continue;\n if (action.gtdProject && _GTD.tiddlerHasTag(action.gtdProject, config.options.txtGTDSomedayContext)) continue;\n // if we are not displaying all actions, filter completed actions and non-next project actions\n if (reviewMode && !allActions && (action.gtdActionDone || (action.gtdProject && !_GTD.isNextAction(action)))) continue;\n // if we are not displaying all actions, filter old completed actions (if specified)\n if (!allActions && action.gtdActionDone && aging > 0 && _GTD.tiddlerAgeInDays(action) > aging) continue;\n var theListItem = createTiddlyElement(theList, "li");\n var el = config.macros.gtdAction.createActionElement(theListItem, action, parentTiddler, action.tags);\n }\n }\n}\n\nconfig.macros.gtdAction = {}\nconfig.macros.gtdAction.createActionElement = function(place, actionTiddler, filterName, tags)\n{\n if (typeof(actionTiddler) == "string") actionTiddler = store.getTiddler(actionTiddler);\n \n var actionElement = createTiddlyElement(place, "span", null, "gtdActionItem");\n \n // oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...\n var cb = document.createElement("input");\n cb.setAttribute("type", "checkbox");\n cb.setAttribute("actionTiddler", actionTiddler.title);\n cb.onclick = this.onClickDone;\n actionElement.appendChild(cb);\n cb.checked = actionTiddler.gtdActionDone;\n createTiddlyLink(actionElement, actionTiddler.title, true);\n if (actionTiddler.gtdActionDone) actionElement.className = "gtdCompletedActionItem";\n if (_GTD.isNextAction(actionTiddler)) actionElement.className = "gtdNextActionItem";\n \n var filterTags = [], actionTags = [];\n if (actionTiddler.gtdProjectName && actionTiddler.gtdProjectName.length > 0)\n actionTags.push(actionTiddler.gtdProjectName);\n if (actionTiddler.gtdContextName && actionTiddler.gtdContextName.length > 0)\n actionTags.push(actionTiddler.gtdContextName);\n for (var i = 0; i < tags.length; i++) actionTags.pushUnique(tags[i]);\n if (filterName && filterName.length > 0) filterTags.pushUnique(filterName);\n \n actionTags = _GTD.filteredActionTags(actionTags, filterTags);\n if (actionTags.length > 0) {\n createTiddlyText(actionElement, " [ ");\n for (var i = 0; i < actionTags.length; i++) {\n if (i > 0) createTiddlyText(actionElement, ", ");\n createTiddlyLink(actionElement, actionTags[i], true, "actionCrossReference");\n }\n createTiddlyText(actionElement, " ]");\n }\n \n return actionElement;\n}\n\nconfig.macros.gtdAction.onClickDone = function(e)\n{\n var tiddler = store.getTiddler(this.getAttribute("actionTiddler"));\n if (tiddler) {\n _GTD.toggleTag(tiddler, "done", this.checked);\n tiddler.gtdActionDone = this.checked;\n _GTD.tiddlerHasChanged(tiddler);\n _GTD.refreshActionViews(tiddler);\n if (this.checked && typeof(gtdActionDoneHook) == "function")\n gtdActionDoneHook(tiddler);\n if (tiddler.gtdActionDone && tiddler.gtdProject == undefined && confirm("This action is not a part of a project. Would you just like to delete it?")) {\n story.closeTiddler(tiddler.title, false, false);\n store.removeTiddler(tiddler.title);\n }\n }\n return true;\n}\n\nconfig.macros.gtdAction.handler = function(place,macroName,params)\n{\n var title = params[0], tags;\n var parentTiddler = story.findContainingTiddler(place).getAttribute("tiddler");\n var tiddler = store.getTiddler(title);\n if (!tiddler) {\n // we should *never* get here now for project actions, but keep code in case project code\n // trips up, or we use this macro somewhere else\n this.createAction(title, parentTiddler, params[1]);\n }\n else\n // use actual tiddler tags, not macro param, in case context changed!\n tags = tiddler.tags;\n var action = this.createActionElement(place, title, parentTiddler, tags);\n}\n\nconfig.macros.gtdAction.createAction = function(title, projectTiddlerName, tagParams, extraTags)\n{\n // var tags = ["action", parentTiddler];\n var action, tags = ["action"], fields = {};\n if (_GTD.usingProjectTags)\n tags.push(projectTiddlerName);\n if (typeof(tagParams) == "string") tags = tags.concat(tagParams.readBracketedList());\n if (typeof(extraTags) == "string") tags = tags.concat(extraTags.readBracketedList());\n var templateText = store.getTiddlerText("NewActionTemplate", config.views.wikified.defaultText.format([title]));\n if (_GTD.usingProjectTags)\n action = store.saveTiddler(title, title, templateText, config.options.txtUserName, new Date(), tags);\n else {\n fields["gtd.project"] = projectTiddlerName;\n action = store.saveTiddler(title, title, templateText, config.options.txtUserName, new Date(), tags, fields);\n }\n return action;\n}\n\nconfig.macros.gtdActionCompleted = {}\nconfig.macros.gtdActionCompleted.handler = function(place,macroName,params)\n{\n if (!readOnly) {\n var title = story.findContainingTiddler(place).getAttribute("tiddler");\n var tiddler = store.getTiddler(title);\n // oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...\n var cb = document.createElement("input");\n cb.setAttribute("type", "checkbox");\n cb.setAttribute("actionTiddler", title);\n cb.onclick = this.onClickDone;\n place.appendChild(cb);\n cb.checked = tiddler.gtdActionDone;\n }\n}\n\nconfig.macros.gtdActionCompleted.onClickDone = function(e)\n{\n var tiddler = store.getTiddler(this.getAttribute("actionTiddler"));\n if (tiddler) {\n _GTD.toggleTag(tiddler, "done", this.checked);\n tiddler.gtdActionDone = this.checked;\n _GTD.tiddlerHasChanged(tiddler);\n _GTD.refreshActionViews(tiddler);\n if (this.checked && typeof(gtdActionDoneHook) == "function")\n gtdActionDoneHook(tiddler);\n if (tiddler.gtdActionDone && tiddler.gtdProject == undefined && confirm("This action is not a part of a project. Would you just like to delete it?")) {\n story.closeTiddler(tiddler.title, false, false);\n store.removeTiddler(tiddler.title);\n }\n }\n return true;\n}\n\nconfig.macros.gtdToggleTag = {}\nconfig.macros.gtdToggleTag.handler = function(place,macroName,params)\n{\n if (!readOnly) {\n var title = story.findContainingTiddler(place).getAttribute("tiddler");\n var tiddler = store.getTiddler(title);\n // oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...\n var cb = document.createElement("input");\n cb.setAttribute("type", "checkbox");\n cb.setAttribute("tiddler", title);\n cb.setAttribute("toggledTag", params[0]);\n cb.onclick = this.onClickDone;\n place.appendChild(cb);\n cb.checked = _GTD.tiddlerHasTag(tiddler, params[0]);\n }\n}\n\nconfig.macros.gtdToggleTag.onClickDone = function(e)\n{\n var tiddler = store.getTiddler(this.getAttribute("tiddler"));\n if (tiddler) {\n _GTD.toggleTag(tiddler, this.getAttribute("toggledTag"), this.checked);\n _GTD.tiddlerHasChanged(tiddler);\n if (_GTD.tiddlerHasTag(tiddler, "action"))\n _GTD.refreshActionViews(tiddler);\n else\n // we need a broad notification here, not just refreshActionViews\n store.notify(tiddler.title, true);\n }\n return true;\n}\n\nconfig.macros.gtdToggleState = {}\nconfig.macros.gtdToggleState.handler = function(place,macroName,params)\n{\n var title = story.findContainingTiddler(place).getAttribute("tiddler");\n var tiddler = store.getTiddler(title);\n // oddly, we barf when setting the checkbox type on an input if we use createTiddlyElement...\n var cb = document.createElement("input");\n cb.setAttribute("type", "checkbox");\n cb.setAttribute("tiddler", title);\n var state = params[0] + escape(title);\n cb.setAttribute("stateName", state);\n cb.onclick = this.onClickDone;\n place.appendChild(cb);\n cb.checked = config.options[state];\n}\n\nconfig.macros.gtdToggleState.onClickDone = function(e)\n{\n var tiddler = store.getTiddler(this.getAttribute("tiddler"));\n if (tiddler) {\n var state = this.getAttribute("stateName");\n config.options[state] = this.checked;\n saveOptionCookie(state);\n story.refreshTiddler(tiddler.title, null, true);\n }\n return true;\n}\n\nconfig.macros.importUpdates = { \n importMode: "updates",\n buttonTitle: "Update", \n buttonHelp: "Click here to update the application",\n preUpdateMessage: "Once the download is finished, you will need to reload your document to complete the update. In order to allow you to review the update tiddlers, this will not be done automatically. \sn\snClick \s"OK\s" start the update.",\n postUpdateMessage: "Please remember, you will need to save and reload your document to complete the update. In order to allow you to review the update tiddlers, this will not be done automatically."\n}\nconfig.macros.importUpdates.handler = function(place, macroName, params)\n{\n var mode = params[1] ? params[1] : this.importMode;\n var title = params[2] ? params[2] : this.buttonTitle;\n var prompt = params[3] ? params[3] : this.buttonHelp;\n var button = createTiddlyButton(place, title, prompt, this.onClickUpdate);\n button.setAttribute("updateSource", params[0]);\n button.setAttribute("importMode", mode);\n if (params.length > 4) button.setAttribute("importExtras", params.slice(4).join(" "));\n}\n\nconfig.macros.importUpdates.onClickUpdate = function(e)\n{\n if (!confirm(config.macros.importUpdates.preUpdateMessage))\n return;\n var importParams = [ this.getAttribute("importMode"), this.getAttribute("updateSource") ];\n var importExtras = this.getAttribute("importExtras");\n if (importExtras) importParams = importParams.concat(importExtras.split(" "));\n if (version.extensions.importTiddlers.major < 3)\n importParams.push("force");\n // force a saveChanges with backup before the update\n _GTD.saveWithForcedBackup();\n // chain to the importTiddlers macro\n config.macros.importTiddlers.handler(this, "importTiddlers", importParams);\n // ensure that relevant release notes are displayed on first launch\n config.options.chkGTDReleaseNotes = true;\n saveOptionCookie("chkGTDReleaseNotes");\n // do *not* cause a browser navigation\n return false;\n}\n\nconfig.macros.gtdArchive = {}\nconfig.macros.gtdArchive.handler = function(place, macroName, params)\n{\n var archiveAction = params.length > 0 ? params[0] : "archive"\n var btn = createTiddlyButton(place, archiveAction, "", this.onClick);\n btn.setAttribute("archiveAction", archiveAction);\n}\n\nconfig.macros.gtdArchive.onClick = function(e)\n{\n var warning = "Are you sure you want to %0 all %1 projects and actions?";\n var status = "There were %0 project(s) and %1 action(s) %2d.";\n var archiveAction = this.getAttribute("archiveAction");\n \n var projectCount = 0, actionCount = 0;\n \n if (archiveAction == "archive") {\n if (confirm(warning.format([archiveAction, "completed"]))) {\n clearMessage();\n var projects = store.getTaggedTiddlers("project");\n for (var i = 0; i < projects.length; i++) {\n var project = projects[i];\n if (project.gtdActions == undefined || project.gtdActions.length == 0) continue;\n var projectComplete = true;\n for (var j = 0; projectComplete && j < project.gtdActions.length; j++)\n projectComplete = project.gtdActions[j].gtdActionDone;\n if (!projectComplete) continue;\n // if we get here, all project actions are done, so archive project\n story.closeTiddler(project.title, false, false);\n _GTD.tiddlerSwapTag(project, "project", "project-archive");\n _GTD.tiddlerHasChanged(project, false);\n projectCount++;\n for (j = 0; j < project.gtdActions.length; j++) {\n story.closeTiddler(project.gtdActions[j].title, false, false);\n _GTD.tiddlerSwapTag(project.gtdActions[j], "action", "action-archive");\n _GTD.tiddlerHasChanged(project.gtdActions[j], false);\n actionCount++;\n }\n }\n var actions = store.getTaggedTiddlers("action");\n for (i = 0; i < actions.length; i++) {\n var action = actions[i];\n if (action.gtdActionDone && !action.gtdProject) {\n story.closeTiddler(action.title, false, false);\n _GTD.tiddlerSwapTag(action, "action", "action-archive");\n _GTD.tiddlerHasChanged(action, false);\n actionCount++;\n }\n }\n displayMessage(status.format([projectCount, actionCount, archiveAction]));\n var saveClearMessage = clearMessage;\n clearMessage = function() {};\n if (config.options.chkAutoSave) saveChanges();\n clearMessage = saveClearMessage;\n store.notify(null, true);\n }\n }\n \n else if (archiveAction == "unarchive") {\n if (confirm(warning.format([archiveAction, "archived"]))) {\n clearMessage();\n var projects = store.getTaggedTiddlers("project-archive");\n for (var i = 0; i < projects.length; i++) {\n var project = projects[i];\n story.closeTiddler(project.title, false, false);\n _GTD.tiddlerSwapTag(project, "project-archive", "project");\n _GTD.tiddlerHasChanged(project, false);\n projectCount++;\n }\n var actions = store.getTaggedTiddlers("action-archive");\n for (i = 0; i < actions.length; i++) {\n var action = actions[i];\n story.closeTiddler(action.title, false, false);\n _GTD.tiddlerSwapTag(action, "action-archive", "action");\n _GTD.tiddlerHasChanged(action, false);\n actionCount++;\n }\n displayMessage(status.format([projectCount, actionCount, archiveAction]));\n var saveClearMessage = clearMessage;\n clearMessage = function() {};\n if (config.options.chkAutoSave) saveChanges();\n clearMessage = saveClearMessage;\n store.notify(null, true);\n }\n }\n \n else if (archiveAction == "purge") {\n if (confirm(warning.format([archiveAction, "archived"]))) {\n clearMessage();\n _GTD.saveWithForcedBackup();\n var projects = store.getTaggedTiddlers("project-archive");\n for (var i = 0; i < projects.length; i++) {\n var project = projects[i];\n story.closeTiddler(project.title, false, false);\n store.removeTiddler(project.title);\n projectCount++;\n }\n var actions = store.getTaggedTiddlers("action-archive");\n for (i = 0; i < actions.length; i++) {\n var action = actions[i];\n story.closeTiddler(action.title, false, false);\n store.removeTiddler(action.title);\n actionCount++;\n }\n displayMessage(status.format([projectCount, actionCount, archiveAction]));\n var saveClearMessage = clearMessage;\n clearMessage = function() {};\n if (config.options.chkAutoSave) saveChanges();\n clearMessage = saveClearMessage;\n store.notify(null, true);\n }\n }\n else\n alert("That archiving action is not supported");\n}\n\nconfig.formatters.push(\n {\n name: "gtdAction",\n match: "^\s\s.{2}.*",\n lookahead: "^\s\s.{2}([^|]*)(?:\s\s|?)(.*)",\n handler: function(w)\n {\n var lookaheadRegExp = new RegExp(this.lookahead,"g");\n var lookaheadMatch = lookaheadRegExp.exec(w.matchText)\n if (lookaheadMatch) {\n var params = [ lookaheadMatch[1].trim() ];\n if (lookaheadMatch[2].trim().length > 0) params.push(lookaheadMatch[2].trim());\n config.macros.gtdAction.handler(w.output, "gtdAction", params);\n }\n }\n }\n);\n\nconfig.commands.newAction = { text: "action", tooltip: "Create a new action for this context", hideReadOnly: true };\nconfig.commands.newAction.handler = function(event, src, context)\n{\n var d = new Date();\n var newActionTitle = d.formatString("New Action hh:0mm:0ss");\n if (!store.tiddlerExists(newActionTitle)) {\n var tiddler = store.createTiddler(newActionTitle);\n var templateText = store.getTiddlerText("NewActionTemplate", config.views.wikified.defaultText.format([newActionTitle]));\n tiddler.assign(newActionTitle, templateText, config.options.txtUserName, new Date(), [ "action", context ]);\n \n story.displayTiddler(null, newActionTitle, DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(newActionTitle, "title");\n }\n return false;\n}\n\nconfig.commands.newProjectAction = { text: "action", tooltip: "Create a new action for this project", hideReadOnly: true };\nconfig.commands.newProjectAction.handler = function(event, src, project)\n{\n var d = new Date();\n var newActionTitle = d.formatString("New Action hh:0mm:0ss");\n if (!store.tiddlerExists(newActionTitle)) {\n var defaultContext = config.options.txtGTDUnfiledContext;\n _GTD.appendProjectActionMarkup(store.getTiddler(project), newActionTitle, defaultContext);\n \n var tiddler = store.createTiddler(newActionTitle);\n var templateText = store.getTiddlerText("NewActionTemplate", config.views.wikified.defaultText.format([newActionTitle]));\n var tags = ["action"], fields = {};\n if (_GTD.usingProjectTags)\n tags.push(project);\n tags.push(defaultContext);\n if (_GTD.usingProjectTags)\n tiddler.assign(newActionTitle, templateText, config.options.txtUserName, new Date(), tags);\n else {\n fields["gtd.project"] = project;\n tiddler.assign(newActionTitle, templateText, config.options.txtUserName, new Date(), tags, new Date(), fields);\n }\n \n story.displayTiddler(null, newActionTitle, DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(newActionTitle, "title");\n }\n return false;\n}\n\nconfig.commands.changeContext = { text: "context", tooltip: "Change context of this action", hideReadOnly: true, popupNone: "There are no contexts" };\nconfig.commands.changeContext.handler = function(event,src,title)\n{\n var popup = Popup.create(src);\n if (popup) {\n var contexts = _GTD.getCachedContexts();\n var tiddler = store.getTiddler(title);\n var currentContext = _GTD.findActionContext(tiddler);\n if (!currentContext) currentContext = '';\n \n var c = false;\n for (var i = 0; i < contexts.length; i++)\n if (contexts[i].title != currentContext) {\n var button = createTiddlyButton(createTiddlyElement(popup, "li"), contexts[i].title, '', this.onClickContext);\n button.setAttribute("actionTiddler", title);\n button.setAttribute("oldContext", currentContext);\n button.setAttribute("newContext", contexts[i].title);\n c = true;\n }\n \n if (!c)\n createTiddlyText(createTiddlyElement(popup, "li", null, "disabled"), this.popupNone);\n }\n \n Popup.show(popup, false);\n event.cancelBubble = true;\n if (event.stopPropagation) event.stopPropagation();\n // do *not* cause a browser navigation\n return false;\n}\n\nconfig.commands.changeContext.onClickContext = function(e)\n{\n var tiddler = store.getTiddler(this.getAttribute("actionTiddler"));\n if (tiddler) {\n var contextChanged = false;\n var oldContext = this.getAttribute("oldContext");\n var newContext = this.getAttribute("newContext");\n if (oldContext.length == 0)\n contextChanged = (tiddler.tags.push(newContext) > 0);\n else\n contextChanged = _GTD.tiddlerSwapTag(tiddler, oldContext, newContext);\n \n if (contextChanged) {\n tiddler.gtdContextName = newContext;\n _GTD.setExtendedValue(tiddler, "gtd.context", newContext);\n _GTD.tiddlerHasChanged(tiddler);\n _GTD.refreshActionViews(tiddler);\n // be sure to refresh old context as well...\n story.refreshTiddler(oldContext, null, true);\n }\n }\n // do *not* cause a browser navigation\n return false;\n}\n\nconfig.commands.deleteAction = { text: "delete", tooltip: "Delete this action", hideReadOnly: true, warning: "Are you sure you want to delete '%0'?", altwarning: "Are you sure you want to delete '%0'? The action will also be removed from project '%1'." };\nconfig.commands.deleteAction.handler = function(event, src, title)\n{\n var tiddler = store.getTiddler(title);\n var ok = (tiddler.gtdProject ? confirm(this.altwarning.format([title, tiddler.gtdProject.title])) : confirm(this.warning.format([title])));\n if (ok) {\n if (tiddler.gtdProject) _GTD.removeProjectAction(tiddler.gtdProject, title);\n store.removeTiddler(title);\n story.closeTiddler(title,true,event.shiftKey || event.altKey);\n if (config.options.chkAutoSave)\n saveChanges();\n }\n \n return false;\n}\n\nconfig.commands.deleteContext = { text: "delete", tooltip: "Delete this context", hideReadOnly: true, warning: "Are you sure you want to delete '%0'? All associated actions will be tagged as 'unfiled'." };\nconfig.commands.deleteContext.handler = function(event, src, title)\n{\n if (confirm(this.warning.format([title]))) {\n store.suspendNotifications();\n this.unlinkActions(title);\n // force a rebuild of our context cache\n _GTD.clearContextCache();\n store.resumeNotifications();\n store.removeTiddler(title);\n story.closeTiddler(title,true,event.shiftKey || event.altKey);\n if (config.options.chkAutoSave)\n saveChanges();\n }\n \n return false;\n}\n\nconfig.commands.deleteContext.unlinkActions = function(contextTitle)\n{\n var tiddlers = config.macros.list.tagged.innerHandler([contextTitle, "action"], true);\n for (var i = 0; i < tiddlers.length; i++) {\n var tiddler = tiddlers[i];\n _GTD.tiddlerSwapTag(tiddler, contextTitle, config.options.txtGTDUnfiledContext);\n _GTD.tiddlerHasChanged(tiddler, false);\n // context removal will do view notification...\n }\n}\n\nconfig.commands.archiveProject = { text: "archive", tooltip: "Archive this project", hideReadOnly: true, warning: "Are you sure you want to archive '%0'?", noarchive: "This project is %0 and will not be archived." };\nconfig.commands.archiveProject.handler = function(event, src, title)\n{\n if (confirm(this.warning.format([title]))) {\n var project = store.getTiddler(title);\n if (project.gtdActions == undefined || project.gtdActions.length == 0) {\n alert(this.noarchive.format(["empty"]));\n return;\n }\n var projectComplete = true;\n for (var j = 0; projectComplete && j < project.gtdActions.length; j++)\n projectComplete = project.gtdActions[j].gtdActionDone;\n if (!projectComplete) {\n alert(this.noarchive.format(["incomplete"]));\n return;\n }\n // if we get here, all project actions are done, so archive project\n story.closeTiddler(project.title, false, false);\n _GTD.tiddlerSwapTag(project, "project", "project-archive");\n _GTD.tiddlerHasChanged(project, false);\n for (j = 0; j < project.gtdActions.length; j++) {\n story.closeTiddler(project.gtdActions[j].title, false, false);\n _GTD.tiddlerSwapTag(project.gtdActions[j], "action", "action-archive");\n _GTD.tiddlerHasChanged(project.gtdActions[j], false);\n }\n store.notify(null, true);\n if (config.options.chkAutoSave)\n saveChanges();\n }\n\n return false;\n}\n\nconfig.commands.deleteProject = { text: "delete", tooltip: "Delete this project", hideReadOnly: true, warning: "Are you sure you want to delete '%0'? All associated actions will no longer be bound to this (or any) project." };\nconfig.commands.deleteProject.handler = function(event, src, title)\n{\n if (confirm(this.warning.format([title]))) {\n store.suspendNotifications();\n this.unlinkActions(title);\n store.resumeNotifications();\n store.removeTiddler(title);\n story.closeTiddler(title,true,event.shiftKey || event.altKey);\n if (config.options.chkAutoSave)\n saveChanges();\n }\n \n return false;\n}\n\nconfig.commands.deleteProject.unlinkActions = function(projectTitle)\n{\n // var tiddlers = config.macros.list.tagged.innerHandler([projectTitle, "action"], true);\n var project = store.getTiddler(projectTitle);\n for (var i = 0; i < project.gtdActions.length; i++) {\n var tiddler = project.gtdActions[i];\n tiddler.gtdProject = null;\n tiddler.gtdProjectName = null;\n if (_GTD.usingProjectTags)\n tiddler.tags.splice(tiddler.tags.find(projectTitle), 1);\n else {\n _GTD.setExtendedValue(tiddler, "gtd.project", null);\n _GTD.setExtendedValue(tiddler, "gtd.projectindex", null);\n }\n _GTD.tiddlerHasChanged(tiddler, false);\n // project removal will do view notification...\n }\n}\n\nconfig.commands.deleteProjectAll = { text: "delete all", tooltip: "Delete this project and its actions", hideReadOnly: true, warning: "Are you sure you want to delete '%0' and all its associated actions?" };\nconfig.commands.deleteProjectAll.handler = function(event, src, title)\n{\n if (confirm(this.warning.format([title]))) {\n store.suspendNotifications();\n this.deleteActions(title);\n store.resumeNotifications();\n store.removeTiddler(title);\n story.closeTiddler(title,true,event.shiftKey || event.altKey);\n if (config.options.chkAutoSave)\n saveChanges();\n }\n \n return false;\n}\n\nconfig.commands.deleteProjectAll.deleteActions = function(projectTitle)\n{\n // var tiddlers = config.macros.list.tagged.innerHandler([projectTitle, "action"], true);\n var project = store.getTiddler(projectTitle);\n for (var i = 0; i < project.gtdActions.length; i++) {\n var tiddler = project.gtdActions[i].title;\n store.removeTiddler(tiddler);\n story.closeTiddler(tiddler, true, false);\n // project removal will do view notification...\n }\n}\n\nconfig.commands.projectify = { text: "projectify", tooltip: "Convert this action to a project", hideReadOnly: true, warning: "Are you sure you want to convert '%0' to a project?" };\nconfig.commands.projectify.handler = function(event, src, title)\n{\n if (confirm(this.warning.format([title]))) {\n var tiddler = store.getTiddler(title);\n if (tiddler.gtdProject) _GTD.removeProjectAction(tiddler.gtdProject, title);\n tiddler.tags = [ "project" ];\n _GTD.tiddlerHasChanged(tiddler, true);\n // we need a broad notification here, not just refreshActionViews\n store.notify(title, true);\n }\n \n return false;\n}\n\n// *** ***/\n// *** These are overrides to core TiddlyWiki functionality ***\n// *** ***/\n\nTiddler.prototype._GTDInheritedChanged = Tiddler.prototype.changed;\nTiddler.prototype.changed = function()\n{\n this._GTDInheritedChanged();\n \n // Note that this is called both as part of normal tiddler changes AND as a part\n // of the initial TW loading process from DIVs...\n \n if (_GTD.tiddlerHasTag(this, "project")) {\n // (re)build the in-memory ordered action list\n this.gtdActions = [];\n this.gtdNextAction = null;\n if (this.text) {\n var reActionWikitext = "^\s\s.{2}([^|\s\sn]+)(?:\s\s|?)(.*)";\n var reActionMacro = "<<gtdAction ((?:[^>]|(?:>(?!>)))*)>>";\n var actionRe = new RegExp("(" + reActionWikitext + ")|(" + reActionMacro + ")", "mg");\n do {\n var formatMatch = actionRe.exec(this.text);\n if (formatMatch) {\n var macroParams = (formatMatch[1] ? null : formatMatch[5].readMacroParams());\n // note that for the ".." notation, we are trimming up action titles and contexts\n var actionTiddlerName = (formatMatch[1] ? formatMatch[2].trim() : macroParams[0]);\n var actionTiddler = store.getTiddler(actionTiddlerName);\n if (!actionTiddler) {\n var actionTags = (formatMatch[1] ? formatMatch[3].trim() : macroParams[1]);\n var extraTags = (formatMatch[1] ? '' : macroParams[2]);\n actionTiddler = config.macros.gtdAction.createAction(actionTiddlerName, this.title, actionTags, extraTags);\n }\n if (actionTiddler) {\n actionTiddler.gtdProject = this;\n if (this.gtdNextAction == null && !_GTD.tiddlerHasTag(actionTiddler, "done"))\n this.gtdNextAction = actionTiddler;\n this.gtdActions.push(actionTiddler);\n _GTD.setExtendedValue(actionTiddler, "gtd.projectindex", this.gtdActions.length - 1);\n // handle project renaming in action\n if (actionTiddler.gtdProjectName && actionTiddler.gtdProjectName != this.title) {\n if (_GTD.usingProjectTags)\n _GTD.tiddlerSwapTag(actionTiddler, actionTiddler.gtdProjectName, this.title);\n else\n _GTD.setExtendedValue(actionTiddler, "gtd.project", this.title);\n // action view won't get updated through any other refresh mechanism, so\n story.refreshTiddler(actionTiddler.title, null, true);\n }\n actionTiddler.gtdProjectName = this.title;\n }\n }\n } while(formatMatch);\n }\n }\n \n else if (_GTD.tiddlerHasTag(this, "context")) {\n if (this.gtdContextName == undefined)\n this.gtdContextName = this.title;\n else if (this.gtdContextName != this.title) {\n // propagate renamed context to affected actions\n store.suspendNotifications();\n var results = config.macros.list.tagged.innerHandler([ this.gtdContextName, "action"], true);\n for (var t = 0; t < results.length; t++) {\n _GTD.tiddlerSwapTag(results[t], this.gtdContextName, this.title);\n results[t].gtdContextName = this.title;\n _GTD.setExtendedValue(results[t], "gtd.context", this.title);\n // action view won't get updated through any other refresh mechanism, so\n //story.refreshTiddler(results[t].title, null, true);\n }\n // because the store is not yet updated, we need to manipulate the context cache directly\n _GTD.renameCachedContext(this.gtdContextName, this.title);\n this.gtdContextName = this.title;\n // we need a broad notification here, not just refreshActionViews\n store.resumeNotifications();\n store.notify(null, true);\n }\n }\n \n else if (_GTD.tiddlerHasTag(this, "action")) {\n if (this.gtdActionName == undefined)\n this.gtdActionName = this.title;\n else if (this.gtdActionName != this.title && this.gtdProject) {\n // ugh...dig into related project and update the wiki code to use new action name\n var reActionWikitext = "^(\s\s.{2}[ \s\st]*)(" + this.gtdActionName + ")(([ \s\st]*\s\s|.*\s\sn?)|(\s\sn?))";\n var reActionMacro = "(<<gtdAction [\s"\s']?)(" + this.gtdActionName + ")([\s"\s']?\s\ss+(?:[^>]|(?:>(?!>)))*>>)";\n this.gtdProject.text = this.gtdProject.text.replace(new RegExp(reActionWikitext, "mg"), "$1" + this.title + "$3");\n this.gtdProject.text = this.gtdProject.text.replace(new RegExp(reActionMacro, "mg"), "$1" + this.title + "$3");\n this.gtdActionName = this.title;\n }\n this.gtdActionDone = _GTD.tiddlerHasTag(this, "done");\n this.gtdContextName = _GTD.findActionContext(this);\n _GTD.setExtendedValue(this, "gtd.context", this.gtdContextName);\n // reset the next action on the associated project\n if (this.gtdProject) _GTD.setNextAction(this.gtdProject);\n }\n}\n\nStory.prototype.chooseTemplateForTiddler = function(title,template)\n{\n // This override to core TW functionality is used to provide tag-based view and edit templates. The\n // basic idea is that the tiddler is scanned for its tags and, depending on whether we are opening a\n // tiddler in "view" or "edit" mode, a corresponding 'tag + "ViewTemplate"' or 'tag + "EditTemplate"'\n // tiddler is searched for. If it exists, it is used instead of the default templates.\n \n if (!template)\n template = DEFAULT_VIEW_TEMPLATE;\n\n // before reverting to default behaviour, check to see if a tag-based template exists\n if (template == DEFAULT_VIEW_TEMPLATE || template == DEFAULT_EDIT_TEMPLATE) {\n if (this.tagBasedTemplateCache == undefined) this.tagBasedTemplateCache = new Array();\n var templateRoot = (template == DEFAULT_VIEW_TEMPLATE ? "ViewTemplate" : "EditTemplate");\n var tiddler = store.getTiddler(title);\n if (tiddler) {\n for (var i = 0; i < tiddler.tags.length; i++) {\n var tag = tiddler.tags[i];\n var tagTemplate = tag + templateRoot;\n var tagCacheId = tag + template;\n // first check our cache to see if we have seen this template before\n if (this.tagBasedTemplateCache[tagCacheId] != undefined) {\n // make sure template still exists\n if (store.tiddlerExists(this.tagBasedTemplateCache[tagCacheId])) {\n template = this.tagBasedTemplateCache[tagCacheId];\n break;\n }\n else\n delete this.tagBasedTemplateCache[tagCacheId];\n }\n // go to the store to see if template exists\n if (store.tiddlerExists(tagTemplate)) {\n template = tagTemplate;\n this.tagBasedTemplateCache[tagCacheId] = tagTemplate;\n break;\n }\n }\n }\n }\n \n if (template == DEFAULT_VIEW_TEMPLATE || template == DEFAULT_EDIT_TEMPLATE)\n template = config.tiddlerTemplates[template];\n return template;\n}\n\n// Clint Checketts' IE first-child patch, version 1.1, http://www.checkettsweb.com/tw/gtd_tiddlywiki.htm#GiveFirstTiddlerClassPatch\n\nStory.prototype.closeTiddlerIEFirstChild = Story.prototype.closeTiddler;\nStory.prototype.closeTiddler = function(title,animate,slowly) {\n var tiddler = document.getElementById(this.idPrefix + title);\n // we need to test to ensure tiddler is actually open\n if (tiddler) {\n var storyArea = tiddler.parentNode;\n if ((this.idPrefix + title) == storyArea.firstChild.id){\n removeClass(storyArea.firstChild,"IEFirstChild");\n // this next line is redundant, since it is looked after at the end of this function\n // if (storyArea.firstChild.nextSibling) addClass(storyArea.firstChild.nextSibling,"IEFirstChild");\n }\n story.closeTiddlerIEFirstChild(title,animate,slowly);\n if (storyArea.firstChild) addClass(storyArea.firstChild,"IEFirstChild");\n }\n}\n\nStory.prototype.displayTiddlerIEFirstChild = Story.prototype.displayTiddler;\nStory.prototype.displayTiddler = function(srcElement,title,template,animate,slowly) {\n var storyArea = document.getElementById(this.container);\n if (storyArea.firstChild) removeClass(storyArea.firstChild,"IEFirstChild");\n story.displayTiddlerIEFirstChild(srcElement,title,template,animate,slowly);\n addClass(storyArea.firstChild,"IEFirstChild");\n}\n\n_GTD.initialize();\n\n//}}}\n
/***\n!GTD specific styles\n***/\n\n/*{{{*/\n/* how annoying is that big header anyway?! */\n.headerForeground, .headerShadow {\n padding-top: 1em;\n}\n\n/* the tagging popup really gets in the way so push it off to the side */\n.tagging { float: right; }\n\n/* this unbullets actions in the actionList macro */\nul.gtdActionList { list-style-type: none; }\nli.gtdActionListProject, li.gtdActionListContext { margin-top: 1.0em; }\n\n.gtdCompletedActionItem { text-decoration: line-through; }\n.gtdNextActionItem { border-bottom: 1px solid red; }\n\na.actionCrossReference { color: #228B22; }\na.actionCrossReference:hover { color: white; }\n\n/* necessary bits copied from enhanced stylesheet to render properly without it */\n#mainMenu {\n font-size: 1em;\n text-align: left;\n width: 12em;\n}\n\n#mainMenu * {\n font-size: 1em;\n font-weight: normal;\n padding: 0; margin: 0; border: 0;\n}\n\n#mainMenu ul {\n list-style: none;\n margin-bottom: 10px;\n}\n\n#mainMenu li {\n text-indent: 1em;\n}\n\n#mainMenu li li {\n text-indent: 1.5em;\n}\n\n#mainMenu li li li {\n text-indent: 2em;\n}\n\n#mainMenu li li li li {\n text-indent: 2.5em;\n}\n\n#mainMenu a.button, #mainMenu a.tiddlyLink, #mainMenu a.externalLink {\n display: block; margin: 0;\n}\n\ntable.review { width: 98%; }\n.review tr { vertical-align: top; }\n\n/*}}}*/\n\n/***\n!Imported 3x5 printing styles\n//adapted from the work of Clint Checketts, http://www.checkettsweb.com/tw/gtd_tiddlywiki.htm //\n***/\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\n#contentWrapper\n{\n margin: 0;\n width: 100%;\n position: static;\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 /* we don't want any unnecessary output */\n border: none;\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, .header, .footer, .tagging, .tagged\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: none;\n page-break-before: always;\n font-size: 200%;\n /* IF YOU DO NOT USE INDEX CARDS, USE THIS */\n font-size: 100%;\n}\n\n.tiddler:first-child {\n page-break-before: avoid;\n}\n\n/* this relies on Clint's IE first-child patch */\n.IEFirstChild {\n page-break-before: auto;\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/*}}}*/\n\n/***\n!Imported styles for calendar plugin\n***/\n\n/*{{{*/\n\n#mainMenu .calendar {\n width: 100%;\n background-color: transparent !important;\n}\n\n#mainMenu .calendar, #mainMenu .calendar tr, #mainMenu .calendar td, #mainMenu .calendar a {\n}\n\n\n/*}}}*/\n
/***\n!Layout Rules /%==============================================%/\n***/\n/*{{{*/\n\nbody {\n /* this is required for proper layout on IE, for some reason... */\n _position: static;\n}\n\n.tagClear {\n /* this, too, is a necessary IE hack... */\n _margin-top: 10em; \n _clear: both;\n}\n\n.headerForeground, .headerShadow {\n padding-top: 1em;\n}\n\n.tiddler {\n margin: 0 0 0.9em 0;\n padding-bottom: 1em;\n}\n\n#mainMenu {\n width: 16em;\n font-size: 1em;\n text-align: left;\n padding-top: 0.5em;\n}\n\n#mainMenu * {\n font-size: 1em;\n font-weight: normal;\n padding: 0; margin: 0; border: 0;\n}\n\n#mainMenu ul {\n list-style: none;\n margin-bottom: 10px;\n}\n\n#mainMenu li {\n text-indent: 1em;\n}\n\n#mainMenu a.button, #mainMenu a.tiddlyLink, #mainMenu a.externalLink {\n display: block; margin: 0;\n}\n\n#displayArea {\n margin-left: 19em; margin-top: 0;\n}\n\n.toolbar .button {\n margin-left: 4px;\n}\n\n/*}}}*/\n\n/***\n!Generic Rules /%==============================================%/\n***/\n/*{{{*/\nbody {\n background: #464646;\n color: #000;\n}\n\nh1,h2,h3,h4,h5 {\n color: #000;\n background: #eee;\n}\n\n/*}}}*/\n/***\n!Header /%==================================================%/\n***/\n/*{{{*/\n.header {\n background: #000;\n}\n\n.headerForeground {\n color: #cf6;\n}\n\n.headerForeground a {\n font-weight: normal;\n color: #cf6;\n}\n\n/* ??? what is up when you specify a site title colour in IE ??? */\n/* .siteTitle { color: red; } */\n\n/*}}}*/\n/***\n!General tabs /%=================================================%/\n***/\n/*{{{*/\n\n.tabSelected {\n color: #fff;\n background: #960;\n border: none;\n}\n\n.tabUnselected {\n color: #fff;\n background: #660;\n}\n\n.tabContents {\n color: #004;\n background: #960;\n border: none;\n}\n\n.tabContents .button, .tabContents a {\n border: none;\n color: #fff;\n}\n\n.tabContents a:hover, .tabset a:hover {\n background: #000;\n}\n\n/* make nested tab areas look different */\n.tabContents .tabSelected, .tabContents .tabContents {\n background: #700;\n color: #fff;\n}\n\n.tabContents .tabContents {\n color: #eeb;\n}\n\n/*}}}*/\n/***\n!Main Menu /%=================================================%/\n***/\n/*{{{*/\n#mainMenu {\n background: #700;\n color: #fff;\n border-right: 3px solid #500;\n}\n\n#mainMenu * {\n color: #fff;\n}\n\n#mainMenu a.button, #mainMenu a.tiddlyLink, #mainMenu a.externalLink {\n border: none;\n border-bottom: 1px solid #500;\n border-top: 1px solid #900;\n}\n\n#mainMenu a:hover,\n#mainMenu a.button:hover {\n background-color: #b00;\n color: #fff;\n}\n\n/*}}}*/\n/***\n!Sidebar options /%=================================================%/\n~TiddlyLinks and buttons are treated identically in the sidebar and slider panel\n***/\n/*{{{*/\n#sidebar {\n color: #000;\n background: #eeb;\n border-right: 3px solid #bb8;\n border-bottom: 3px solid #520;\n}\n\n#sidebarOptions .sliderPanel {\n background: #fff;\n}\n\n#sidebarOptions .sliderPanel a {\n border: none;\n color: #700;\n}\n\n#sidebarOptions .sliderPanel a:hover {\n color: #fff;\n background: #700;\n}\n\n#sidebarOptions .sliderPanel a:active {\n color: #700;\n background: #fff;\n}\n\n#sidebarOptions a {\n color: #700;\n border: none;\n}\n\n#sidebarOptions a:hover, #sidebarOptions a:active {\n color: #fff;\n background: #700;\n}\n\n/*}}}*/\n/***\n!Message Area /%=================================================%/\n***/\n/*{{{*/\n#messageArea {\n border-right: 3px solid #da1;\n border-bottom: 3px solid #a80;\n background: #ffe72f;\n color: #014;\n}\n\n/*}}}*/\n/***\n!Popup /%=================================================%/\n***/\n/*{{{*/\n.popup {\n background: #cf6;\n border: none;\n}\n\n.popup hr {\n color: #000;\n}\n\n.popup li.disabled {\n color: #666;\n background: #cf6;\n}\n\n.popup li a, .popup li a:visited {\n color: #000;\n border: 1px outset #cf6;\n background: #cf6;\n}\n\n.popup li a:hover {\n color: #000;\n border: 1px outset #cf6;\n background: #ef9;\n}\n/*}}}*/\n/***\n!Tiddler Display /%=================================================%/\n***/\n/*{{{*/\n.tiddler {\n background: #fff;\n border-right: 3px solid #aaa;\n border-bottom: 3px solid #555;\n}\n\n.title {\n color: #900;\n}\n\n.toolbar {\n color: #000;\n}\n\n.toolbar .button {\n background: #eeb /*#cf6*/;\n border: 1px outset #eeb /*#cf6*/;\n}\n\n.toolbar .button:hover {\n background: #700 /*#ef9*/;\n color: #fff;\n}\n\n#mainMenu .calendar { border: 1px solid white; }\n#mainMenu .calendar, #mainMenu .calendar tr, #mainMenu .calendar td, #mainMenu .calendar a {\n}\n\n/*}}}*/\n\n/***\n!Additional print overrides for fancy style /%==============================================%/\n***/\n/*{{{*/\n\n@media print {\n\n.tiddler {\n /* get rid of our fancy tiddler outline */\n border: none;\n}\n\n}\n/*}}}*/\n
''Guerriers, Voleurs et Magiciens'' est une adaptation et une simplification du dK system destiné à jouer rapidement, éventuellement avec des débutants ou en convention. En cours de développement, il sera à terme une alternative intéressante pour tous ceux qui veulent faire de l'initiation en club, dans les écoles, en convention.\nNous espérons que le fichier sera aussi assez complet pour qu'un complet débutant puisse y trouver tout ce qu'il faut pour se lancer dans notre hobby.\n\n[img[http://legrumph.org/VP/GVM.jpg]]\n\nVous trouverez le fichier tiddlywiki du GVM à cette adresse : [[GVM.htm|http://legrumph.org/VP/GVM.htm]]. Vous pouvez le consulter en ligne ou le télécharger sur votre ordinateur (click droit et //enregistrer sous//). Dès que possible, les cartes à découper seront disponibles.
/***\n|''Name:''|ImportTiddlersPlugin|\n|''Source:''|http://www.TiddlyTools.com/#ImportTiddlersPlugin|\n|''Author:''|Eric Shulman - ELS Design Studios|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|''~CoreVersion:''|2.0.10|\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. It can also be very extremely helpful 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\nThis plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. Automatically add tags to imported tiddlers so they are easy to find later on. Generates a detailed report of import 'history' in ImportedTiddlers.\n!!!!!Interactive interface\n<<<\n{{{<<importTiddlers>>}}} or {{{<<importTiddlers core>>}}}\ninvokes the built-in importTiddlers macro (TW2.1.x+). If installed in documents using TW2.0.x or earlier, fallback is to use 'link' display (see below)\n\n{{{<<importTiddlers link>>}}}\ncreates "import tiddlers" link that when clicked to show/hide import control panel\n\n{{{<<importTiddlers inline>>}}}\ncreates import control panel directly in tiddler content\n\n<<importTiddlers inline>>\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!!!!!non-interactive 'load tiddlers' macro\n<<<\nUseful for automated installation/update of plugins and other tiddler content.\n\n{{{<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>}}}\n<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>\n\nSyntax:\n{{{<<loadTiddlers label:text prompt:text filter source quiet confirm>>}}}\n\n''label:text'' and ''prompt:text''\n>defines link text and tooltip (prompt) that can be clicked to trigger the load tiddler processing. If a label is NOT provided, then no link is created and loadTiddlers() is executed whenever the containing tiddler is rendered.\n''filter'' (optional) determines which tiddlers will be automatically selected for importing. Use one of the following keywords:\n>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.\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>''"tiddler:~TiddlerName"'' retrieves only the specific tiddler named in the parameter.\n>''"tag:text"'' retrieves only the tiddlers tagged with the indicated text.\n''source'' (required) is the location of the imported document. It can be either a local document path/filename in whatever format your system requires, or a remote web location (starting with "http://" or "https://")\n>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked\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''"confirm"'' (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!!!!!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.11.14 [3.1.2]'' fix macro handler parameter declaration (double-pasted param list corrupts IE)\n''2006.11.13 [3.1.1]'' use apply() method to invoke hijacked core handler\n''2006.11.13 [3.1.0]'' hijack TW2.1 built-in importTiddlers.handler() so it can co-exist with the plugin interface 'panel'. Use macro without params (or use 'core' keyword) to display built-in core interface. Use new "link" param to embed "import tiddlers" link that shows floating panel when clicked. Renamed a few plugin utility functions so they don't collide with core internal functions. More code restructuring to come.\n''2006.10.12 [3.0.8]'' in readTiddlersFromHTML(), fallback to find end of store area by matching "/body" when POST-BODY-START is not present (backward compatibility for older documents)\n''2006.09.10 [3.0.7]'' in readTiddlersFromHTML(), find end of store area by matching "POST-BODY-START" instead of "/body" \n''2006.08.16 [3.0.6]'' Use higher-level store.saveTiddler() instead of store.addTiddler() to avoid conflicts with ZW and other adaptations that hijack low-level tiddler handling. Also, in CreateImportPanel(), no longer register notify to "refresh listbox after every tiddler change" (left over from old 'auto-filtered' list handling). Thanks to Bob McElrath for report/solution.\n''2006.07.29 [3.0.5]'' added noChangeMsg to loadTiddlers processing. if not 'quiet' mode, reports skipped tiddlers.\n''2006.04.18 [3.0.4]'' in loadTiddlers.handler, fixed parsing of "prompt:" param. Also, corrected parameters mismatch in loadTiddlers() callback function definition (order of params was wrong, resulting in filters NOT being applied)\n''2006.04.12 [3.0.3]'' moved many display messages to macro properties for easier L10N translations via 'lingo' definitions.\n''2006.04.12 [3.0.2]'' additional refactoring of 'core candidate' code. Proposed API now defines "loadRemoteFile()" for XMLHttpRequest processing with built in fallback for handling local filesystem access, and readTiddlersFromHTML() to process the resulting source HTML content.\n''2006.04.04 [3.0.1]'' in refreshImportList(), when using [by tags], tiddlers without tags are now included in a new "untagged" psuedo-tag list section\n''2006.04.04 [3.0.0]'' Separate non-interactive {{{<<importTiddlers...>>}}} macro functionality for incorporation into TW2.1 core and renamed as {{{<<loadTiddlers>>}}} macro. New parameters for loadTiddlers: ''label:text'' and ''prompt:text'' for link creation, ''ask'' for filename/URL, ''tag:text'' for filtering, "confirm" for accept/reject of individual inbound tiddlers. Also, ImportedTiddlers report generator output has been simplified and "importReplace/importPublic" tags and associated "force" param (which were rarely, if ever, used) has been dropped.\n''2006.03.30 [2.9.1]'' when extracting store area from remote URL, look for "</body>" instead of "</body>\sn</html>" so it will match even if the "\sn" is absent from the source.\n''2006.03.30 [2.9.0]'' added optional 'force' macro param. When present, autoImportTiddlers() bypasses the checks for importPublic and importReplace. Based on a request from Tom Otvos.\n''2006.03.28 [2.8.1]'' in loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (IE does *not* define these values, so we bypass this code)\nAlso, when extracting store area from remote URL, explicitly look for "</body>\sn</html>" to exclude any extra content that may have been added to the end of the file by hosting environments such as GeoCities. Thanks to Tom Otvos for finding these bugs and suggesting some fixes.\n''2006.02.21 [2.8.0]'' added support for "tiddler:TiddlerName" filtering parameter in auto-import processing\n''2006.02.21 [2.7.1]'' Clean up layout problems with IE. (Use tables for alignment instead of SPANs styled with float:left and float:right)\n''2006.02.21 [2.7.0]'' Added "local file" and "web server" radio buttons for selecting dynamic import source controls in ImportPanel. Default file control is replaced with URL text input field when "web server" is selected. Default remote document URL is defined in SiteURL tiddler. Also, added option for prepending SiteProxy URL as prefix to remote URL to mask cross-domain document access (requires compatible server-side script)\n''2006.02.17 [2.6.0]'' Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.\n''2006.02.16 [2.5.4]'' added checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.\n''2006.02.14 [2.5.3]'' FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()\n''2006.02.10 [2.5.2]'' corrected unintended global variable in importReport().\n''2006.02.05 [2.5.1]'' moved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2006.01.18 [2.5.0]'' added checkbox for "create a report". Default is to create/update the ImportedTiddlers report. Clear the checkbox to skip this step.\n''2006.01.15 [2.4.1]'' added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic\n''2006.01.15 [2.4.0]'' Added support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax. Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.\n''2006.01.15 [2.3.2]'' Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)\n''2006.01.15 [2.3.1]'' Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME. Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins). Seems to resolve the "Found 0 tiddlers" problem. Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.\n''2006.01.12 [2.3.0]'' Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest. Let's processing continue while waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source. Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.\n''2006.01.11 [2.2.0]'' Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck\n''2006.01.09 [2.1.1]'' When a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button. This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit. I removed the onChange handling for file input field. To open a file (local or URL), you must now explicitly press the "open" button in the control panel.\n''2006.01.08 [2.1.0]'' IMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.\n''2006.01.06 [2.0.2]'' When refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.\n''2006.01.04 [2.0.1]'' When "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.\n''2005.12.27 [2.0.0]'' Update 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]'' tweak formatting in importReport() and add 'discard report' link to output\n''2005.12.03 [1.3.0]'' Dynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)\n''2005.11.29 [1.2.1]'' fixed formatting of 'detail info' in importReport()\n''2005.11.11 [1.2.0]'' added 'inline' param to embed controls in a tiddler\n''2005.11.09 [1.1.0]'' only load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.\n''2005.10.25 [1.0.5]'' fixed typo in importReport() that prevented reports from being generated\n''2005.10.09 [1.0.4]'' combined documentation with plugin code instead of using separate tiddlers\n''2005.08.05 [1.0.3]'' moved CSS and HTML definitions into plugin code instead of using separate tiddlers\n''2005.07.27 [1.0.2]'' core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()\n''2005.07.23 [1.0.1]'' added parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]'' Initial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n// // ''MACRO DEFINITION''\n//{{{\n// Version\nversion.extensions.importTiddlers = {major: 3, minor: 1, revision: 2, date: new Date(2006,11,14)};\n\n// IE needs explicit global scoping for functions/vars called from browser events\nwindow.onClickImportButton=onClickImportButton;\nwindow.refreshImportList=refreshImportList;\n\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\n// fixups for TW2.0.x and earlier\nif (window.merge==undefined) window.merge=function(dst,src,preserveExisting)\n { for (p in src) if (!preserveExisting||dst[p]===undefined) dst[p]=src[p]; return dst; }\nif (config.macros.importTiddlers==undefined) config.macros.importTiddlers={ };\n\nmerge(config.macros.importTiddlers,{\n label: "import tiddlers",\n prompt: "Copy tiddlers from another document",\n foundMsg: "Found %0 tiddlers in %1",\n countMsg: "%0 tiddlers selected for import",\n importedMsg: "Imported %0 of %1 tiddlers from %2",\n src: "", // path/filename or URL of document to import (retrieved from SiteUrl tiddler)\n proxy: "", // URL for remote proxy script (retrieved from SiteProxy tiddler)\n useProxy: false, // use specific proxy script in front of remote URL\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\nif (config.macros.importTiddlers.coreHandler==undefined)\n config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler\n\nconfig.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!params[0] || params[0].toLowerCase()=='core') { // default to built in\n if (config.macros.importTiddlers.coreHandler)\n config.macros.importTiddlers.coreHandler.apply(this,arguments);\n else \n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n }\n else if (params[0]=='link') // show link to floating panel\n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n else if (params[0]=='inline') {// show panel as INLINE tiddler content\n createImportPanel(place);\n document.getElementById("importPanel").style.position="static";\n document.getElementById("importPanel").style.display="block";\n }\n else config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers\n}\n//}}}\n\n// // ''INTERFACE DEFINITION''\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\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 refreshImportList();\n var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";\n document.getElementById("importSourceURL").value=siteURL;\n config.macros.importTiddlers.src=siteURL;\n var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";\n document.getElementById("importSiteProxy").value=siteProxy;\n config.macros.importTiddlers.proxy=siteProxy;\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 background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\s\n padding: 0.5em; margin:0em; -moz-border-radius:1em;\s\n}\s\n#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\s\n#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\s\n#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\s\n#importPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\s\n#importPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\s\n#importPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\s\n#importPanel .rad { width:auto; }\s\n#importPanel .chk { width:auto; margin:1px;border:0; }\s\n#importPanel .btn { width:auto; }\s\n#importPanel .btn1 { width:98%; }\s\n#importPanel .btn2 { width:48%; }\s\n#importPanel .btn3 { width:32%; }\s\n#importPanel .btn4 { width:24%; }\s\n#importPanel .btn5 { width:19%; }\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#importCollisionPanel { display:none; margin:0.5em 0em 0em 0em; }\s\n';\n//}}}\n\n// // HTML \n//{{{\nconfig.macros.importTiddlers.html = '\s\n<!-- source and report -->\s\n<table><tr><td align=left>\s\n import from\s\n <input type="radio" class="rad" name="importFrom" value="file" CHECKED\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=!this.checked?\s'block\s':\s'none\s'"> local file\s\n <input type="radio" class="rad" name="importFrom" value="http"\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=!this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=this.checked?\s'block\s':\s'none\s'"> web server\s\n</td><td align=right>\s\n <input type=checkbox class="chk" id="chkImportReport" checked\s\n onClick="config.options[\s'chkImportReport\s']=this.checked;"> create a report\s\n</td></tr></table>\s\n<!-- import from local file -->\s\n<div id="importLocalPanel" style="display:block;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\nlocal document path/filename:<br>\s\n<input type="file" id="fileImportSource" size=57 style="width:100%"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<!-- import from http server -->\s\n<div id="importHTTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\n<table><tr><td align=left>\s\n remote document URL:<br>\s\n</td><td align=right>\s\n <input type="checkbox" class="chk" id="importUseProxy"\s\n onClick="config.macros.importTiddlers.useProxy=this.checked;\s\n document.getElementById(\s'importSiteProxy\s').style.display=this.checked?\s'block\s':\s'none\s'"> use a proxy script\s\n</td></tr></table>\s\n<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\s\n onKeyUp="config.macros.importTiddlers.proxy=this.value"\s\n onChange="config.macros.importTiddlers.proxy=this.value;">\s\n<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<table><tr><td align=left>\s\n select:\s\n <a href="JavaScript:;" id="importSelectAll"\s\n onclick="onClickImportButton(this)" title="select all tiddlers">\s\n all </a>\s\n <a href="JavaScript:;" id="importSelectNew"\s\n onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\s\n added </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 changes </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 differences </a> \s\n <a href="JavaScript:;" id="importToggleFilter"\s\n onclick="onClickImportButton(this)" title="show/hide selection filter">\s\n filter </a> \s\n</td><td align=right>\s\n <a href="JavaScript:;" id="importListSmaller"\s\n onclick="onClickImportButton(this)" title="reduce list size">\s\n – </a>\s\n <a href="JavaScript:;" id="importListLarger"\s\n onclick="onClickImportButton(this)" title="increase list size">\s\n + </a>\s\n <a href="JavaScript:;" id="importListMaximize"\s\n onclick="onClickImportButton(this)" title="maximize/restore list size">\s\n = </a>\s\n</td></tr></table>\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 class="chk" id="chkAddTags" checked\s\n onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags \s\n<input type=checkbox class="chk" id="chkImportTags" checked\s\n onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags \s\n<input type=checkbox class="chk" id="chkKeepTags" checked\s\n onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags<br>\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="importCollisionPanel">\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// // 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 theCollisionPanel = document.getElementById('importCollisionPanel');\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 config.macros.importTiddlers.loadRemoteFile(config.macros.importTiddlers.src, function(src,txt) {\n var tiddlers = readTiddlersFromHTML(txt);\n var count=tiddlers?tiddlers.length:0;\n displayMessage(config.macros.importTiddlers.foundMsg.format([count,src]));\n config.macros.importTiddlers.inbound=tiddlers;\n window.refreshImportList(0);\n });\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 theCollisionPanel.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 theCollisionPanel.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: ';\n theText +='[['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\sn';\n theText +='^^'+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 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.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 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.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// // 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 if (!tags || !tags.length) {\n if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }\n theTitles["untagged"].push(title);\n }\n else 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// // 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 inbound = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(inbound.title);\n // avoid redundant import for tiddlers that are listed multiple times (when 'by tags')\n if (inbound.status=="added")\n continue;\n // don't import the "ImportedTiddlers" history from the other document...\n if (inbound.title=='ImportedTiddlers')\n continue;\n // if tiddler exists and import not marked for replace or merge, stop importing\n if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.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+=inbound.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 inbound.set(null,null,null,null,newTags.trim());\n // set the status to 'added' (if not already set by the 'ask the user' UI)\n inbound.status=(inbound.status=="")?'added':inbound.status;\n // do the import!\n // OLD: store.addTiddler(in); store.setDirty(true);\n store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags);\n store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value\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 collision panel and set the title edit field\n document.getElementById('importCollisionPanel').style.display='block';\n theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;\n }\n}\n//}}}\n\n// // ''REPORT GENERATOR''\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 collision panel will still be open... close it now.\n var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';\n\n // get the alphasorted list of tiddlers\n var tiddlers = config.macros.importTiddlers.inbound;\n // gather the statistics\n var count=0;\n for (var t=0; t<tiddlers.length; t++)\n if (tiddlers[t].status && tiddlers[t].status.trim().length && tiddlers[t].status.substr(0,7)!="skipped") count++;\n\n // generate a report\n if (count && config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName\n newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\sn[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\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 newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n// 20060918 ELS: DON'T ADD "discard" BUTTON TO REPORT\n// newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n// newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n// newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n // OLD: store.addTiddler(theReport);\n store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n\n // reset status flags\n for (var t=0; t<config.macros.importTiddlers.inbound.length; t++) config.macros.importTiddlers.inbound[t].status="";\n\n // refresh display if tiddlers have been loaded\n if (count) { store.setDirty(true); store.notifyAll(); }\n\n // always show final message when tiddlers were actually loaded\n if (count) displayMessage(config.macros.importTiddlers.importedMsg.format([count,tiddlers.length,config.macros.importTiddlers.src]));\n}\n//}}}\n\n/***\n!!!!! non-interactive 'load tiddlers' macro\n***/\n//{{{\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\nconfig.macros.loadTiddlers = {\n label: "",\n prompt: "add/update tiddlers from '%0'",\n askMsg: "Please enter a local path/filename or a remote URL",\n openMsg: "Opening %0",\n openErrMsg: "Could not open %0 - error=%1",\n readMsg: "Read %0 bytes from %1",\n foundMsg: "Found %0 tiddlers in %1",\n nochangeMsg: "'%0' is up-to-date... skipped.",\n loadedMsg: "Loaded %0 of %1 tiddlers from %2"\n};\n\nconfig.macros.loadTiddlers.handler = function(place,macroName,params) {\n var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;\n var prompt=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.prompt;\n var filter="updates";\n if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'\n || params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))\n filter=params.shift();\n var src=params.shift(); if (!src || !src.length) return; // filename is required\n var quiet=(params[0]=="quiet"); if (quiet) params.shift();\n var ask=(params[0]=="confirm"); if (ask) params.shift();\n var force=(params[0]=="force"); if (force) params.shift();\n if (label.trim().length) {\n // link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store\n createTiddlyButton(place,label.format([src]),prompt.format([src]), function() {\n if (src=="ask") src=prompt(config.macros.loadTiddlers.askMsg);\n config.macros.importTiddlers.loadRemoteFile(src,loadTiddlers,quiet,ask,filter,force);\n })\n }\n else {\n // load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store\n if (src=="ask") src=prompt(config.macros.loadTiddlers.askMsg);\n config.macros.importTiddlers.loadRemoteFile(src,loadTiddlers,quiet,ask,filter,force);\n }\n}\n\nfunction loadTiddlers(src,html,quiet,ask,filter,force)\n{\n var tiddlers = readTiddlersFromHTML(html);\n var count=tiddlers?tiddlers.length:0;\n if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src]));\n var count=0;\n if (tiddlers) for (var t=0;t<tiddlers.length;t++) {\n var inbound = tiddlers[t];\n var theExisting = store.getTiddler(inbound.title);\n if (inbound.title=='ImportedTiddlers')\n continue; // skip "ImportedTiddlers" history from the other document...\n\n // apply the all/new/changes/updates filter (if any)\n if (filter && filter!="all") {\n if ((filter=="new") && theExisting) // skip existing tiddlers\n continue;\n if ((filter=="changes") && !theExisting) // skip new tiddlers\n continue;\n if ((filter.substr(0,4)=="tag:") && inbound.tags.find(filter.substr(4))==null) // must match specific tag value\n continue;\n if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name\n continue;\n if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0))\n { if (!quiet) displayMessage(config.macros.loadTiddlers.nochangeMsg.format([inbound.title])); continue; }\n }\n // get confirmation if required\n if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\snfrom "+src))\n { tiddlers[t].status="skipped - cancelled by user"; continue; }\n // DO IT!\n // OLD: store.addTiddler(in);\n store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags);\n store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value\n tiddlers[t].status=theExisting?"updated":"added"\n count++;\n }\n if (count) {\n // refresh display\n store.setDirty(true);\n store.notifyAll();\n // generate a report\n if (config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName+" loaded "+count+" tiddlers from\sn[["+src+"|"+src+"]]:\sn";\n newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n// 20060918 ELS: DON'T ADD "discard" BUTTON TO REPORT\n// newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n// newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n// newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n // OLD: store.addTiddler(theReport);\n store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n }\n // always show final message when tiddlers were actually loaded\n if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src]));\n}\n\n// replaces existing core function\n\nconfig.macros.importTiddlers.loadRemoteFile = function(src,callback,quiet,ask,filter,force) {\n if (src==undefined || !src.length) return null; // filename is required\n if (!quiet) clearMessage();\n if (!quiet) displayMessage(config.macros.loadTiddlers.openMsg.format([src]));\n if (src.substr(0,4)!="http" && src.substr(0,4)!="file") { // if not a URL, fallback to read from local filesystem\n var txt=loadFile(src);\n if ((txt==null)||(txt==false)) // file didn't load\n { if (!quiet) displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,"(unknown)"])); }\n else {\n if (!quiet) displayMessage(config.macros.loadTiddlers.readMsg.format([txt.length,src]));\n if (callback) callback(src,convertUTF8ToUnicode(txt),quiet,ask,filter,force);\n }\n }\n else {\n var x; // get an request object\n try {x = new XMLHttpRequest()} // moz\n catch(e) {\n try {x = new ActiveXObject("Msxml2.XMLHTTP")} // IE 6\n catch (e) {\n try {x = new ActiveXObject("Microsoft.XMLHTTP")} // IE 5\n catch (e) { return }\n }\n }\n // setup callback function to handle server response(s)\n x.onreadystatechange = function() {\n if (x.readyState == 4) {\n if (x.status==0 || x.status == 200) {\n if (!quiet) displayMessage(config.macros.loadTiddlers.readMsg.format([x.responseText.length,src]));\n if (callback) callback(src,x.responseText,quiet,ask,filter,force);\n }\n else {\n if (!quiet) displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,x.status]));\n }\n }\n }\n // get privileges to read another document's DOM via http:// or file:// (moz-only)\n if (typeof(netscape)!="undefined") {\n try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }\n catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }\n }\n // send the HTTP request\n try {\n var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();\n x.open("GET",src,true);\n if (x.overrideMimeType) x.overrideMimeType('text/html');\n x.send(null);\n }\n catch (e) {\n if (!quiet) {\n displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,"(unknown)"]));\n displayMessage(e.description?e.description:e.toString());\n }\n }\n }\n}\n\nfunction readTiddlersFromHTML(html)\n{\n // extract store area from html \n var start=html.indexOf('<div id="storeArea">');\n var end=html.indexOf("<!--POST-BODY-START--"+">",start);\n if (end==-1) var end=html.indexOf("</body"+">",start); // backward-compatibility for older documents\n var sa="<html><body>"+html.substring(start,end)+"</body></html>";\n\n // load html into iframe document\n var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);\n f=document.createElement("iframe"); f.id="loaderFrame";\n f.style.width="0px"; f.style.height="0px"; f.style.border="0px";\n document.body.appendChild(f);\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 d.open(); d.writeln(sa); d.close();\n\n // read tiddler DIVs from storeArea DOM element \n var sa = d.getElementById("storeArea");\n if (!sa) return null;\n sa.normalize();\n var nodes = sa.childNodes;\n if (!nodes || !nodes.length) return null;\n var tiddlers = [];\n for(var t = 0; t < nodes.length; t++) {\n var title = null;\n if(nodes[t].getAttribute)\n title = nodes[t].getAttribute("tiddler");\n if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))\n title = nodes[t].id.substr(5);\n if(title && title != "")\n tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));\n }\n return tiddlers;\n}\n//}}}
!Piratage\nSi vous désirez effectuer une opération sur un serveur pour lequel vous ne possédez ni les codes ni les autorisations - si vous voulez le pirater - vous pouvez procéder de deux manières :\n*Si vous ne voulez pas ralentir la fluidité du jeu, vous pouvez n'effectuer qu'un seul jet pour l'ensemble des opérations que vous voulez effectuer. La difficulté dépend de la couleur du système visé auquel vous ajoutez un dK pour chaque opération planifiée. En cas de réussite, tous vos objectifs sont remplis ; en cas d'échec, vous pouvez avoir déclenché une alerte.\n*Si vous le préférez, par exemple pour accompagner une action physique en temps réel, vous pouvez effectuer un jet pour chaque opération. Chaque jet réussi fait baisser la sécurité adverse de 1, 2 ou 3d6 - selon les programmes d'attaque que vous possédez. Chaque jet raté fait baisser votre score d'intrusion (égal à la somme de la valeur de votre matériel et du score total de votre compétence). Lorsque vous arrivez à 0 points d'intrusion, vous pouvez déclencher une alerte à tout moment. Si la sécurité du système est entièrement annulée, vous pouvez librement agir dans la machine tant que vous ne vous déconnectez pas.\n!Couleur\nTechniquement, pour attaquer un domaine adverse (celui d’une personne ou d’une machine), vous devez effectuez un jet de //Réseaux// contre une difficulté variable, éventuellement avec des dK de circonstance si le domaine en question est protégé. Vous pouvez aussi devoir agir contre un ingénieur, en opposition.\nLa difficulté varie de 15 (un domaine mal configuré, avec les portes de derrière ouvertes, tenu par une gamine de 15 ans qui ne s’en sert que pour faire des rencontres virtuelles avec ses copines ou du shopping) à 20 (un domaine tenu par un utilisateur sérieux, formé, correctement protégé par des programmes commerciaux solides) ou à 40 (un domaine tenu par un paranoïaque, un ingénieur informaticien défenseur du code source ultime ou un agent d’une agence de sécurité qui se fait configurer son domaine par l’un des deux premiers). Les dK de circonstance s’appliquent si des programmes spécifiques ont été installés ou des options particulières cochées.\n\nLes systèmes informatiques sont classés selon leur sécurité et à leur protection effective contre les intrusions, les virus et autres manipulations.\n|''Couleur du système''|''Sécurité (difficulté)''|''Achat''|\n|Vert|15|15|\n|Jaune|20|22|\n|Cyan|25|28|\n|Indigo|30|37|\n|Rouge|35|48|\n|Noir|40|60|\n!Alerte\nSi vous échouez à un jet d'intrusion - ou si vos points d'intrusion sont réduits à 0 et que l'adversaire obtient un 6 sur ses dégâts ou un double-6 en cours d'opération (selon les règles habituelles de combat ou de poursuite) - vous déclenchez une alerte. L'effet de l'alerte dépend de la couleur du système. Lancez 1d12 et appliquez les effets.\n\n| |''Vert''|''Jaune''|''Cyan''|\n|1|System sweep|System sweep|System sweep|\n|2|System sweep|System sweep|System sweep + connection logged|\n|3|System sweep|Connection logged|Connection logged + access denied|\n|4|Connection logged|Connection logged|Authentication required|\n|5|Connection logged|Access denied|Authentication required + connection logged|\n|6|Access denied|Access denied|Trace initiated|\n|7|Access denied|Authentication required|Trace initiated + connection logged|\n|8|Authentication required|Trace initiated|Disruptor drone activated|\n|9|Trace initiated|Authentication required + tracer initiated|Disruptor drone activated + trace initiated|\n|10|Trace initiated|Disruptor drone activated|Administrator alert + trace initiated|\n|11|Administrator alert|Administrator alert + trace initiated|Administrator alert + trace initiated|\n|12|Disconnected|Disconnected|Disconnected|\n| |''Indigo''|''Rouge''|''Noir''|\n|1|System sweep + connection logged|System sweep + connection logged + access denied|Retroactive tracer initiated + connection logged + authentication required|\n|2|Connection logged + access denied|Retroactive tracer initiated|Retroactive tracer initiated + connection logged + authentication required|\n|3|Access denied + authentication required|Disruptor drone activated + retroactive tracer initiated|Retroactive tracer initiated + connection logged + access denied + authentication required|\n|4|Retroactive tracer initiated|Destroyer drone activated + retroactive tracer initiated|Retroactive tracer initiated + connection logged + access denied + authentication required|\n|5|Disruptor drone activated + retroactive tracer initiated|Destroyer drone activated + retroactive tracer initiated|Destroyer drone activated + retroactive tracer initiated + administrator alert|\n|6|Disruptor drone activated + retroactive tracer initiated|Retroactive tracer initiated + access denied|Destroyer drone activated + retroactive tracer initiated + administrator alert|\n|7|Destroyer drone activated + retroactive tracer initiated|Retroactive tracer initiated + authentication required|Destroyer drone activated + retroactive tracer initiated + administrator alert|\n|8|Destroyer drone activated + retroactive tracer initiated|Administrator alert + retroactive tracer initiated|Killer drone activated + retroactive tracer initiated + administrator alert|\n|9|Retroactive tracer initiated + access denied|Administrator alert + retroactive tracer initiated|Killer drone activated + retroactive tracer initiated + administrator alert|\n|10|Administrator alert + retroactive tracer initiated|Killer drone activated + retroactive tracer initiated|Killer drone activated + retroactive tracer initiated + administrator alert|\n|11|Disconnected|Disconnected|Disconnected|\n|12|Disconnected|Disconnected|Disconnected|\n\n[''Access denied'': The system temporarily blocks all access. The hacker cannot take any action in the system for d6 rounds.]\n[''Administrator alert'': The system’s administrator is alerted to the presence of an intruder and coordinates security measures against him more effectively. This has the following effects: 1. Halve the time required for any trace already in progress or any trace initiated in the future until the hacker logs off or is disconnected, 2. Any system sweep inflicts a –10 penalty instead of –5, 3. Any drone activated gets a +2 bonus to its attack roll.]\n[''Authentication required'': Access is denied to the hacker and the system requires him to verify his authentication again. This obstacle must be overcome by taking a successful bypass authentication action before the hacker can proceed with his task.]\n[''Connection logged'': The hacker’s attempted action is logged twice instead of just once. This creates an additional log for him to cope with.]\n[''Destroyer drone activated'': A destroyer drone engages the hacker in hivenet combat. Destroyer drones are detailed in the software section.]\n[''Disconnected'': The hacker’s connection to the remote system is immediately terminated. If he still wants to have a try at infiltrating the system, he has to begin again from the start.]\n[''Disruptor drone activated'': A disruptor drone engages the hacker in hivenet combat. Disruptor drones are detailed in the software section.]\n[''Killer drone activated'': A killer drone engages the hacker in hivenet combat. Killer drones are detailed in the software section.]\n[''Retroactive trace initiated'': Retroactive traces have been designed to defeat hacking attempts made from a constantly changing location (ie by hackers that are on the move using a satellite link to connect to the hivenet). This works exactly like a normal trace, but as soon as the trace is complete the remote system sends a small file to be installed in the hacker’s computer. Thereafter, each time the hacker connects to the hivenet (not necessarily logging on the same system), the installed tracer reports his location to the system administrator. The tracer file is minute in size and doesn’t take up any memory, speed slots or bandwidth. A retroactive trace will be detected by a trace monitor as a normal trace. If the hacker suspects that a retroactive tracer has been placed in his computer, he may find it by taking a system scan action.]\n[''System sweep'': The system detects suspicious activity and initiates a full sweep. This makes the hacker’s job more difficult, inflicting a –5 penalty on his next Computer Use check.]\n[''Trace initiated'': The remote system attempts to trace the hacker’s connection back to his physical location. The hacker won’t be aware that he’s being traced unless he uses an active trace monitor. Once a trace is initiated, it can’t be stopped unless the hacker disconnects from the hivenet. Each new “trace initiated result” will decrease the time required for the trace to be completed by d6 rounds. A trace usually takes d6 rounds to be completed, but if the hacker has “bounced” his connection, an additional d6 rounds per bounce are required. Once the trace concludes, the system (and its administrators) becomes aware of the hacker’s physical location (ie the place from which he connects to the hivenet).]\n
<<gradient horiz #bbbbbb #eeeeee #ffffff>>Après avoir joué pendant un an et demi avec des krâsses sur 6 uniquement, je suis passé dernièrement aux krâsses sur 6 et 3. Et bien, c'est assez équilibré !>>\nMaintenant, à ma table, les dK font des krâsses sur 6 et 3.\nLes joueurs (et les PNJ) peuvent ajouter 3 ou 6 (selon le résultat) à leur d20 pour calculer le score final. Bien entendu, seuls les 6 comptent pour les blessures (en tout cas en version héroïque).\nC'est assez équilibré et je pense que cela devrait satisfaire ceux qui pensent que les krâsses sur 6 sont peu équilibrées et ne servent à rien. L'ajout du 3 ajoute de la dymanique et permet aussi de lancer moins de dés pour un résultat assuré (ou presque).\nEn tout cas, mes joueurs sont très contents (même quand ce sont les méchants qui obtiennent des 3 !)
/***\n|''Name:''|LegacyStrikeThroughPlugin|\n|''Description:''|Support for legacy (pre 2.1) strike through formatting|\n|''Version:''|1.0.1|\n|''Date:''|Jul 21, 2006|\n|''Source:''|http://www.tiddlywiki.com/#LegacyStrikeThroughPlugin|\n|''Author:''|MartinBudden (mjbudden (at) gmail (dot) com)|\n|''License:''|[[BSD open source license]]|\n|''CoreVersion:''|2.1.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n\n***/\n\n//{{{\n\n// Ensure that the LegacyStrikeThrough Plugin is only installed once.\nif(!version.extensions.LegacyStrikeThroughPlugin)\n {\n version.extensions.LegacyStrikeThroughPlugin = true;\n\nconfig.formatters.push(\n{\n name: "legacyStrikeByChar",\n match: "==",\n termRegExp: /(==)/mg,\n element: "strike",\n handler: config.formatterHelpers.createElementAndWikify\n});\n\n} // end of "install only once"\n//}}}\n
[[Mode d'emploi]]\n[[dKrunch]]\n[[Univers]]\n[[FAQs]]
Armes et armures n'ont certes pas des conceptions standardisées. Il y a peu en commun entre les bricolages, les expérimentations, les assemblages hétéroclites d'une part et les équipements testés, éprouvés et fabriqués à la chaîne par des maîtres artisans d'autre part. \n*''Militaires'' : Les armes et armures militaires sont généralement parfaitement calibrées. On sait à quoi s'attendre avec elles et elles déçoivent rarement. Les armes militaires font toujours 4, 8 ou 12 points de dégâts. On considère qu'elles provoquent toujours une (et une seule) blessure grave lorsque l'adversaire est mal en point. Les armures militaires protègent de 2, 4 ou 6 points avec un encombrement équivalent.\n*''Mercenaire'' : Les armes et armures mercenaires sont des équipements de bric et de broc, capables du meilleurs comme du pire. Les armes mercenaires font 1d6, 2d6 ou 3d6 points de dégâts et les armures mercenaires protègent de 1d6-2, 1d6 et 1d6+2 points, pour un encombrement de 2, 4 ou 6 points.\nLorsqu'un personnage choisit une arme ou une armure, il doit définir à quelle catégorie celle-ci appartient. Le plus souvent, la catégorie sera dictée par l'origine ou la provenance de l'arme, éventuellement par son apparence extérieure.\n>[Option] Considérez enfin qu'une armure militaire donne un bonus de +1 en //Diplomatie// tandis qu'une armure mercenaire donne un bonus de +1 en //Intimidation//.
Ce site est un tiddlywiki, c'est-à-dire un outil formidable et révolutionnaire - un wiki léger, portable et exportable sous la forme d'un seul fichier html que vous pouvez consulter en ligne ou tranquillement chez vous si vous le téléchargez sur votre ordinateur. Vous pouvez aussi, très simplement, créer votre propre tiddlywiki et y importer certains articles qui vous intéressent.\nVous trouverez toutes les informations que vous voulez sur les tiddlywiki à cette adresse : [[tiddlywiki.com|http://www.tiddlywiki.com/]].\n\n*Laissez-vous guider par les liens en bleu pour naviguer d'un article à un autre.\n*Les tags sont des références. Un même article peut ainsi être référencé dans plusieurs catégories pour une consultation plus simple et plus complète.\n*Vous pouvez aussi utiliser l'outil de recherche, en haut et à droite de votre écran. Il est très puissant et très rapide.
Vous trouverez dans la fenêtre //Tagging//, à droite, la liste des modules dKrunch proposés par les utilisateurs de la Matrice.
/***\n''NestedSlidersPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman\nsource: http://www.elsdesign.com/tiddlywiki/#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//''note: Enabling these settings may produce unexpected results. Use at your own risk.''//\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 'default to open', 'cookiename', 'heading level', 'custom label/tooltip', 'automatic blockquote' and 'deferred rendering'.\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)}}}^^\nsave the slider opened/closed state, and restore 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* {{{[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----\ndefault to open: \n{{{\n++++\n content\n===\n}}}\n++++\n content\n===\n----\nuse a custom label: \n{{{\n+++[label]\n content\n===\n}}}\n+++[label]\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, custom label/tooltip, blockquoted)//\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 slider with more specific info:\n +++[view details...|click for details]>\n put some detail here, which could include some +++[definitions]>explaining technical terms===\n ===\n===\n}}}\n+++[get info...|click for information]>\n put some general information here, plus a slider with more specific info:\n +++[view details...|click for details]>\n put some detail here, which could include some +++[definitions]>explaining technical terms===\n === \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.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]] based on considerable research, programming and suggestions from RodneyGomes, GeoffSlocock, and PaulPetterson\n===\n***/\n// //+++!!!!![Code]\n//{{{\nversion.extensions.nestedSliders = {major: 1, minor: 6, revision: 2, date: new Date(2006,1,3)};\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\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\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 // 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[4]) {\n title = lookaheadMatch[4].trim().substr(1,lookaheadMatch[4].length-2);\n if ((pos=title.indexOf("|")) != -1)\n { tooltip = title.substr(pos+1,title.length); title = title.substr(0,pos); }\n else\n { tooltip += " "+title; }\n }\n // use "Hn" header format instead of button/link\n if (lookaheadMatch[3]) {\n var lvl=(lookaheadMatch[3].length>6)?6:lookaheadMatch[3].length;\n var btn = createTiddlyElement(createTiddlyElement(w.output,"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 }\n else\n var btn = createTiddlyButton(w.output,title,tooltip,onClickNestedSlider);\n var panel = createTiddlyElement(w.output,"span",null,"sliderPanel",null);\n btn.sliderCookie = cookie;\n btn.sliderPanel = panel;\n panel.style.display = show;\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n if (!lookaheadMatch[6] || show=="block") {\n w.subWikify(lookaheadMatch[5]?createTiddlyElement(panel,"blockquote"):panel,this.terminator);\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[5]?"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)\n 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// DISABLED: animation sets overflow:hidden, which clips nested sliders...\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 return false;\n}\n//}}}\n// //===
<<gtdActionList>>
The outcome for this project is
/***\n|''Name:''|NewerTiddlerPlugin|\n|''Version:''|$Revision: 13 $ |\n|''Source:''|http://thePettersons.org/tiddlywiki.html#NewerTiddlerPlugin |\n|''Author:''|[[Paul Petterson]] |\n|''Type:''|Macro Extension |\n|''Requires:''|TiddlyWiki 1.2.33 or higher |\n!Description\nCreate a 'new tiddler' button with lots more options! Specify the text to show on the button, the name of the new tiddler (with date macro expansion), one or more tags for the new tiddlers, and what text if any to include in the new tiddler body! Uses a named parameter format, simalar to the reminder plugin.\n\nAlso - if the tiddler already exists it won't replace any of it's existing data (like tags).\n\n!Syntax\n* {{{<<newerTiddler button:"Inbox" name:"Inbox YYYY/MM/DD" tags:"Journal, inbox" text:"New stuff for today:">>}}}\n* {{{<<newerTiddler button:"@Action" name:"Action: what" tags:"@Action" text:"Add project and describe action">>}}}\n* {{{<<newerTiddler button:"New Project" name:"Project Name?" tags:"My Projects, My Inbox, Journal" template:"MyTemplate">>}}}\n!!Parameters\n* name:"Name of Tiddler"\n* tags:"Tag1, Tag2, Tag3" - tags for new tiddler, comma seperated //don't use square brackets //({{{[[}}})// for tags!//\n* button:"name for button" - the name to display instead of "new tiddler"\n* body:"what to put in the tiddler body"\n* template:"Name of a tiddler containing the text to use as the body of the new tiddler"\n\n''Note:'' if you sepecify both body and template parameters, then template parameter will be used and the body parameter overridden.\n\n!Sample Output\n* <<newerTiddler button:"Inbox" name:"Inbox YYYY/MM/DD" tags:"Journal inbox" text:"New stuff for today:">>\n* <<newerTiddler button:"@Action" name:"Action: what" tags:"@Action" text:"Add project and describe action">>\n* <<newerTiddler button:"New Project" name:"Project Name?" tags:"[[My Projects]] [[My Inbox]] Journal" template:"MyTemplate">>\n\n!Todo\n<<projectTemplate>>\n\n!Known issues\n* Must use double quotes (") around parameter values if they contain a space, can't use single quotes (').\n* can't use standard bracketted style tags, ust type in the tags space and all and put a comma between them. For example tags:"one big tag, another big tag" uses 2 tags ''one big tag'' and ''another big tag''.\n\n!Notes\n* It works fine, and I use it daily, however I haven't really tested edge cases or multiple platforms. If you run into bugs or problems, let me know!\n\n!Requests\n* Have delta-date specifiers on the name: name:"Inbox YYY/MM/DD+1" ( ceruleat@gmail.com )\n* Option to just open the tiddler instead of immediately edit it ( ceruleat@gmail.com )\n* Have date formatters in tags as well as in name (me)\n\n!Revision history\n$History: PaulsNotepad.html $\n * \n * ***************** Version 2 *****************\n * User: paulpet Date: 2/26/06 Time: 7:25p\n * Updated in $/PaulsNotepad3.0.root/PaulsNotepad3.0/PaulsPlugins/systemConfig\n * Port to tw2.0, bug fixes, and simplification!\nv1.0.2 (not released) - fixed small documentation issues.\nv1.0.1 October 13th - fixed a bug occurring only in FF\nv1.0 October 11th - Initial public release\nv0.8 October 10th - Feature complete... \nv0.7 Initial public preview\n\n!Code\n***/\n//{{{\nconfig.macros.newerTiddler = { \nname:"New(er) Tiddler",\ntags:"",\ntext:"Type Tiddler Contents Here.",\nbutton:"new(er) tiddler",\n\nreparse: function( params ) {\n var re = /([^:\s'\s"\ss]+)(?::([^\s'\s":\ss]+)|:[\s'\s"]([^\s'\s"\s\s]*(?:\s\s.[^\s'\s"\s\s]*)*)[\s'\s"])?(?=\ss|$)/g;\n var ret = new Array() ;\n var m ;\n\n while( (m = re.exec( params )) != null )\n ret[ m[1] ] = m[2]?m[2]:m[3]?m[3]:true ;\n\n return ret ;\n},\nhandler: function(place,macroName,params,wikifier,paramString,tiddler) {\n if ( readOnly ) return ;\n\n var input = this.reparse( paramString ) ;\n var tiddlerName = input["name"]?input["name"].trim():config.macros.newerTiddler.name ;\n var tiddlerTags = input["tags"]?input["tags"]:config.macros.newerTiddler.tags ;\n var tiddlerBody = input["text"]?input["text"]:config.macros.newerTiddler.text ;\n var buttonText = input["button"]?input["button"]:config.macros.newerTiddler.button ;\n var template = input["template"]?input["template"]:null;\n\n // if there is a template, use it - otherwise use the tiddlerBody text\n if ( template ) {\n tiddlerBody = store.getTiddlerText( template );\n }\n if ( tiddlerBody == null || tiddlerBody.length == 0 )\n tiddlerBody = config.macros.newerTiddler.text ;\n\n var now = new Date() ;\n tiddlerName = now.formatString( tiddlerName ) ;\n \n createTiddlyButton( place, buttonText, "", function() {\n var exists = store.tiddlerExists( tiddlerName );\n var t = store.createTiddler( tiddlerName );\n if ( ! exists )\n t.assign( tiddlerName, tiddlerBody, config.views.wikified.defaultModifier, now, tiddlerTags.readBracketedList() );\n \n story.displayTiddler(null,tiddlerName,DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(tiddlerName,"title");\n return false;\n });\n}}\n//}}}\n/***\nThis plugin is released under the [[Creative Commons Attribution 2.5 License|http://creativecommons.org/licenses/by/2.5/]]\n***/
|Feed|d-cubed|\n|URL|http://dcubed.ca/gtd-update.html|
//Par ''Sherkan''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>Souvent critiqué, le Guide l'Orient version D20 a été mon premier supplément D&D 3ème Ed. C'est un ouvrage que j'aime beaucoup et que j'utilise avec le vieux et vénérable ~Kara-Tur d'AD&D plutôt qu'avec la version D20 proposée de Légende des 5 Anneaux (qui aura plus tard son propre supplément Rokugan D20)\nEt miracle ! Le dK System se prête plus à de l'action rapide façon wu xia pian ou du duel à la chambara que le D20 lui-même !\nEnjoy ! >>\n!Les peuples\n!!!Nezumi\n+1 constitution.\n-1 charisme.\nVision nocturne.\nOdorat (voir les Atouts Monstrueux).\n>Personnelement j'utilise ces hommes-rats hors du contexte de ~L5A. Il n'y a donc pas de souillure d'Outremonde dans mes campagnes. Mais si vous comptez quand même l'utiliser, considérer que les Nezumis sont naturellement immunisés contre la souillure de l'Outremonde. En contrepartie ils sont Socialement Mal Adapté à la vie Rokuganaise.\n!!!Vanara\n-1 en Force.\n+1 en Sagesse.\nBond (voir Atouts Monstrueux).\nTerrain privilégié : Jungle (le MJ ne peut leur infliger de dK sur leurs jets de Survie, ni quand il s’agit de se déplacer dans la jungle, de grimper aux arbres…).\n>Ces êtres d'apparence simiesque sont aussi espiègles que sages. Leur faible force est compensée par leur extraordinaire agilité.\n!!!Koroburuku\nPetit.\n-1 Intelligence.\n+1 Constitution.\n+4 Sauvegarde contre les effets magiques et les sorts.\n>Il s'agit de la version Nain du Guide de L'Orient avec quelques notables différences : ils sont plus bourrus et leur extrème superstition n'a fait que renforcer leur résistance en la magie, dont ils se méfient par dessous tout.\n!!!~Semi-Esprits\nD'apparence humaine, ils sont les héritiers d'unions entre humains et esprits, ce qui en fait des êtres aussi bien liés au monde des mortels qu'à celui de la nature.\n>Je les ai partiellement modifié afin de les rendre bien différents les uns des autres, ce qui n'était pas le cas dans le Guide de l'Orient\n!!!~Semi-Esprit des Bambous\n+1 Constitution.\nAllergique au Feu ( les dégâts cumulatifs commencent à 2d6).\nTerrain privilégié : Forêt/Jungle.\nNe laisse pas de trace, ni d’odeur en Forêt/Jungle.\n!!!~Semi-Esprit des Mers\n+1 Dextérité.\nAmphibie (voir Atouts Monstrueux).\nLangage Animal (Uniquement ceux qui peuplent les océans).\nMal adapté aux endroits désertiques (les malus ou dégâts liés à la soif, fatigue sont multipliés par 2).\n!!!~Semi-Esprit des Rivières\n-1 Constitution.\n~Sous-Type Aquatique : eau des rivières (voir Atouts Monstrueux).\nFascination.\n+2 sauvegarde effets magiques liés au Domaine de l’Eau.\n!!!Hengeyokai\n-1 en Sagesse. (cumulable avec tout le reste)\n>Le Hengeyokai est un métamorphe capable d’avoir trois formes : humaine, hybride et animale. Il s’agit souvent d’animaux inoffensifs comme la belette, le chat, le renard, le moineau, la carpe, la grue, le crabe, le lièvre…. Il peut se transformer un nombre de fois par jour égal à son niveau +1 (ou alors vous gérez çà à votre guise) et obtient l’Atout Forme Hybride ou Forme Animale suivant l’apparence qu’il veut prendre. Il n’est pas obligé de passer de la forme hybride pour passer à sa forme animale, c'est-à-dire qu’il peut passer directement de sa forme humaine à sa forme animale par exemple. Bien entendu les avantages de ces deux Atouts ne sont pas cumulables.\n''Atout Forme Hybride'' : +1 dans une caractéristique suivant l’animal adopté (généralement la Dextérité: renard, chat, carpe, ou la Constitution : belette, crabe...). Vision Nocturne. \nCommunication avec les animaux de leur race. +2 dans une compétence comme Evasion pour le chat, Acrobatie pour le renard, Natation pour la carpe, etc, etc... Impossibilité de porter des armures de brutasse sous cette forme.\n>A ce stade, je considère que la forme Hybride ne permet pas encore d’avoir un Odorat ou d’être Amphibie.\n''Atout Forme Animale'' : Minuscule (Atout monstrueux modifié) : +4 en Défense et en Discrétion, mais 1d6/2 de dégâts quand la créature peut en infliger : morsure d’un renard, griffes acérées du chat… Communication avec animaux de leur race. +4 dans la compétence liée à leur race (cf forme hybride) . Vitesse doublée ou triplée par rapport à un humain (course, natation, vol). Vision Nocturne. Odorat ou Vue perçante (pour les oiseaux) ou Amphibie (pour les poissons). Impossible de tenir des armes et de porter des armures. Impossible de parler avec les Humains (mais ils peuvent comprendre ce qu'ils disent...ce qui en fait de redoutables espions).\n!Les "classes" et la magie\nAfin de simuler les classes et la magie si spécifiques au Guide de l'Orient, voici quelques indications : \n*Les ''Chamans'' utiliseront une magie divine liée au culte des esprits de la nature ou des ancêtres.Le style le plus approprié est donc la Compétence Connaissance (Prière). Les Domaines liés à un élément ou à la divination sont ceux à acquérir de suite pour un Chaman.\n*Les ''Sohei'' sont les protecteurs des temples, des moines-guerriers avec quelques affinités magiques. Un tel personnage aura intérêt à se tourner vers des Atouts comme Arts Martiaux et/ou Rage Destructrice (appelé dans ce cas Déchainement de Ki).Quant à la magie, le style qui leur convient le mieux est bien évidemment la Compétence Acrobatie (pour les Katas).\n*Le ''Shugenja'' est le lanceur de sort type de ~L5A. Pour cela il utilise des ofuda (des parchemins) comme focalisateur. Ainsi son styte sera ~Calligraphie-Métier (Scribe). Les Shugenjas ont une affinité toute particulière avec les Elements. Parmi les premiers Domaines qu'ils choisissent, l'un d'eux doit obligatoirement faire partie ou de l'Eau, ou du Feu, ou de la Terre, ou de l'Air. Ainsi ils bénéficieront d'un bonus de -5 à la difficulté lors de la création d'un sort lié à leur Domaine de prédilection. En contrepartie, ils auront un malus de +5 à la difficulté de création de sort concernant un Domaine Elementaire opposé : l'Air s'oppose à la Terre, et le Feu à l'Eau. (Cette règle me semble plus souple que d'interdire le Domaine opposé comme dans le Guide de l'Orient).\n*Le ''Wu jen'' est le lanceur de sort typique de ce genre d'univers, et comme n'importe quel magicien, il utilise sa Compétence Connaissance (magie). A ceci près que lorsque le Wu Jen parvient enfin à lancer des sorts professionnels liés aux Domaines Végétal, de l'Eau, du Feu, de l'Air et de la Terre avec lesquels il a une affinité toute particulière, on dit qu'il en acquiert un Secret Mystique. Pour ces domaines, et seulement pour eux , à partir du niveau professionnel, il acquiert un bonus de -5 dans la difficulté d'élaboration d'un sort. En contrepartie, il acquiert un Tabou pour chacun de ces cinq domaines maîtrisés au niveau professionnel. Ces Tabous prennent plusieurs formes : ne plus se laver, ne plus se couper les cheveux, abandonner à tout jamais un type de nourriture, ne plus porter une couler spécifique, etc, etc...\n*Pour ce qui des styles d'arts martiaux, des Taos (coucou Qin !) ou des écoles pour les Samuraïs, reportez vous à la page 131 du dK System, tout y est expliqué.
<div class='header' macro='gradient vert #000 #464646'>\n<div class='headerShadow'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n</div>\n<div id='mainMenu' refresh='content' tiddler='MainMenu' force='true'></div>\n<div id='sidebar'>\n<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\n</div>\n<div id='displayArea'>\n<div id='messageArea'></div>\n<div id='tiddlerDisplay'></div>\n</div>
!Les races de Planescape\n//Par ''Sherkan''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>Voici un essai de conversion au dK System des principales races jouables dans Planescape. Pour ce faire je me suis basé sur le Planewalker's Handbook plutôt que les récents Manuel des Plans et Planar Handbook, ce qui ne les rend pas obsolètes pour autant, surtout par rapports aux créatures et monstres planaires qui y sont décrits.\nBien que Planescape soit un univers développé pour AD&D, il existe de nombreuses adaptations pour le D20 (souvent en anglais hélas) un peu partout sur le net, et les anciens suppléments sont pour la plupart disponibles en PDF dans les meilleures boutiques Online.\nEnjoy !>>\n\nA l'origine les races jouables pour Planescape étaient, en plus des races habituelles de D&D, l'Aasimar, le Bariaur, le Genasi (d'Air, d'Eau, de Feu et de Terre), le Githzerai et le Tiefling.\n!!!Aasimar \nD'ascendance céleste, les Aasimars ont le port noble et charismatique. D'un point de vue tout à fait cliché, ils sont la représentation spirituelle de ce que devrait être un paladin.\n+1 Charisme\n-1 Constitution\nAura de Lumière\nVision Thermique\n!!!Bariaur\nNe les traitez jamais de Centaure ! Ces quadrupèdes assez turbulents, aux cornes de bouc, sont un formidable rempart contre tout ce qui est "Chaotic Evil"\n+1 Force\n-1 Charisme\nQuadrupède (appliquer l'atout Né à Cheval directement au personnage)\nArme Naturelle (Sabots uniquement)\nCharge Furieuse\nTravers : le corps du Bariaur est inadapté aux armures de professionnels et de brutasses.\nQu'ils soient d'eau, de feu, d'air ou de terre, ces êtres apparentés aux quatre éléments aiment montrer leur différence de manière très orgueilleuse.\n!!!Genasi, Air\n+1 Dextérité\n-1 Sagesse\n+2 Sauvegarde contre les sorts du Domaine de l'Air\nAccès aux sorts d'amateur du Domaine de l'Air\n!!!Genasi, Eau\n+1Dextérité\n-1 Intelligence\n+2 Sauvegarde contre les sorts du Domaine de l'Eau\nAccès aux sorts d'amateur du Domaine de l'Eau\n!!!Genasi, Feu\n+1 Intelligence\n-1 Sagesse\n+2 Sauvegarde contre les sorts du Domaine du Feu\nAccès aux sorts d'amateur du Domaine du Feu\n!!!Genasi, Terre\n+1 Constitution\n-1 Dextérité\n+2 Sauvegarde contre les sorts du Domaine de la Terre\nAccès aux sorts d'amateur du Domaine de la Terre\n!!!Githzerai\nCes êtres sombres et