//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 &nbsp;all&nbsp;</a>\s\n <a href="JavaScript:;" id="exportSelectChanges"\s\n onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\s\n &nbsp;changes&nbsp;</a> \s\n <a href="JavaScript:;" id="exportSelectOpened"\s\n onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\s\n &nbsp;opened&nbsp;</a> \s\n <a href="JavaScript:;" id="exportToggleFilter"\s\n onclick="onClickExportButton(this)" title="show/hide selection filter">\s\n &nbsp;filter&nbsp;</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 &nbsp;&#150;&nbsp;</a>\s\n <a href="JavaScript:;" id="exportListLarger"\s\n onclick="onClickExportButton(this)" title="increase list size">\s\n &nbsp;+&nbsp;</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 &nbsp;all&nbsp;</a>\s\n <a href="JavaScript:;" id="importSelectNew"\s\n onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\s\n &nbsp;added&nbsp;</a> \s\n <a href="JavaScript:;" id="importSelectChanges"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\s\n &nbsp;changes&nbsp;</a> \s\n <a href="JavaScript:;" id="importSelectDifferences"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\s\n &nbsp;differences&nbsp;</a> \s\n <a href="JavaScript:;" id="importToggleFilter"\s\n onclick="onClickImportButton(this)" title="show/hide selection filter">\s\n &nbsp;filter&nbsp;</a> \s\n</td><td align=right>\s\n <a href="JavaScript:;" id="importListSmaller"\s\n onclick="onClickImportButton(this)" title="reduce list size">\s\n &nbsp;&#150;&nbsp;</a>\s\n <a href="JavaScript:;" id="importListLarger"\s\n onclick="onClickImportButton(this)" title="increase list size">\s\n &nbsp;+&nbsp;</a>\s\n <a href="JavaScript:;" id="importListMaximize"\s\n onclick="onClickImportButton(this)" title="maximize/restore list size">\s\n &nbsp;=&nbsp;</a>\s\n</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 &nbsp;\s\n<input type=checkbox class="chk" id="chkImportTags" checked\s\n onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags &nbsp;\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>&nbsp;\n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;\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 tristes sont néanmoins de redoutables adversaires. Leurs capacités psychiques leur permettent de s'opposer directement aux Flagelleurs Mentaux dont ils sont les pires ennemis.\n+1 Sagesse\n-1 en Charisme\nVision Nocturne\nAccès aux sorts d'amateur du Domaine de l'Esprit\n!!!Tiefling\nIls ont tous un aspect différent qui rappelle leur ascendance démoniaque. Loin des clichés qui veulent faire croire qu'ils sont tous des voleurs ou des assassins, ce sont avant tout des êtres passionnés...bien qu'ils prennent un malin plaisir à jouer sur leur aspect pour intimider l'adversaire. Ouais...quoiqu'on en dise il y aura toujours quelque chose de démoniaque en eux !\n+1 intelligence\n-1 Charisme\nVision Nocturne\nPorte Poisse (parce que je me suis dit que ça pouvait simuler l'étrangeté et la crainte qui émane de cette race)\n>''Note''\n>Tous les Planaires ont un malus sous forme de dK (un ou plus, selon votre bonne humeur du moment) de circonstance lorsqu'ils sont victimes d'un sort de professionnel et de brutasse lié au Domaine de la Conjuration.\n>En échange tous les Planaires bénéficient de bonus de +4 en Perception lorsqu'il s'agit de trouver un portail dimensionnel.
//Par ''Drulaan''//\nDans le dK, un jet de premiers soins réussi redonne Xd6 points de vie (où X est le degré dans la compétence du soigneur).\nDans un univers plus "rude" (post apo, cyberpunk,...) où les personnages risquent leur peau et où il faut bien leur faire sentir que leur vie ne tient qu'à un fil, on peut essayer cette option :\nUn jet de premiers soins contre une difficulté de 15 fait récupérer 1d6 + X points de vie (où X est le degré dans la compétence du soigneur)\n
! Active projects with remaining actions\n<<gtdActionList *>>\n! Projects with no open actions\n<<list tagged "project done -someday">>
*+++(gtdImportantProjectsSliderState)[Important:] <<list tagged "project important -someday" all>>===\n+++(gtdOtherProjectsSliderState)[Other:] <<list tagged "project -syntora -important -someday" all>>===
<<list tagged txtGTDReferenceContext any>>
/***\n|''Name:''|ReminderPlugin|\n|''Version:''|2.3.8.3 (Nov 28, 2006)|\n|''Source:''|http://www.geocities.com/allredfaq/reminderMacros.html|\n|''Author:''|Jeremy Sheeley(pop1280 [at] excite [dot] com)|\n|''Modified by:''|Tom Otvos|\n|''Licence:''|[[BSD open source license]]|\n|''Macros:''|reminder, showreminders, displayTiddlersWithReminders, newReminder|\n|''TiddlyWiki:''|2.0+|\n|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|\n\n!Description\nThis plugin provides macros for tagging a date with a reminder. Use the {{{reminder}}} macro to do this. The {{{showReminders}}} and {{{displayTiddlersWithReminder}}} macros automatically search through all available tiddlers looking for upcoming reminders.\n\n''This version contains a fix by Tom Otvos that modifies tag filtering when tiddlers contain no tags. In this version, if you are filtering showReminders by tag, and a tiddler has no tags, the filter will //not// match the tiddler. There are also a number of small UI-related changes to make the reminder interface a bit nicer. Do not copy this into your own TW documents unless you accept these changes.''\n\n!Installation\n* Create a new tiddler in your tiddlywiki titled ReminderPlugin and give it the {{{systemConfig}}} tag. The tag is important because it tells TW that this is executable code.\n* Double click this tiddler, and copy all the text from the tiddler's body.\n* Paste the text into the body of the new tiddler in your TW.\n* Save and reload your TW.\n* You can copy some examples into your TW as well. See [[Simple examples]], [[Holidays]], [[showReminders]] and [[Personal Reminders]]\n\n!Syntax:\n|>|See [[ReminderSyntax]] and [[showRemindersSyntax]]|\n\n!Revision history\n* v2.3.8 (Mar 9, 2006)\n**Bug fix: A global variable had snuck in, which was killing FF 1.5.0.1\n**Feature: You can now use TIDDLER and TIDDLERNAME in a regular reminder format\n* v2.3.6 (Mar 1, 2006)\n**Bug fix: Reminders for today weren't being matched sometimes.\n**Feature: Solidified integration with DatePlugin and CalendarPlugin\n**Feature: Recurring reminders will now return multiple hits in showReminders and the calendar.\n**Feature: Added TIDDLERNAME to the replacements for showReminders format, for plugins that need the title without brackets.\n* v2.3.5 (Feb 8, 2006)\n**Bug fix: Sped up reminders lots. Added a caching mechanism for reminders that have already been matched.\n* v2.3.4 (Feb 7, 2006)\n**Bug fix: Cleaned up code to hopefully prevent the Firefox 1.5.0.1 crash that was causing lots of plugins \nto crash Firefox. Thanks to http://www.jslint.com\n* v2.3.3 (Feb 2, 2006)\n**Feature: newReminder now has drop down lists instead of text boxes.\n**Bug fix: A trailing space in a title would trigger an infinite loop.\n**Bug fix: using tag:"birthday !reminder" would filter differently than tag:"!reminder birthday"\n* v2.3.2 (Jan 21, 2006)\n**Feature: newReminder macro, which will let you easily add a reminder to a tiddler. Thanks to Eric Shulman (http://www.elsdesign.com) for the code to do this.\n** Bug fix: offsetday was not working sometimes\n** Bug fix: when upgrading to 2.0, I included a bit to exclude tiddlers tagged with excludeSearch. I've reverted back to searching through all tiddlers\n* v2.3.1 (Jan 7, 2006)\n**Feature: 2.0 compatibility\n**Feature AlanH sent some code to make sure that showReminders prints a message if no reminders are found.\n* v2.3.0 (Jan 3, 2006)\n** Bug Fix: Using "Last Sunday (-0)" as a offsetdayofweek wasn't working.\n** Bug Fix: Daylight Savings time broke offset based reminders (for example year:2005 month:8 day:23 recurdays:7 would match Monday instead of Tuesday during DST.\n\n!Code\n***/\n//{{{\n\n//============================================================================\n//============================================================================\n// ReminderPlugin\n//============================================================================\n//============================================================================\n\nversion.extensions.ReminderPlugin = {major: 2, minor: 3, revision: 8, date: new Date(2006,3,9), source: "http://www.geocities.com/allredfaq/reminderMacros.html"};\n\n//============================================================================\n// Configuration\n// Modify this section to change the defaults for \n// leadtime and display strings\n//============================================================================\n\nconfig.macros.reminders = {};\nconfig.macros["reminder"] = {};\nconfig.macros["newReminder"] = {};\nconfig.macros["showReminders"] = {};\nconfig.macros["displayTiddlersWithReminders"] = {};\n\nconfig.macros.reminders["defaultLeadTime"] = [0,365];\nconfig.macros.reminders["defaultReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY";\nconfig.macros.reminders["defaultShowReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY -- TIDDLER";\nconfig.macros.reminders["defaultAnniversaryMessage"] = "(DIFF)";\nconfig.macros.reminders["untitledReminder"] = "Untitled Reminder";\nconfig.macros.reminders["noReminderFound"] = "Couldn't find a match for TITLE in the next LEADTIMEUPPER days."\nconfig.macros.reminders["todayString"] = "Today";\nconfig.macros.reminders["tomorrowString"] = "Tomorrow";\nconfig.macros.reminders["ndaysString"] = "DIFF days";\nconfig.macros.reminders["emtpyShowRemindersString"] = "There are no upcoming events";\n\n\n//============================================================================\n// Code\n// You should not need to edit anything \n// below this. Make sure to edit this tiddler and copy \n// the code from the text box, to make sure that \n// tiddler rendering doesn't interfere with the copy \n// and paste.\n//============================================================================\n\n// This line is to preserve 1.2 compatibility\n// if (!story) var story=window; \n//this object will hold the cache of reminders, so that we don't\n//recompute the same reminder over again.\nvar reminderCache = {};\n\nconfig.macros.showReminders.handler = function showReminders(place,macroName,params)\n{\n var now = new Date().getMidnight();\n var paramHash = {};\n var leadtime = [0,14];\n paramHash = getParamsForReminder(params);\n var bProvidedDate = (paramHash["year"] != null) || \n (paramHash["month"] != null) || \n (paramHash["day"] != null) || \n (paramHash["dayofweek"] != null);\n if (paramHash["leadtime"] != null)\n {\n leadtime = paramHash["leadtime"];\n if (bProvidedDate)\n {\n //If they've entered a day, we need to make \n //sure to find it. We'll reset the \n //leadtime a few lines down.\n paramHash["leadtime"] = [-10000, 10000];\n }\n }\n var matchedDate = now;\n if (bProvidedDate)\n {\n var leadTimeLowerBound = new Date().getMidnight().addDays(paramHash["leadtime"][0]);\n var leadTimeUpperBound = new Date().getMidnight().addDays(paramHash["leadtime"][1]);\n matchedDate = findDateForReminder(paramHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound); \n }\n\n var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);\n var elem = createTiddlyElement(place,"span",null,null, null);\n var mess = "";\n if (arr.length == 0)\n {\n mess += config.macros.reminders.emtpyShowRemindersString; \n }\n for (var j = 0; j < arr.length; j++)\n {\n if (paramHash["format"] != null)\n {\n arr[j]["params"]["format"] = paramHash["format"];\n }\n else\n {\n arr[j]["params"]["format"] = config.macros.reminders["defaultShowReminderMessage"];\n }\n mess += getReminderMessageForDisplay(arr[j]["diff"], arr[j]["params"], arr[j]["matchedDate"], arr[j]["tiddler"]);\n mess += "\sn";\n }\n wikify(mess, elem, null, null);\n};\n\n\nconfig.macros.displayTiddlersWithReminders.handler = function displayTiddlersWithReminders(place,macroName,params)\n{\n var now = new Date().getMidnight();\n var paramHash = {};\n var leadtime = [0,14];\n paramHash = getParamsForReminder(params);\n var bProvidedDate = (paramHash["year"] != null) || \n (paramHash["month"] != null) || \n (paramHash["day"] != null) || \n (paramHash["dayofweek"] != null);\n if (paramHash["leadtime"] != null)\n {\n leadtime = paramHash["leadtime"];\n if (bProvidedDate)\n {\n //If they've entered a day, we need to make \n //sure to find it. We'll reset the leadtime \n //a few lines down.\n paramHash["leadtime"] = [-10000,10000];\n }\n }\n var matchedDate = now;\n if (bProvidedDate)\n {\n var leadTimeLowerBound = new Date().getMidnight().addDays(paramHash["leadtime"][0]);\n var leadTimeUpperBound = new Date().getMidnight().addDays(paramHash["leadtime"][1]);\n matchedDate = findDateForReminder(paramHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound); \n }\n var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);\n for (var j = 0; j < arr.length; j++)\n {\n displayTiddler(null, arr[j]["tiddler"], 0, null, false, false, false);\n }\n};\n\nconfig.macros.reminder.handler = function reminder(place,macroName,params)\n{\n var dateHash = getParamsForReminder(params);\n if (dateHash["hidden"] != null)\n {\n return;\n }\n var leadTime = dateHash["leadtime"];\n if (leadTime == null)\n {\n leadTime = config.macros.reminders["defaultLeadTime"]; \n }\n var leadTimeLowerBound = new Date().getMidnight().addDays(leadTime[0]);\n var leadTimeUpperBound = new Date().getMidnight().addDays(leadTime[1]);\n var matchedDate = findDateForReminder(dateHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound);\n if (!window.story) \n {\n window.story=window; \n }\n if (!store.getTiddler) \n {\n store.getTiddler=function(title) {return this.tiddlers[title];};\n }\n var title = window.story.findContainingTiddler(place).id.substr(7);\n if (matchedDate != null)\n {\n var diff = matchedDate.getDifferenceInDays(new Date().getMidnight());\n var elem = createTiddlyElement(place,"span",null,null, null);\n var mess = getReminderMessageForDisplay(diff, dateHash, matchedDate, title);\n wikify(mess, elem, null, null);\n }\n else\n {\n createTiddlyElement(place,"span",null,null, config.macros.reminders["noReminderFound"].replace("TITLE", dateHash["title"]).replace("LEADTIMEUPPER", leadTime[1]).replace("LEADTIMELOWER", leadTime[0]).replace("TIDDLERNAME", title).replace("TIDDLER", "[[" + title + "]]") );\n }\n};\n\nconfig.macros.newReminder.handler = function newReminder(place,macroName,params)\n{\n // tomo - cleaned up the form layout a bit\n var today=new Date().getMidnight();\n var formstring = '<html><br/><form>';\n \n formstring += 'Year: <select name="year"><option value="">Every year</option>';\n for (var i = 0; i < 5; i++)\n {\n formstring += '<option' + ((i == 0) ? ' selected' : '') + ' value="' + (today.getFullYear() +i) + '">' + (today.getFullYear() + i) + '</option>';\n }\n formstring += '</select>&nbsp;&nbsp;Month: <select name="month"><option value="">Every month</option>';\n for (i = 0; i < 12; i++)\n {\n formstring += '<option' + ((i == today.getMonth()) ? ' selected' : '') + ' value="' + (i+1) + '">' + config.messages.dates.months[i] + '</option>';\n }\n formstring += '</select>&nbsp;&nbsp;Day: <select name="day"><option value="">Every day</option>';\n for (i = 1; i < 32; i++)\n {\n formstring += '<option' + ((i == (today.getDate() )) ? ' selected' : '') + ' value="' + i + '">' + i + '</option>';\n }\n formstring += '</select>&nbsp;&nbsp;&nbsp;&nbsp;Reminder Title: <input type="text" size="40" name="title" value="" onfocus="this.select();">&nbsp;&nbsp;<input type="button" value="Add reminder" onclick="addReminderToTiddler(this.form)">';\n formstring += '</form></html>';\n \n var panel = config.macros.slider.createSlider(place, null, "New Reminder", "Open a form to add a new reminder to this tiddler");\n wikify(formstring, panel, null, store.getTiddler(params[1]));\n};\n\n// onclick: process input and insert reminder at 'marker'\nwindow.addReminderToTiddler = function(form) {\n if (!window.story) \n {\n window.story=window; \n }\n if (!store.getTiddler) \n {\n store.getTiddler=function(title) {return this.tiddlers[title];};\n }\n var title = window.story.findContainingTiddler(form).id.substr(7);\n var tiddler=store.getTiddler(title);\n var txt='\sn<<reminder ';\n if (form.year.value != "")\n txt += 'year:'+form.year.value + ' ';\n if (form.month.value != "")\n txt += 'month:'+form.month.value + ' ';\n if (form.day.value != "")\n txt += 'day:'+form.day.value + ' ';\n txt += 'title:"'+form.title.value+'" ';\n txt +='>>';\n tiddler.set(null,tiddler.text + txt);\n window.story.refreshTiddler(title,1,true);\n store.setDirty(true);\n // tomo - make sure to save if required\n if(config.options.chkAutoSave)\n saveChanges();\n};\n\nfunction hasTag(tiddlerTags, tagFilters)\n{\n // tomo - this has been updated to work better with tag-less tiddlers\n \n //Make sure we respond well to empty tagFilterlists\n if (tagFilters.length==0) return true;\n \n var bHasTag = false;\n \n /*bNoPos says: "'till now there has been no check using a positive filter"\n Imagine a filterlist consisting of 1 negative filter:\n If the filter isn't matched, we want hasTag to be true.\n Yet bHasTag is still false ('cause only positive filters cause bHasTag to change)\n \n If no positive filters are present bNoPos is true, and no negative filters are matched so we have not returned false\n Thus: hasTag returns true.\n \n If at any time a positive filter is encountered, we want at least one of the tags to match it, so we turn bNoPos to false, which\n means bHasTag must be true for hasTag to return true*/\n var bNoPos=true;\n \n for (var t3 = 0; t3 < tagFilters.length; t3++)\n {\n var negTest = tagFilters[t3].length > 1 && tagFilters[t3].charAt(0) == '!';\n // do the positive filter test outside of the tag loop, in case there are no tags!\n if (bNoPos && !negTest) bNoPos = false;\n \n for(var t2=0; t2<tiddlerTags.length; t2++)\n {\n if (negTest) \n {\n if (tiddlerTags[t2] == tagFilters[t3].substring(1))\n {\n //If at any time a negative filter is matched, we return false\n return false;\n }\n }\n else \n {\n if (tiddlerTags[t2] == tagFilters[t3])\n {\n //A positive filter is matched. As long as no negative filter is matched, hasTag will return true\n bHasTag=true;\n }\n }\n }\n }\n return (bNoPos || bHasTag);\n};\n\n//This function searches all tiddlers for the reminder //macro. It is intended that other plugins (like //calendar) will use this function to query for \n//upcoming reminders.\n//The arguments to this function filter out reminders //based on when they will fire.\n//\n//ARGUMENTS:\n//baseDate is the date that is used as "now". \n//leadtime is a two element int array, with leadtime[0] \n// as the lower bound and leadtime[1] as the\n// upper bound. A reasonable default is [0,14]\n//tags is a space-separated list of tags to use to filter \n// tiddlers. If a tag name begins with an !, then \n// only tiddlers which do not have that tag will \n// be considered. For example "examples holidays" \n// will search for reminders in any tiddlers that \n// are tagged with examples or holidays and \n// "!examples !holidays" will search for reminders \n// in any tiddlers that are not tagged with \n// examples or holidays. Pass in null to search \n// all tiddlers.\n//limit. If limit is null, individual reminders can \n// override the leadtime specified earlier. \n// Pass in 1 in order to override that behavior.\n\nwindow.findTiddlersWithReminders = function findTiddlersWithReminders(baseDate, leadtime, tags, limit)\n{\n//function(searchRegExp,sortField,excludeTag)\n// var macroPattern = "<<([^>\s\s]+)(?:\s\s*)([^>]*)>>";\n var macroPattern = "<<(reminder)(.*)>>";\n var macroRegExp = new RegExp(macroPattern,"mg");\n var matches = store.search(macroRegExp,"title","");\n var arr = [];\n var tagsArray = null;\n if (tags != null)\n {\n tagsArray = tags.split(" ");\n }\n for(var t=matches.length-1; t>=0; t--)\n {\n if (tagsArray != null)\n {\n //If they specified tags to filter on, and this tiddler doesn't \n //match, skip it entirely.\n if ( ! hasTag(matches[t].tags, tagsArray))\n {\n continue;\n }\n }\n\n var targetText = matches[t].text;\n do {\n // Get the next formatting match\n var formatMatch = macroRegExp.exec(targetText);\n if(formatMatch && formatMatch[1] != null && formatMatch[1].toLowerCase() == "reminder")\n {\n //Find the matching date.\n \n var params = formatMatch[2] != null ? formatMatch[2].readMacroParams() : {};\n var dateHash = getParamsForReminder(params);\n if (limit != null || dateHash["leadtime"] == null)\n {\n if (leadtime == null)\n dateHash["leadtime"] = leadtime;\n else\n {\n dateHash["leadtime"] = [];\n dateHash["leadtime"][0] = leadtime[0];\n dateHash["leadtime"][1] = leadtime[1];\n }\n }\n if (dateHash["leadtime"] == null)\n dateHash["leadtime"] = config.macros.reminders["defaultLeadTime"]; \n var leadTimeLowerBound = baseDate.addDays(dateHash["leadtime"][0]);\n var leadTimeUpperBound = baseDate.addDays(dateHash["leadtime"][1]);\n var matchedDate = findDateForReminder(dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound);\n while (matchedDate != null)\n {\n var hash = {};\n hash["diff"] = matchedDate.getDifferenceInDays(baseDate);\n hash["matchedDate"] = new Date(matchedDate.getFullYear(), matchedDate.getMonth(), matchedDate.getDate(), 0, 0);\n hash["params"] = cloneParams(dateHash);\n hash["tiddler"] = matches[t].title;\n hash["tags"] = matches[t].tags;\n arr.pushUnique(hash);\n if (dateHash["recurdays"] != null || (dateHash["year"] == null))\n {\n leadTimeLowerBound = leadTimeLowerBound.addDays(matchedDate.getDifferenceInDays(leadTimeLowerBound)+ 1);\n matchedDate = findDateForReminder(dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound);\n }\n else matchedDate = null;\n }\n }\n }while(formatMatch);\n }\n if(arr.length > 1) //Sort the array by number of days remaining.\n {\n arr.sort(function (a,b) {if(a["diff"] == b["diff"]) {return(0);} else {return (a["diff"] < b["diff"]) ? -1 : +1; } });\n }\n return arr;\n};\n\n//This function takes the reminder macro parameters and\n//generates the string that is used for display.\n//This function is not intended to be called by \n//other plugins.\n window.getReminderMessageForDisplay= function getReminderMessageForDisplay(diff, params, matchedDate, tiddlerTitle)\n{\n var anniversaryString = "";\n var reminderTitle = params["title"];\n if (reminderTitle == null)\n {\n reminderTitle = config.macros.reminders["untitledReminder"];\n }\n if (params["firstyear"] != null)\n {\n anniversaryString = config.macros.reminders["defaultAnniversaryMessage"].replace("DIFF", (matchedDate.getFullYear() - params["firstyear"]));\n }\n var mess = "";\n var diffString = "";\n if (diff == 0)\n {\n diffString = config.macros.reminders["todayString"];\n }\n else if (diff == 1)\n {\n diffString = config.macros.reminders["tomorrowString"];\n }\n else\n {\n diffString = config.macros.reminders["ndaysString"].replace("DIFF", diff);\n }\n var format = config.macros.reminders["defaultReminderMessage"];\n if (params["format"] != null)\n {\n format = params["format"];\n }\n mess = format;\n//HACK! -- Avoid replacing DD in TIDDLER with the date\n mess = mess.replace(/TIDDLER/g, "TIDELER");\n mess = matchedDate.formatStringDateOnly(mess);\n mess = mess.replace(/TIDELER/g, "TIDDLER");\n if (tiddlerTitle != null)\n {\n mess = mess.replace(/TIDDLERNAME/g, tiddlerTitle);\n mess = mess.replace(/TIDDLER/g, "[[" + tiddlerTitle + "]]");\n }\n \n mess = mess.replace("DIFF", diffString).replace("TITLE", reminderTitle).replace("DATE", matchedDate.formatString("DDD MMM DD, YYYY")).replace("ANNIVERSARY", anniversaryString);\n return mess;\n};\n\n// Parse out the macro parameters into a hashtable. This\n// handles the arguments for reminder, showReminders and \n// displayTiddlersWithReminders.\nwindow.getParamsForReminder = function getParamsForReminder(params)\n{\n var dateHash = {};\n var type = "";\n var num = 0;\n var title = "";\n for(var t=0; t<params.length; t++)\n {\n var split = params[t].split(":");\n type = split[0].toLowerCase();\n var value = split[1];\n for (var i=2; i < split.length; i++)\n {\n value += ":" + split[i];\n }\n if (type == "nolinks" || type == "limit" || type == "hidden")\n {\n num = 1;\n }\n else if (type == "leadtime")\n {\n var leads = value.split("...");\n if (leads.length == 1)\n {\n leads[1]= leads[0];\n leads[0] = 0;\n }\n leads[0] = parseInt(leads[0], 10);\n leads[1] = parseInt(leads[1], 10);\n num = leads;\n }\n else if (type == "offsetdayofweek")\n {\n if (value.substr(0,1) == "-")\n {\n dateHash["negativeOffsetDayOfWeek"] = 1;\n value = value.substr(1);\n }\n num = parseInt(value, 10);\n }\n else if (type != "title" && type != "tag" && type != "format")\n {\n num = parseInt(value, 10);\n }\n else\n {\n title = value;\n t++;\n while (title.substr(0,1) == '"' && title.substr(title.length - 1,1) != '"' && params[t] != undefined)\n {\n title += " " + params[t++];\n }\n //Trim off the leading and trailing quotes\n if (title.substr(0,1) == "\s"" && title.substr(title.length - 1,1)== "\s"")\n {\n title = title.substr(1, title.length - 2);\n t--;\n }\n num = title;\n }\n dateHash[type] = num;\n }\n //date is synonymous with day\n if (dateHash["day"] == null)\n {\n dateHash["day"] = dateHash["date"];\n }\n return dateHash;\n};\n\n//This function finds the date specified in the reminder \n//parameters. It will return null if no match can be\n//found. This function is not intended to be used by\n//other plugins.\nwindow.findDateForReminder= function findDateForReminder( dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound)\n{\n if (baseDate == null)\n {\n baseDate = new Date().getMidnight();\n }\n var hashKey = baseDate.convertToYYYYMMDDHHMM();\n for (var k in dateHash)\n {\n hashKey += "," + k + "|" + dateHash[k];\n }\n hashKey += "," + leadTimeLowerBound.convertToYYYYMMDDHHMM();\n hashKey += "," + leadTimeUpperBound.convertToYYYYMMDDHHMM();\n if (reminderCache[hashKey] == null)\n {\n //If we don't find a match in this run, then we will\n //cache that the reminder can't be matched.\n reminderCache[hashKey] = false;\n }\n else if (reminderCache[hashKey] == false)\n {\n //We've already tried this date and failed\n return null;\n }\n else\n {\n return reminderCache[hashKey];\n }\n \n var bOffsetSpecified = dateHash["offsetyear"] != null || \n dateHash["offsetmonth"] != null || \n dateHash["offsetday"] != null || \n dateHash["offsetdayofweek"] != null || \n dateHash["recurdays"] != null;\n \n // If we are matching the base date for a dayofweek offset, look for the base date a \n //little further back.\n var tmp1leadTimeLowerBound = leadTimeLowerBound; \n if ( dateHash["offsetdayofweek"] != null)\n {\n tmp1leadTimeLowerBound = leadTimeLowerBound.addDays(-6); \n }\n var matchedDate = baseDate.findMatch(dateHash, tmp1leadTimeLowerBound, leadTimeUpperBound);\n if (matchedDate != null)\n {\n var newMatchedDate = matchedDate;\n if (dateHash["recurdays"] != null)\n {\n while (newMatchedDate.getTime() < leadTimeLowerBound.getTime())\n {\n newMatchedDate = newMatchedDate.addDays(dateHash["recurdays"]);\n }\n }\n else if (dateHash["offsetyear"] != null || \n dateHash["offsetmonth"] != null || \n dateHash["offsetday"] != null || \n dateHash["offsetdayofweek"] != null)\n {\n var tmpdateHash = cloneParams(dateHash);\n tmpdateHash["year"] = dateHash["offsetyear"];\n tmpdateHash["month"] = dateHash["offsetmonth"];\n tmpdateHash["day"] = dateHash["offsetday"];\n tmpdateHash["dayofweek"] = dateHash["offsetdayofweek"];\n var tmpleadTimeLowerBound = leadTimeLowerBound;\n var tmpleadTimeUpperBound = leadTimeUpperBound;\n if (tmpdateHash["offsetdayofweek"] != null)\n {\n if (tmpdateHash["negativeOffsetDayOfWeek"] == 1)\n {\n tmpleadTimeLowerBound = matchedDate.addDays(-6);\n tmpleadTimeUpperBound = matchedDate;\n\n }\n else\n {\n tmpleadTimeLowerBound = matchedDate;\n tmpleadTimeUpperBound = matchedDate.addDays(6);\n }\n\n }\n newMatchedDate = matchedDate.findMatch(tmpdateHash, tmpleadTimeLowerBound, tmpleadTimeUpperBound);\n //The offset couldn't be matched. return null.\n if (newMatchedDate == null)\n {\n return null;\n }\n }\n if (newMatchedDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))\n {\n reminderCache[hashKey] = newMatchedDate;\n return newMatchedDate;\n }\n }\n return null;\n};\n\n//This does much the same job as findDateForReminder, but\n//this one doesn't deal with offsets or recurring \n//reminders.\nDate.prototype.findMatch = function findMatch(dateHash, leadTimeLowerBound, leadTimeUpperBound)\n{\n\n var bSpecifiedYear = (dateHash["year"] != null);\n var bSpecifiedMonth = (dateHash["month"] != null);\n var bSpecifiedDay = (dateHash["day"] != null);\n var bSpecifiedDayOfWeek = (dateHash["dayofweek"] != null);\n if (bSpecifiedYear && bSpecifiedMonth && bSpecifiedDay)\n {\n return new Date(dateHash["year"], dateHash["month"]-1, dateHash["day"], 0, 0);\n }\n var bMatchedYear = !bSpecifiedYear;\n var bMatchedMonth = !bSpecifiedMonth;\n var bMatchedDay = !bSpecifiedDay;\n var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;\n if (bSpecifiedDay && bSpecifiedMonth && !bSpecifiedYear && !bSpecifiedDayOfWeek)\n {\n\n //Shortcut -- First try this year. If it's too small, try next year.\n var tmpMidnight = this.getMidnight();\n var tmpDate = new Date(this.getFullYear(), dateHash["month"]-1, dateHash["day"], 0,0);\n if (tmpDate.getTime() < leadTimeLowerBound.getTime())\n {\n tmpDate = new Date((this.getFullYear() + 1), dateHash["month"]-1, dateHash["day"], 0,0);\n }\n if ( tmpDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))\n {\n return tmpDate;\n }\n else\n {\n return null;\n }\n }\n\n var newDate = leadTimeLowerBound; \n while (newDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))\n {\n var tmp = testDate(newDate, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek);\n if (tmp != null)\n return tmp;\n newDate = newDate.addDays(1);\n }\n};\n\nfunction testDate(testMe, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek)\n{\n var bMatchedYear = !bSpecifiedYear;\n var bMatchedMonth = !bSpecifiedMonth;\n var bMatchedDay = !bSpecifiedDay;\n var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;\n if (bSpecifiedYear)\n {\n bMatchedYear = (dateHash["year"] == testMe.getFullYear());\n }\n if (bSpecifiedMonth)\n {\n bMatchedMonth = ((dateHash["month"] - 1) == testMe.getMonth() );\n }\n if (bSpecifiedDay)\n {\n bMatchedDay = (dateHash["day"] == testMe.getDate());\n }\n if (bSpecifiedDayOfWeek)\n {\n bMatchedDayOfWeek = (dateHash["dayofweek"] == testMe.getDay());\n }\n\n if (bMatchedYear && bMatchedMonth && bMatchedDay && bMatchedDayOfWeek)\n {\n return testMe;\n }\n};\n\n//Returns true if the date is in between two given dates\nDate.prototype.isBetween = function isBetween(lowerBound, upperBound)\n{\n return (this.getTime() >= lowerBound.getTime() && this.getTime() <= upperBound.getTime());\n}\n//Return a new date, with the time set to midnight (0000)\nDate.prototype.getMidnight = function getMidnight()\n{\n return new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0);\n};\n// Add the specified number of days to a date.\nDate.prototype.addDays = function addDays(numberOfDays)\n{\n return new Date(this.getFullYear(), this.getMonth(), this.getDate() + numberOfDays, 0, 0);\n};\n//Return the number of days between two dates.\nDate.prototype.getDifferenceInDays = function getDifferenceInDays(otherDate)\n{\n//I have to do it this way, because this way ignores daylight savings\n var tmpDate = this.addDays(0);\n if (this.getTime() > otherDate.getTime())\n {\n var i = 0;\n for (i = 0; tmpDate.getTime() > otherDate.getTime(); i++)\n {\n tmpDate = tmpDate.addDays(-1);\n }\n return i;\n }\n else\n {\n var i = 0;\n for (i = 0; tmpDate.getTime() < otherDate.getTime(); i++)\n {\n tmpDate = tmpDate.addDays(1);\n }\n return i * -1;\n }\n return 0;\n};\nfunction cloneParams(what) {\n var tmp = {};\n for (var i in what) {\n tmp[i] = what[i];\n }\n return tmp;\n}\n// Substitute date components into a string\nDate.prototype.formatStringDateOnly = function formatStringDateOnly(template)\n{\n template = template.replace("YYYY",this.getFullYear());\n template = template.replace("YY",String.zeroPad(this.getFullYear()-2000,2));\n template = template.replace("MMM",config.messages.dates.months[this.getMonth()]);\n template = template.replace("0MM",String.zeroPad(this.getMonth()+1,2));\n template = template.replace("MM",this.getMonth()+1);\n template = template.replace("DDD",config.messages.dates.days[this.getDay()]);\n template = template.replace("0DD",String.zeroPad(this.getDate(),2));\n template = template.replace("DD",this.getDate());\n return template;\n};\n\n//}}}
!Overdue actions\n<<showReminders leadtime:-365...-1 tag:"action !done" format:"DATE: @@color:red;TITLE@@ [ TIDDLER ]">>\n!Actions for today and tomorrow\n<<showReminders leadtime:0...1 tag:"action !done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>\n!All reminders for the next week\n<<showReminders leadtime:0...7 tag:"!done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>
Click on the button below to create a new reminder as a tickler:\n\n<<newReminder>>
Matrice dK
<<list tagged txtGTDSomedayContext any>>\n
//Par ''Oufle''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>> Voici mon adaptation de la version 2.0 de Spycraft. Vous y trouverez :\n*Un résumé de création et d'évolution de personnage.\n*Les atouts qui remplacent ceux du dK.\n*Les options de combats qui ne sont en fait que des atouts donnés gratuitement aux joueurs.\nOn notera que j'ai réintégré la notion de classe. J'ai toujours trouvé les classes de PJ de spycraft vraiment bien faite, je ne voulais donc pas m'en séparer. En plus, cela permet de bien cadrer les joueurs à la création du groupe.\nLa gestion des points de gadget ne me convient pas encore, elle est hérité de la v1 de Spycraft.>>\n!Création de personnage\n''Concept'' : Choisissez une classe de personnage parmi les six classes suivantes : Faceman, Intruder, Pointman, Soldier, Wheelman, Snoop.\n''Caractéristiques'' : Répartissez les bonus suivants entre les six caractéristiques (Dextérité, Force, Constitution, Intelligence, Charisme, Sagesse) : +0, +1, +2, +3, +4, +5. Vous pouvez appliquer un bonus de +2 à une caractéristique si vous appliquez un malus de -2 à une autre.\n''Points de Gadget'' : Vous disposez de un point de gadget à la création.\n''Education'' : Votre éducation est égal à 1 (votre niveau de départ) + vos bonus de caractéristiques.\n''Autre scores'' : Mettez un degré dans deux bonus aux choix entre Attaque, Défense et Sauvegarde. Ajoutez les bonus de caractéristiques correspondants. Vos points de vie sont égaux à 10 + Con. Vous avez 4 points de vitalité à la création.\n''Compétences'' : Mettez un degré dans (5 + Int) compétences. Ajoutez les bonus de caractéristiques correspondant.\n''Talents'' : De base, votre personnage dispose des Talents Maîtrise des Armes de poing, Maîtrise des armes de Mêlée et Armure Légère. De plus, choisissez cinq talents. Les Talents de classe sont réservé aux classes correspondantes. Enfin, seul le Soldier et le Wheelman peuvent prendre des Voies de combat.\n''Equipement'' : Vos disposez d’un équipement fourni par l’Agence. Cet équipement est alloué en fonction de vos compétences. En définitive vous ne disposez que de l’équipement pour lequel vous avez une compétence associée. Par exemple, un kit de crochetage pour un personnage qui a investi un degré en crochetage, un fusil pour un personnage qui dispose du Talent Fusil.\n!Augmentation de niveau\nA chaque passage de niveau, votre personnage gagne un certain nombre de bienfaits :\n*Il gagne 4 points de vitalité (sauf si Talent spécial). \n*Il gagne un point de gadget. \n*Il gagne un point de connaissance. \nDe plus, vous pouvez choisir deux options parmi les suivantes :\n*Ajouter un Degré à un nombre de compétence égal à 5 + Bonus d’Intelligence. Aucune compétence ne peut avoir plus de degrés que le niveau actuel du personnage (sauf talent approprié). \n*Gagner deux fois +1 degré à ses scores de combat différents. Tous les 5 degrés à partir du 6ième vous gagnez une attaque supplémentaire, la première au niveau +6/+1… \n*Prendre un nouveau Talent en respectant les limitations de classe. \n*Ajouter 1 à un bonus de Caractéristique. Attention, vous ne pouvez faire ça qu’une fois par tranche de 5 niveaux de votre personnage (c'est-à-dire un première fois à partir du niveau 1, une deuxième fois à partie du niveau 5, etc…). \n*Demander un changement de classe. Effectif au prochain niveau. \n>Attention, un personnage ne peut investir plus de points dans une compétence, ou talent de combat, que sa base. C'est à dire si vous avez 3 en For et 2 en Charisme, et que vous décidez de monter la compétence 'Intimider', vous ne pourrez investir que 5 points. \nL'objectif de cette règle est de faire en sorte que les personnages aient des limitations de progression.\n!Atouts\nLes atouts pouvant être pris plusieurs fois sont indiqués par une *\n!!!Faceman\n''Linguiste'' : L’agent gagne deux langages supplémentaires. De plus, il s’exprime sans accent dans toutes les langues qu’il possède. Il parle comme si la langue était sa langue maternelle. Il est donc impossible de distinguer son accent d’une personne élevée dans le pays.\n''Lecture à froid''* : Une fois par session, le Faceman peut poser 3 questions au MJ à propos d’un personnage qu’il vient de rencontrer. Exemple : « Qu’est ce que cet homme fait dans la vie ? », « Quelle est la couleur préférée de cette femme ? ». Le MJ peut refuser de répondre en donnant un dé d’Actions aux joueurs.\n''Caméléon''* : Une fois par session, le Faceman peut changer ses manières et ses vêtements en un tour de telle manière à paraître quelqu’un d’autre. Cela revient à utiliser la compétence Déguisement sans Kit et sans prendre le temps habituellement nécessaire. Cependant, le Faceman ne peut utiliser cette compétence alors qu’il est observé sauf s’il parvient à être hors de vue un instant (ex : derrière un abris d’autobus pendant un instant). Une personne qui tente de percer à jour le déguisement dispose d’un bonus de +5.\nVous devez avoir au moins un degré en déguisement pour prendre cet atout.\n''Vieil ami''* : Une fois par session, le Faceman peut faire appel à une relation avec lequel il est en bon terme. Cette personne l’aidera tant que cela ne met pas ses proches en danger.\n''Vielle Dette''* : En faisant appel à l’atout Vieil Ami, vous pouvez, une fois par session, décider que cet ami vous doit une grande faveur. Il devient un allié et sera prêt à prendre des risques pour aider votre personnage.\n''Simule''* : Une fois par session, le Faceman peut prétendre disposer d’une compétence qu’il ne possède pas. Cela ne lui permet pas d’utiliser la compétence, juste de faire comme s’il l’avait. Ainsi, il pourrait se trouver à côté d’un chirurgien et prétendre comprendre ce qu’il se passe, mais il ne pourrait pas opérer de lui-même. Si le joueur doit faire un jet de bluff, il dispose d’un bonus de + 20.\n''1000 visages''* : Une fois par session, le Faceman peut imiter parfaitement l’apparence, les manières et la façon de parler de n’importe qui. Il faut pour cela étudier la cible pendant un jour complet. Le joueur gagne un bonus égal à son niveau pour tous les jets de bluff ou de comédie. Vous devez avoir au moins un degré en déguisement et en comédie pour prendre cet atout.\n''Vrai mensonge''* : Une fois par session, le Faceman peut dire un mensonge à un PNJ. Si le PNJ n’est pas absolument certain que le Faceman lui ment (en lui disant que le ciel est vert par exemple), il croira automatiquement ce mensonge.\n!!!Intruder\n''Improvisation''* : Une fois par session, l’Intruder peut improviser un objet simple en utilisant ce qui se trouve prêt de lui. Même complètement nu dans une cellule, il parviendrait à créer un kit de serrurerie à partir de quelques cheveux et de sang séché.\n''Maître voleur''* : Une fois par session, l’Intruder réussi automatiquement un jet de compétence lié à la Dextérité.\n''Maîtrise'' : L’Intruder choisi un nombre de compétence égale à (3+INT) pour lesquelles il lui sera possible de prendre 10 même dans une situation stressante.\n''Le lapin dans le chapeau'' : En un tour, l’Intruder peut cacher sur lui un objet pesant 1 kilogramme ou moins. Toutes les fouilles échoueront automatiquement sauf si le MJ donnent 3 dés d’Actions aux joueurs avant de jeter les dés.\n''Un As dans la Manche'' : Une fois par session, l’Intruder peut utiliser un gadget simple (une seule fonction). On considère que le gadget était caché sur lui tant que l’Intruder n’en a pas révélé qu’il l’utilisait. Une fouille échouera donc automatiquement tant que sa fonction n’a pas été précisée. D’autre part, il ne fonctionne qu’une fois avant de devenir inutile jusqu’à la session suivante.\nQuelques exemples de gadgets :\nZip Gun : 1D6 de dégâts.\nExplosifs : 6D6 de dégâts\nRéserve d’oxygène : Permet de respirer sous l’eau pendant une heure.\nMini parachute : Est utilisé comme un parachute.\nPiège : Dégâts d’une grenade. Est actionné à distance.\nAutres : Demander l’accord au MJ\n!!!Pointman\n''Assistance''* : Le Pointman peut réduire le temps qu’il faudrait à l’un de ses coéquipiers pour utiliser une de ses compétences. Il faut que l’action prenne au moins une heure. Si cet atout est pris une fois, il divise ce temps par deux. Si cet atout est pris deux fois, il divise le temps nécessaire par quatre, puis par huit…\n''Coordination'' : Le Pointman peut jeter les dés pour une action de groupe. Exemple : Grimper, s’infiltrer, mettre en place des explosifs… Même si c’est le Pointman qui jette le dé, on utilise la plus haute compétence du groupe. Si le jet est réussi, tout le groupe réussi. Si le jet échoue, tout le groupe échoue.\n''Tactiques''* : Une fois par session, le Pointman peut donner un ordre à son équipe. Cet ordre doit être spécifique, du type « couvrez Molly pendant qu’elle ouvre la porte ! » («Aidez Molly» ne fonctionnerait pas). Les personnages qui suivent l’ordre gagnent un bonus de +4 sur leurs jets.\n''Atout multiclasse''* : Cet atout permet au Pointman de choisir un atout d’une autre classe de personnage. Il y a une restriction cependant. Le Pointman ne peut prendre qu’un atout par classe qui n’est pas la sienne. \n''Aide imprévue''* : Une fois par session, il se passe un événement qui aidera les personnages au moment où ils en auront le plus besoin. Un objet ou une personne peut apparaître, ou tout simplement un concours de circonstance peut survenir. Le MJ peut activer cet atout lui-même lorsqu’il l’entend. Un joueur peut aussi l’activer. Il faudra cependant que le MJ donne 2 DK au joueur s’il veut annuler l’effet. Si le joueur accepte les dés d’actions, on considère qu’il a utilisé son atout. Sinon, il pourra tenter de l’utiliser une autre fois.\n!!!Snoop\n''Recherche minutieuse'' : Le Snoop ne rate jamais complètement un jet de perception, sauf s’il fait un échec critique. Le Snoop trouve toujours au moins un indice, ou une vague information. Cependant, s’il fait un échec critique, le MJ pourra quand même dépenser deux DK pour activer le critique.\n''Intuition''* : Une fois par session, le Snoop peut demander au MJ une piste sur la manière d’utiliser un indice, ou un morceau d’information que l’équipe a découverte.\n''Passer la rue au peigne fin''* : Une fois par session, le Snoop peut localiser avec exactitude dans une ville une personne qu’il recherche en utilisant une description physique ou une photo d’identité. Le Snoop doit cependant mener ses recherches dans la même ville que la cible. La recherche prend au moins un jour complet.\n''Communication interceptée''* : Une fois par session, le Snoop peut intercepter un appel téléphonique, une lettre ou une autre communication d’une personne ou d’un lieu en particulier. Pour cela il n’a pas besoin de faire un jet de surveillance.\n''Maîtrise'' : Le Snoop choisi un nombre de compétence égale à (3+INT) pour lesquelles il lui sera possible de prendre 10 même dans une situation stressante.\n''Master Cracker''* : Une fois par session, le Snoop peut découvrir un code secret ou un mot de passe. Le code ou le mot doit être court.\n''Recherche mondiale''* : Une fois par session, le Snoop peut découvrir dans quelle ville se trouve une personne. Il doit pour cela disposer d’une description physique ou d’une photo. La recherche prend au moins deux jours par niveau de la cible.\n!!!Soldier\n''Une chance sur un million'' : Une fois par session, le Soldier peut choisir d’utiliser une réussite critique automatique pour une action physique. Jet d’attaque, de sauvegarde, ou de compétence liée à une caractéristique physique (Dex, Con, For).\n''Sens du Combat''* : Vous gagnez 2 points supplémentaires de Vitalité par niveau. \nDégâts explosifs* : Dans vos mains, un type d'arme (exemple mêlée exotique, arme à feu de professionnelle) est extrêmement mortel. Quand vous lancez les dés, relancez tous les 6 et additionnez le résultat des chiffres obtenus. Continuez tant que vous obtenez des 6. Si vous prenez à nouveau dégâts explosifs, vous relancez également les 5. Avec un troisième atout, vous relancez les 4. Prérequis : niveau 9, niveau 12 pour le deuxième, niveau 15 pour le troisième.\n!!!Wheelman\n''Custom ride'' : La catégorie d’équipement du Wheelman gagne automatiquement deux niveaux si l’équipement concerne un véhicule. \n''Gadget ride''* : A chaque session, le Wheelman gagne deux points de gadget supplémentaires à dépenser dans un véhicule. \n''Daredevil'' : Pendant une poursuite, le Wheelman peut utiliser les manœuvres réservées au Daredevil. C’est à dire qu’il peut décider de mise sur plus de 3 dés en un tour.\n''Kick Start''* : Une fois par session le Wheelman peut transformer un échec sur un jet de mécanique en succès.\n''Familiarité'' : Le Wheelman reçoit un bonus de +4 sur ses jets de mécanique, naviguer, piloter, conduire… s’il utilise un véhicule qu’il a pu manœuvrer pendant au moins 2 jours. Le Wheelman ne peut être familier qu’avec un véhicule de chaque type à la fois (voiture, moto, avion…)\n''C’est impossible !'' : Une fois par session, le Wheelman peut effectuer une manœuvre qui devrait défier les lois de la physique.\n''Baby It'' : Vous pouvez conduire des véhicules qui ont encaissés plus de 4 dés de dégâts.\n!!!Atouts de compétences\n''Maîtrise'' (Compétence) : Choisissez trois compétences pour lesquelles vous gagnez un bonus de +2. De plus, votre seuil de réussite critique passe à 19-20 pour ces trois compétences. Vous devez au moins avoir un degré dans ces compétences pour pouvoir prendre cet atout.\n''Maîtrise Avancée'' (Compétence) : Votre seuil de réussite critique pour les trois compétences que vous maîtrisez passe à 18-20. Votre bonus passe à +3.\nVotre agent doit au moins avoir atteint niveau 6 et posséder l’atout Maîtrise pour pouvoir prendre cet atout. \n''Grande Maîtrise Avancée'' (Compétence) : Votre seuil de réussite critique pour les trois compétences que vous maîtrisez passe à 17-20. Votre bonus passe à +4.\nVotre agent doit au moins avoir atteint niveau 12 et posséder l’atout Maîtrise pour pouvoir prendre cet atout.\n''Maîtrise Parfaite'' (Compétence) : Votre seuil de réussite critique pour les trois compétences que vous maîtrisez passe à 16-20. Votre bonus passe à +5.\nVotre agent doit au moins avoir atteint niveau 18 et posséder l’atout Maîtrise pour pouvoir prendre cet atout. \n!!!Atouts de Style\n''Double identité'' : Vous avez une seconde identité parfaite comprenant une histoire, des témoins, de la documentation créés de toute pièce par l’Agence. De plus, vous avez compartimentalisé votre esprit à tel point que vous croyez vraiment être cette autre personne.\nVous pouvez prendre une identité supplémentaire tous les cinq niveaux. Pour chacune d’entre elle, il est impossible de découvrir la vérité à votre sujet. Même en enquêtant auprès de «vos amis et de votre famille».\nIl vous faut une fraction de seconde pour passer d’une identité à une autre. Quand vous faites cela, votre véritable identité est submergée mais secrètement contrôle vos actions. Vous pouvez revenir à votre véritable identité instantanément. \n''La Marque''* : Une fois par session, vous pouvez évaluer les compétences d’un PNJ. Pour cela, il vous suffit de citer trois compétences. Le MJ doit alors vous donner l’ordre d’importance de ces compétences. De la plus forte à la moins forte. Par compétence, on entendra Degré + Modificateurs de caractéristique.\n''Faveur Politique''* : Vos disposez d’informations compromettantes sur un politicien. Une fois par scénario, vous pouvez passer un coup de téléphone qui vous innocentera de toute accusation (sauf accusation de meurtre) ou qui vous permettra d’accéder à un bâtiment sécurisé du gouvernement (ce bâtiment ne doit pas être tenu secret).\n''Identité Secrète'' : Même si l’Agence vous laisse tomber, vous disposez d’une seconde identité prête à être utilisée. Cette identité comprend les papiers nécessaires : un certificat de naissance, un passeport, un permis de conduire d’un pays au choix et 1000 Dollars en liquide. Si cette deuxième identité venait à être découverte, vous conserverez les contacts qui ont permis de la mettre en place. Pour vous créer une nouvelle identité, il vous faudra simplement reprendre cet atout à un autre passage de niveau.\n''Planque'' : Que cela soit une vielle maison familiale, ou un appartement que vous louez, vous aurez toujours un toit au dessus de votre tête.\nUne fois par session, si vous vous trouvez dans une grande ville, vous pouvez utiliser votre Planque privée. Il y a suffisamment de couchage pour toute l’équipe. Le frigo est rempli, il y a la télévision, le téléphone… \n''Extra R&D Support'' : Le nombre de points de gadget dont le personnage dispose à chaque niveau est doublé. Ainsi, si le personnage est de niveau 3 il disposera de 6 points de gadget. \n''Mémoire photographique'' : Vous vous souvenez de tout ce que vous avez vu. \nVous devez avoir un bonus de +4 en Intelligence pour prendre de cet atout.\nAdrenalin addict : Lorsque vous avez des points de stress, le bonus de +2 compte aussi pour vos propres DK.\n''Sang-froid'' : Vous avez un bonus de +4 à vos jets de sauvegarde contre le stress.\n!!!Atouts de Combat \n''Attaque en Finesse'' : Vous remplacez votre bonus de Force par votre bonus de Dextérité pour déterminer votre capacité d’attaque. Vous devez disposer d’une Dextérité au moins égale à +1 pour pouvoir prendre cet atout.\n''Combat à deux armes'' : En utilisant une deuxième arme, vous gagnez une attaque supplémentaires, mais toutes vos attaques se font avec un malus de -2. \n''Combat Aveugle'' : Si vous ratez un opposant à cause de son malus de protection dû à un manque de visibilité (nuit, brouillard…), vous pouvez rejeter une fois le dé.\nInitiative améliorée : Vous gagnez 4 points supplémentaires sur votre score d’initiative.\n''Dégaine Rapide'' : Vous pouvez dégainer votre arme instantanément sans pénalité.\n''Maîtrise des Armes de Poing et Protections Légères'' : Vous pouvez utiliser des armes de poing simple. Ces armes font un maximum de dégât de 2D6 (Pistolets, Revolvers, Arbalètes légères…). \n''Maîtrise des Armes de Mêlée Simples et Protections Légères'' : Vous pouvez utiliser des armes de mêlée. Ces armes font un maximum de dégât de 1D6. (Couteaux, bâtons, tasers…) \n''Maîtrise des Armes de Mêlée Archaïques et Protections Renforcées'' : Vous pouvez utiliser des armes de mêlée Archaïques. Ces armes font un maximum de dégât de 2D6. (Haches, épées…). Vous devez disposer de Maîtrise des Armes de Mêlée Simples pour prendre cet atout.\n''Maîtrise des Armes de Mêlée Exotique et Protection Lourdes'' : Vous pouvez utiliser des armes de mêlée Exotiques. Ces armes font un maximum de dégât de 3D6. (Katanas, tronçonneuses…). Vous devez disposer de Maîtrise des Armes de Mêlée Archaïques pour prendre cet atout.\n''Maîtrise des Fusils et Protections Renforcées'' : Vous pouvez utiliser des fusils. Ces armes font un maximum de dégât de 3D6 (Pistolets Mitrailleurs, Fusils…). Vous devez disposer de Maîtrise des Armes de Poing pour prendre cet atout.\n''Maîtrise des Armes et Protection Lourdes'': Vous pouvez utiliser des armes Lourdes. Ces armes font un maximum de dégât de 10D6 (Mitrailleuses, Lances Roquettes…). Vous devez disposer de Maîtrise des Fusils pour prendre cet atout.\n''Arme improvisée'' : Tous les objets ordinaires deviennent des armes dangereuses entre vos mains. Choisissez un objet, son code de dégâts passe à 2D6.\n''Lutte'' : Vous savez comment tirer parti de votre force physique dans un combat à mains nues. Contrairement à ceux qui ne possèdent pas cet atout, vous ajoutez votre Force aux dégâts que vous infligez sans arme.\n''Arts Martiaux'' : Vous avez appris à utiliser vos poings. Vous gagnez un bonus de +1d6 aux dégâts à mains nues et pouvez causer des blessures réelles. Condition : Dextérité +2. \n''Connaître son ennemi'' : Vous savez observer vos ennemis et déceler leurs failles. Après trois tours de combat, vous gagnez automatiquement un bonus de +2 en attaque contre un adversaire donné. Dans certains cas, le Conteur peut autoriser qu’il s’agisse d’un groupe d’adversaire s’ils sont très semblables (contre certains hommes de main par exemple).\n''Coup surprise'' : Quand vous vous battez avec une arme, vous pouvez effectuer une attaque supplémentaire à -5 en donnant un coup de poing, de pied, de tête, de coude ou de genou. Les règles du combat à mains nues s’appliquent alors. Cette capacité s’ajoute aux attaques données par les attaques multiples (un personnage possédant deux attaques supplémentaires peut donc attaquer quatre fois au total : une normale à 0, une armée à -5, une à main nue à -5 et une armée à -10).\n''Rechargement rapide'' - Vous gagnez une action sur toutes les actions de rechargement de vos armes.\n!!!Voies de Combat\n''Garde du Corps''* : Vous décidez de mettre votre défense à la place d’une autre personne, à condition que vous n’attaquiez pas le même tour. Désignez une personne. Vous pouvez désigner une deuxième personne en prenant cet atout une seconde fois.\n''Sniper'' : Si vous passez un tour à viser, les dés de bonus que vous dépensez au tour suivant sont pris en compte s’ils affichent ‘5’ et ‘6’.\n''Gunfighter'' : Avant de porter votre attaque à distance, vous pouvez effectuer un jet d’acrobatie. Si celui-ci est réussi vous pouvez dépensez des dés de bonus pour améliorer votre score. Les dés sont pris en compte s’ils font ‘5’ ou ‘6’.\n''Défourailleur'' : Vous êtes particulièrement efficace contre un groupe compact d’assaillant. Quand vous tirez en rafale, vous pouvez désigner une cible supplémentaire par cinq degrés en bonus de combat.\n''Wuxia'' : Avant de porter votre attaque au corps à corps, vous pouvez effectuer un jet d’acrobatie. Si celui-ci est réussi vous pouvez dépensez des dés de bonus pour améliorer votre score. Les dés sont pris en compte s’ils font ‘5’ ou ‘6’. Si vous ratez votre jet d’acrobatie, vous ne pouvez pas dépenser de dés de bonus. Pré requis : Atout Artiste martial\n!!!Atouts d’Espionnage\n''«Ce n’était qu’un chat…»''* : Une fois par session, vous pouvez retenter un jet de Discrétion que vous aviez raté. Vous devez disposer d’au moins un degré en discrétion pour prendre cet atout.\n''«C’était moins une»''* : Une fois par session, si vous vous trouver dans une situation ou des ennemis pourraient vous prendre sur le fait (en train de consulter des dossiers top secret, ou de vous balader dans le repaire de votre ennemi par exemple), vous pouvez vous cacher instantanément de telle manière à ce qu’ils passent sans vous voir.\nVous devez disposer de l’atout « Ce n’était qu’un chat ».\n''«J’ai entendu le sergent dire que…»''* : Une fois par session, vous pouvez assister à une conversation entre deux hommes de mains qui révélera des informations sur la base ou le plan de votre adversaire. Vous pouvez alors poser une question spécifique au MJ.\n''«Cette ligne est sécurisée»''* : Une fois par session, vous pouvez envoyer un message, ou contacter un autre personnage, sans vous soucier d’être espionné. Votre ligne a été sécurisée.\n''Attaque sournoise'' : Si vous réussissez votre jet de discrétion, vous n’avez pas besoin de faire de jet d’attaque pour mettre un ennemi hors d’état de nuire. Cette attaque ne fonctionne cependant qu’avec les Hommes de Main. Vous devez avoir au moins un degré en Discrétion pour prendre cet atout.\n!!!Atouts de Chance\n''Quitte ou double''* : Vous pouvez augmentez la marge de réussite critique et d’échec critique de 5. Ainsi si votre degré de réussite critique est de 19-20, il passera à 14-20. Mais dans le même temps, votre seuil d’échec critique passera à 1-6. \nPré requis : Vous devez disposer de l’atout Sang Froid.\n''Esquive impossible'' : En dépensant des DK, vous pouvez vous donner des chances supplémentaires pour esquiver des attaques. Le nombre de DK dépensé plus le nombre d’atouts de Chance dont vous disposez vous donne le nombre de round pendant lequel cet atout fonctionne. Chaque fois qu’un adversaire réussi son attaque, il doit relancer un d20. S’il fait 1-2, son attaque rate quand même.\n''Règle des 6''* : Lorsque vous faites un 6 sur un DK, vous le relancez. Si vous prenez cet atout une nouvelle fois, ce seront les 5 qui exploseront, etc. Cela vous permettra dans la plupart des cas de relancer votre DK mais sans comptabiliser le score de 5.\nPré requis : Vous devez disposer de l’atout Quitte ou Double.\n''Jynx'' : Vous activez les échecs critiques de vos adversaires sans avoir besoin de dépenser de DK.\n!Options de combat\n(Atouts gratuits pour tous les PJ)\n''Combat Défensif'' : Vous savez vous protéger tout en gardant un maximum d’efficacité à l’attaque. Appliquez un malus de -2 à vos jets d’attaque et vous gagner un bonus de +4 à votre défense.\n''Combat Offensif'' : Vous savez prendre des risques et vous mettre à découvert pour gagner un maximum d’efficacité à l’attaque. Appliquez un malus de -2 à votre défense et vous gagner un bonus de +4 à votre attaque.\n''Attaque Puissante'' : Vous pouvez choisir de prendre un malus de -2 en attaque et de gagner un bonus de +1d6 aux dégâts. Il est possible de prendre cet atout plusieurs fois (mais pas plus d'une fois par niveau) et ainsi de cumuler les bonus et les malus…\nCet Atout ne fonctionne que pour les combats au corps à corps et mêlée.\n''Attaque sournoise'' : Vous pouvez ajouter 1d6 à vos dégâts, en mêlée ou à distance, si vous pouvez surprendre votre adversaire (mais jamais lors de rafales d'armes automatiques). \n''Rafale d'amateur'' : Votre jet d'attaque est réduit de -2 et vos dégâts sont augmentés d'1d6. Vous pouvez également » arroser » une petite zone : vous faites des dégâts normaux mais votre rafale peut toucher 3 (faites un seul jet d'attaque comparé à leurs défenses respectives et appliquez les dégâts à toutes les personnes touchées). Cependant, vous devez lancer deux dK. Si l’un des DK fait un 6, votre chargeur est vide à la fin du tour. \n''Rafale de professionnel'' : Votre jet d'attaque est réduit de -4 et vous ajoutez 2d6 à vos dégâts. Vous pouvez également » arroser » une zone moyenne : vous faites des dégâts normaux mais votre rafale peut toucher 4 personnes (faites un seul jet d'attaque comparé à leurs défenses respectives et appliquez les dégâts à toutes les personnes touchées). Cependant, vous devez lancer trois dK. Si l’un des DK fait un 6, votre chargeur est vide à la fin du tour.\n''Rafale Exotique'' : Dépensez 30 munitions ou lancez cinq dK pour déterminer si votre chargeur est vide à la fin du tour. Votre jet d'attaque est réduit de -6 et vous ajoutez 3d6 aux dégâts. Vous pouvez également » arroser » une grande zone : vous faites des dégâts normaux mais votre rafale peut toucher 6 personnes (faites un seul jet d'attaque comparé à leurs défenses respectives et appliquez les dégâts à toutes les personnes touchées). Cependant, vous devez lancer quatre dK. Si l’un des DK fait un 6, votre chargeur est vide à la fin du tour.\n''Chargeur'' : Enlever un chargeur et en prendre un autre est une action. Enclencher un nouveau chargeur et armer l’arme constitue une autre action. Il est donc possible de recharger une arme à chargeur en 2 tours. Si le personnage possède le don Recharge Rapide, il peut décharger et recharger en une seule action de mouvement.
!!Atouts\n*Les nouveau atouts "Engins de professionnels" et "Engins de Brutasse" servent à spécialiser les compétences de pilotage et de réparation. Ils correspondent respectivement aux chasseurs et transporteurs légers d'une part et aux vaisseaux de grande taille pour les autres. Tous les autres engins sont considérés comme amateurs. \n*Certains atouts pouvant être pris plusieurs fois mais avec des pré-requis de niveau (comme Dégâts explosifs par exemple) sont limités à trois et énoncés "Atout amateur", "Atout professionnel" et "Atout brutasse". \n*Les atouts de spécialisation sont renommés Spécialisation Professionnelle (+2) et Spécialisation Brutasse (+4). \n*Bagarreur, Arts-Martiaux et Maître en arts-martiaux deviennent respectivement Bagarreur Amateur, Professionnel et Brutasse. \n*Visée et Viseur d'élite sont remplacés par Visée Amateur, Professionnelle et Brutasse. \n*Les atouts sociaux "Relations" et "Alliés", donnés au cours des des aventures, ne peuvent jamais être pris comme atout libre du niveau.
!!Compétences \n*Certaines compétences sortent des métiers : Réparation, Informatique, Intrusion, Médecine.\n*Perception et Fouille sont fusionnées. \n*La force est gérée par une seule compétence et ses pouvoirs sont déterminés par des Atouts adaptés du jeu officiel, laissant de coté système de magie du dK. \n*Pour chaque compétence et avant d'avoir 5 degrés, seule la caractéristique la plus forte est prise en compte au lieu des 2. \nVoici donc la liste des compétences utilisées : \n|''Compétence''|''Carac 1''|''Carac 2''|\n|Acrobaties*|Dex|For|\n|Astrogation|Int|Sag|\n|Bluff|Cha|Int|\n|Concentration|Sag|Con|\n|Connaissance : Aliens|Int|Sag|\n|Connaissance : Bureaucratie|Int|Sag|\n|Connaissance : Business|Int|Sag|\n|Connaissance : Espace|Int|Sag|\n|Connaissance : Histoire|Int|Sag|\n|Connaissance : Jedi|Int|Sag|\n|Connaissance : La rue|Int|Sag|\n|Connaissance : Noblesse|Int|Sag|\n|Connaissance : Mondes|Int|Sag|\n|Connaissance : Politique|Int|Sag|\n|Connaissance : Sciences de la vie|Int|Sag|\n|Connaissance : Sciences physiques|Int|Sag|\n|Connaissance : Technologie|Int|Sag|\n|Déguisement|Cha|Dex|\n|Démolition|Int|Dex|\n|Diplomatie|Cha|Int|\n|Discrétion*|Dex|Int|\n|Dressage|Cha|Sag|\n|Équitation|Dex|Sag|\n|Escalade*|For|Dex|\n|Escamotage*|Dex|Int|\n|Évasion*|Dex|For|\n|Informatique|Int|Dex|\n|Intimidation|For|Cha|\n|Intrusion|Int|Dex|\n|Médecine|Int|Dex|\n|Métier : Artisant|Int|Dex|\n|Métier : Avocat|Int|Sag|\n|Métier : Cuisinier|Sag|Dex|\n|Métier : Docker|For|Sag|\n|Métier : Faussaire|Sag|Dex|\n|Métier : Fermier|For|Int|\n|Métier : Joueur|Sag|Dex|\n|Métier : Négociant|Cha|Sag|\n|Métier : Officier|Cha|Int|\n|Métier : Pharmacien|Int|Dex|\n|Métier : Saltimbanque|Dex|Cha|\n|Métier : Tenancier|Cha|Sag|\n|Natation*|For|Con|\n|Perception|Sag|Int|\n|Pilotage|Dex|Sag|\n|Psychologie|Sag|Int|\n|Renseignements|Cha|Sag|\n|Réparation|Int|Dex|\n|Survie|Sag|Con|\n|Utilisation de la Force |Cha|Sag|\n° Le malus d'encombrement s'applique à la compétence.
!La Force\n!!!Table d'effets\nLa table suivante donne, en fonction du jet de compétence "Utilisation de la Force", l'efficacité voire le coût en PE de certains pouvoirs.\n| ''Jet'' | ''Bonus/Malus'' | ''Dégâts/Guérison°'' | ''Poids'' | ''Coût°°'' |\n| 2 à 9 | - | 1PV | Une clé | 1 |\n| 10 à 14 | +1 | 1d6 PV | Une arme | 2 |\n| 15 à 19 | +2 | 2d6 PV ou 1 BG ou 1 PC | Une personne | 4 |\n| 20 à 29 | +4 | 3d6 PV ou 1 BG +1d6 PV ou 1d3 PC | Une moto-jet ou 3 personnes | 8 |\n| 30 à 40 | +8 | 4d6 PV ou 1 BG +2d6 PV ou 1d6 PC | Un speeder ou 10 personnes | 16 |\n| 41 et + | +16 | 5d6 PV ou 1 BG +3d6 PV ou 2d6 PC | Une navette ou 30 personnes | 32 |\n° PV : Points de vie, BG : Blessure grave, PC : Point de caractéristique \n°°Il est toujours possible de réduire la puissance d'un effet après le jet pour diminuer le coût en PE correspondant.\n*Le caractère lumineux ou obscur d'un pouvoir repose davantage sur son usage que sur une dichotomie rigide. Ainsi, un usage non léthal de Poussée pour empècher un attentat n'a aucune raison de procurer un point du coté obscur. \n*Un utilisateur de la force peut remplacer son score de sauvegarde par "Utilisation de la Force" pour contrer un pouvoir de la force. \n>Note : dans la description des pouvoirs, l'abbréviation UF renvoie à la compétence "Utilisation de la Force", "deg" à degrés et "vs" à un jet en opposition. \n|>|>|''Pouvoirs de base''|\n|>|>|''Contrôle''|\n| |''//Transe//''|La transe diminue l'activité du métabolisme durant de longues périodes et besoins en en air, en eau et en nourriture. Dans cet état ressemblant à la mort, la vitesse de guérison est considérée comme "assistée par un médecin". Un personnage en transe est inconscient et doit prédéfinir les conditions de réveil. Jet : UF difficulté 15 Durée : une semaine en plein désert ou un mois sous la pluie. |\n|~|''//Force Intérieure//''|Une fois les PE réduits à 0, il est possible de puiser dans les PV pour alimenter les pouvoirs de la Force. Jet : Automatique|\n|>|>|''Sens''|\n| |''//Sentir la Force//''|Vous avez parfois de vagues impressions liées à la Force, aux lieux et aux personnes. Vous pouvez sentir la vie biologique. Jet : Toujours actif Coût : 0 PE|\n|~|''//Voir la Force//''|Rechercher activement une personne dans la Force ou la Force chez une personne. Jet : UF vs UF si la proie a le pouvoir Dissimulation ou vs UF/2 à défaut Portée : (10 + deg UF) mètres. Coût : 3 PE|\n|~|''//Amplification sensorielle//''|Améliore les sens pour les jets de Perception ou de Survie. Jet : UF difficulté 10 Colonne : Bonus + 2 Durée : 10mn Coût : 3 PE|\n|>|>|''Altération''|\n| |''//Extension//''|Les pouvoirs Contrôle, Guérison, Bouclier, Protection peuvent être étendus à autrui. Jet : Automatique Coût : 0 PE |\n|~|''//Aura//''|Idem précédent + pouvoir Amélioration Jet : UF difficulté +10 Coût : +2 PE / Allié|\n\n\n|>|>|''Pouvoirs avancés''|\n|''Amélioration''||Un des rares pouvoirs ne requiérant un des pouvoirs de base, il permet d'améliorer la For, la Dex ou la Sauvegarde. Le pouvoir n'a jamais d'effet sur les compteurs. Jet : UF difficulté 10 Colonne : Bonus Durée : 10 tours Coût : 1 PE / point obtenu|\n|''Bouclier''||Réduit voire annule un pouvoir de la force utilisé contre contre soi : il permet d'effectuer un jet en opposition contre Utilisation de la Force de l'adversaire. Seule la difference est utilisable pour déterminer l'efficacité du pouvoir. Jet : UF difficulté 10 puis vs UF de l'adversaire Durée : 10 tours Coût : 3 PE|\n|''Défense sabre laser''||Si le projectile est parable au sabre laser et l'utilisateur est conscient d'être pris pour cible, sa défense est augmentée de Niv/4. Il est aussi possible de renvoyer le projectile si ce dernier a raté sa cible de peu. Jet : Défense : automatique dès que le sabre laser est activé ; Renvoi : Attaque -4 vs résultat du tir. Coût : nul|\n|''Dissimulation''||Masquer sa présence dans la Force permet d'éviter d'être repéré par l'usage du pouvoir Voir la Force. Jet : UF vs UF Durée : 10mn Coût : 3 PE|\n|''Drain''|Energie|Pour vider les réserves d'énergie en fonctionnement ou non et créer des court-circuits. Inflige des dégâts aux droids. Jet : UF difficulté 10 puis vs sauvegarde si la cible est un droid. Colonne : dégâts (droids) Coût : 3 PE ou variable (droids) |\n|~|Points d'energie|Permet de voler les PE de l'adversaire. Jet : UF difficulté 25 puis vs Sauv : 1 PE / point d'écart Coût : 3 PE puis gain d'1 PE par tranche de 3 vidés. |\n|''Eclairs''||Utiliser la Force pour générer des éclairs (1 à 4d6 de dégats). Un jet de sauvegarde réussit divise par 2 les dégats. Jet : UF vs Sauvegarde Colonne : dégats PV|\n|''Guérison''||Utiliser la Force pour soigner les créatures vivantes. Il n'est toutefois pas possible de soigner un membre coupé. Les soins personnels décalent d'une ligne vers le haut. Jet : UF (ou vs Sauvegarde contre personne non consentante) Colonne de Blessure en soins Coût : correspondant|\n|''Illusion''||Permet de faire se créer de véritable mirages sonores et/ou visuels UF vs Sauvegarde pour percer l'illusion Coût : - 10 m/3 PE/ tour - 10 km/5 PE/ tour - 100 km/8 PE/ tour - 1000 km/10 PE/ tour|\n|''Manipulation''||Utiliser la force pour altérer les perceptions d'une personne ou effectuer des suggestions télépathiques UF 10 puis vs Sauvegarde Portée : 5m +1/ degré d'UF Coût : - Altération des sens : 2 PE - Suggestion : 4 PE |\n|''Méditation de bataille''||Pouvoir rare à l'époque de la rébéllion qui aide les combattants d'un camp à se coordonner lors d'une bataille rangée. Jet : Bonus au test de combat de masse Colonne : Bonus/Malus Coût : 6 PE par jet |\n|''Oracle''||Gagner de vagues impressions sur des événements arrivant en d'autres lieux et/ou d'autres époques Jet : UF difficulté 15 pour le présent, 20 pour le passé et 25 pour le futur Coût : respectivement 3, 6 ou 9 PE|\n|''Présence''|Paix|Permet de calmer une cible hostile. Un échec déchaine la colère de la cible. Jet : UF vs Sauvegarde. Coût : 2 PE |\n|~|Peur|Retourne les peurs de la cible contre elle-même. En cas de succès, elle subit des malus à l'attaque et aux compétences. Elle peut les ignorer au prix d'1 points du coté obscur. UF vs Sauvegarde. Colonne : Bonus / Malus Durée : deg UF en tours Coût : 2 PE|\n|~|Guide|Transférer des degrés de compétences à un allié. Ces degrés et les PE utilisés ne sont plus disponibles pendant la durée du transfert. Jet : UF difficulté 40 Durée : A volonté Coût : 15 PE|\n|''Protection''||Armure physique s'ajoutant aux protections actuelles. Jet : UF difficulté 10 Colonne : Bonus / Malus Durée : 10 secondes Coût : 2 points / point bonus|\n|''Télépathie''|Empathie|Lire les émotions de surface d'une cible et déterminer son état d'esprit. Le jet donne des bonus à toutes les actions sociales contre la cible. Jet : UF difficulté 10 puis vs Sauvegarde. Même si elle résiste, la cible n'a pas conscience de l'examen. Durée : 10 minutes Coût : 2 PE|\n|~|Communication|Echanger des images et des mots avec autrui. Jet : UF vs 10 (ou 15 si non consentante) : +0 : 10m ou 10 km +10 : 100 m ou 100 km +20 : 1000 m ou 1000 km Coût : 3 PE|\n|''Télékinésie''|Levage|Bouger des objets ou des êtres vivants en utilisant la Force. Le jet indique la masse pouvant être déplacée. Jet : UF difficulté 10 Colonne : Poids |\n|~|~Pousser-Tirer|En poussée : 0, 1 ou 2D6 de dégâts et projection au sol. Permet aussi de saisir un objet tenu en main. Jet : UF vs Sauvegarde pour annuler les effets et diviser les dégâts par 2. Colonne Poids Coût : 2 PE |\n|~|Blessure|En s'attaquant directement aux organes d'une personne, il est possible de la blesser. Jet : UF difficulté 10 puis vs Sauv. Pour diviser les dégâts par 2. Colonne : Dégâts en PV Coût : variable|\n|~|Maelstrom|Création d'un tourbillon télékinétique de 4m de rayon. Les adversaires ont un malus de –4 à tous leurs jets d'attaque et de compétence et prennent 2D6 points de dommages / tour. Jet : UF difficulté 20 puis vs Déf pour diviser les malus et les dégâts par 2. Durée : 3 tours Coût : 6 PE|\n|''Transfert d'énergie''|Absorption|Absorber les dommages énergétiques et récupérer 1 PV / point de dégâts absorbés sans dépasser son maximum. Jet : Sauvegarde vs 10 + dégâts Coût : 5 PE |\n|~|~Rétention-Dissipation|Conserver ou dissiper la chaleur donne un bonus contre les températures extrêmes. Jet : UF difficulté 10. Le bonus est ajouté à la sauvegarde. Colonne : Bonus/Malus Durée : 1 heure|\n|''Vitesse''|Accélération|Multiplie la vitesse de déplacement par 10, 20 ou 30 et les distances de saut par 5, 10 ou 15. Jet : UF difficulté 10, 20 ou 30 Durée : 1 tour Coût : 5,8 ou 12 PE|\n|~|Vol|Enveloppé par la Force, déplacement en ignorant la gravité. Jet : UF difficulté 10 Colonne : Bonus x 4 en mètres Coût 4 PE|\n
!!Peuples\nLes différents peuples de Star Wars sont repris quasiment tel quels : les ajustements de caractéristiques et les compétences bonus sont les suivants : \n|''Peuple''|''Planète''|''Langue Maternelle''|''Caractéristiques, Compétences et Atouts''|\n|''Aqualish''|Ando|Aqualish|+1 Con, -1 Sag, 2 degrés en Natation |\n|''Arcona''|Cona|Arcona||\n|''Barabel''|Barab I|Barabel|+1 For, -1 Dex, +1 Con, -2 Sag Armes naturelles|\n|''Bimm''|Bimmisaari|Bimm|-2 For, +1 Dex, +1 Cha, Petit|\n|''Bith''|Clak'dor VII|Bith|-1 For, -1 Con, +2 Int, +1 Sag, 4 degrés en Perception |\n|''Bothan''|Bothawui|Bothan|+1 Dex, -1 Con, -1 Sag, 2 degrés en Psychologie et Renseignement |\n|''Cerean''|Cerea|Cerean|-1 Dex, +1 Int, +1 Sag, Initiative +2|\n|''Chadra-fan''|Chad|Chadra-fan|-1 For, +1 Dex, -1 Sag, +1 Cha|\n|''Chagrian''|Champala|Chagrian|Petit|\n|''Chiss''|Csilla|Chiss|2 degrés en Métier : Officier Petit|\n|''Devaronian Male''|Devaron|Devaronian|+1 Dex, -1 Int, -1 Sag|\n|''Devaronian Female''|Devaron|Devaronian|-1 Dex, +1 Int, +1 Sag |\n|''Dug''|Malastare|Dug|+1 Dex, -1 Sag, -1 Cha, Petit et Cri de guerre|\n|''Duros''|Duro|Duros|-1 For, +1 Dex, -1 Int, +1 Sag, Terrain privilégié (Espace)|\n|''Ewok''|Endor|Ewok|-1 For, +1 Dex, 4 degrés en Discrétion et 2 en Perception, Petit et Terrain privilégié (Forêt)|\n|''Falleen''|Falleen|Falleen|1 degré en Bluff, Diplomatie, Dressage, Intimitation et Renseignements Fascination (Phéromones) |\n|''Gamorrean''|Gamorr|Gamorrean|+1 For, -1 Dex, -1 Int, 2 degrés en Intimidation, Sauvegarde (Vigueur) +2 et Spécialisation Hache|\n|''Gonosian Worker''|Geonosis|Gonosian|+1 For, -1 Int, -1 Sag, 2 degrés en Intimidation, Armure naturelle +2 et Renforcement vital|\n|''Geonosian Aristocrat''|Geonosis|Geonosian|+1 Dex, -1 Con, Armure naturelle +2|\n|''Gotal''|Antar IV|Gotal|3 degrés en Bluff, Diplomatie, Intimidation et en Psychologie |\n|''Gran''|Malastare|Gran|-1 Sag, +1 Cha |\n|''Gungan''|Naboo|Gungan|+1 Con, -1 Sag, 2 degrés en Natation et 2 en Perception, Sauvegarde (Reflexes) +1 et Vision nocturne|\n|''Human''|Varies|Basic|+1 atout et +1 point de compétence par niveau|\n|''Hutt''|Nal Hutta|Hutt|+1 For, -2 Dex, +1 Con, +1 Int, +1 Cha, Grand et Bon sens|\n|''Ithorian''|Ithor|Ithorian|-1 Dex, +1 Sag, -1 Cha, 2 degrés en Connaissance : Science de la vie et 4 en Survie, Sauvegarde (Volonte) +1|\n|''Jawa''|Tatooine|Jawa|-2 For, +1 Dex, -1 Cha, Petit, Terrain privilégié (Désert) et Vision thermique (20m)|\n|''Kaminoan''|Kamino|Kaminoan|+1 Con, -1 Sag, -1 Cha, 2 degrés en Survie |\n|''Kel Dor''|Dorin|Kel Dor|+1 For, -1 Con, +1 Sag, Vision nocturne, Masque respiratoire (aveuglement et asphyxie sans)|\n|''Kubaz''|Ku'bakai|Kubaz|-1 For, +1 Dex, Sensible à la lumière (-4 en lumière normale)|\n|''Mon Calamari''|Mon Calamari|Mon Calamari|-1 Con, +1 Int, 4 degrés en Natation et en Réparation, Sauvegarde (Volonté) +1 (milieu humide)|\n|''Neimoidian''|Neimoidia|Neimoidian|-1 For, +1 Int, +1 Sag, 2 degrés en Bluff et en Métier : Négociant|\n|''Noghri''|Honoghr|Noghri|+1 Dex, +1 Sag, -2 Cha, 4 degrés en Discrétion Petit et Odorat|\n|''Quarren''|Mon Calamari|Quarren|+1 Con, -1 Sag, -1 Cha, 4 degrés en Natation|\n|''Rodian''|Rodia|Rodian|+1 Dex, -1 Sag, -1 Cha, 4 degrés en Perception |\n|''Snivvian''|Cadomai Prime|Snivvian|Petit|\n|''Sullustan''|Sullust|Sullustan|+1 Dex, -1 Con, 2 degrés en Escalade et en Perception, Vision thermique (20m)|\n|''Toydarian''|Toydaria|Toydarian|-2 For, +2 Dex, -1 Con, Petit et Initiative +4|\n|''Tusken Raider''|Tatooine|Tusken Raider|+1 Con, -1 Int, -1 Sag, Terrain privilégié (Désert)|\n|''Twi'lek''|Ryloth|Twi'lek|-1 Sag, +1 Cha, Vision nocturne et Sauvegarde (Vigueur) +1|\n|''Trandoshan''|Trandosha|Trandoshan|+1 Cha, -1 Dex, Armure naturelle +1 et Vision thermique (20m)|\n|''Ugnaught''|Gentes|Ugnaught|-1 Dex, +1 Con, -1 Sag, Petit et Renforcement vital|\n|''Verpine''|Varies|Verpine|2 degrés en Connaissance : Technologie, en Informatique et en Réparation, Télépathie (Verpine seulement)|\n|''Wookiee''|Kashyyyk|Wookiee|+2 For, -1 Dex, -1 Sag, -1 Cha, 2 degrés en Escalade et en Intimidation, Rage destructice et Reprends ton soufle|\n|''Yuuzhan Vong''|Unknown|Yuuzhan Vong|+1 For, +1 Con, -1 Sag, Immunité à la Force|\n|''Zabrak''|Iridonia|Zabrak|Sauvegarde (Vigueur) +2 et Sauvegarde (Volonté) +2|
!Equipement\n!!!Armes\nLes armes de Star Wars sont reprises et catégorisées avec quelques modifications :\n|''Armes''|''Catégorie''||''Special''|\n|Arbalète Laser|Distance Brutasse|4d6+2|Doublette|\n|Arc|Distance Amateur|2d6||\n|Bâton de combat|Mélée Profesionnel|1d6+For|Doublette|\n|Canon Blaster|Distance Brutasse|4d6|Degâts Explosifs Amateurs|\n|Carabine Blaster|Distance Professionnel|3d6+2||\n|Cesta|Mélée Amateur|1d6|Boule nrj 2d6|\n|Couteau de combat|Mélée Amateur|1d6+For||\n|Détonateur Thermique|Distance Professionnel|8d6+6||\n|Electro filet|Distance Professionnel|-|Immobilisation, Assomant|\n|Epée longue|Mélée Profesionnel|1d6+2+For||\n|Filet|Distance Professionnel|-|Immobilisation|\n|Fronde|Distance Amateur|1d6||\n|Fusil à munitions|Distance Professionnel|3d6|Perceur|\n|Fusil Blaster|Distance Professionnel|3d6+2||\n|Fusil Blaster Sport|Distance Professionnel|3d6||\n|Fusil d'assaut à munitions|Distance Professionnel|2d6+2|Perceur, Rafale|\n|Fusil Ionique|Distance Professionnel|3d6+2|Contre droïdes|\n|Gaderfii|Mélée Amateur|1d6+For|Doublette|\n|Gants de combat|Mélée Amateur|1d6+2||\n|Gourdin|Mélée Amateur|1d6+For||\n|Grenade Cryoban|Distance Professionnel|-|Immobilisation|\n|Grenade Frag|Distance Professionnel|4d6||\n|Grenade Gaz|Distance Professionnel|-|Poison|\n|Grenade Sonique|Distance Professionnel|-|Assomante|\n|Lance|Mélée Amateur|1d6+For||\n|Lutte|Mélée Amateur|||\n|Mains nues|Mélée Amateur|1d6||\n|Massue|Mélée Amateur|1d6+For||\n|Matraque taser|Mélée Amateur|-|Assomante|\n|Mitrailleuse Blaster|Distance Brutasse|4d6|Degâts Explosifs Professionnels|\n|Pique de force|Mélée Profesionnel|2d6+2+For||\n|Pistolet à munitions|Distance Amateur|2d6|Perceur|\n|Pistolet Blaster|Distance Amateur|3d6||\n|Pistolet Blaster Lourd|Distance Professionnel|2d6+2||\n|Pistolet Blaster Mini|Distance Amateur|2d6+2||\n|Pistolet Blaster Sport|Distance Amateur|2d6+2||\n|Pistolet Ionique|Distance Amateur|3d6|Contre droïdes|\n|PM Blaster|Distance Professionnel|3d6|Rafale|\n|PM Blaster lourd|Distance Brutasse|4d6|Rafale|\n|Sabre laser|Mélée Profesionnel|2d6+2+For||\n|Sabre laser double|Mélée Profesionnel|2d6+2+For|Doublette|\n|Vibro-dague|Mélée Profesionnel|1d6+2+For||\n|Vibro-hache|Mélée Profesionnel|2d6+For|Tranchoir|\n|Vibro-lame|Mélée Profesionnel|2d6+For||\n!!!Protections\n*Venant directement des jeux videos officiels ("Jedi Knight" ou "Knights of the old republic"), des boucliers font leur apparition : leur score est volatile. Ainsi, un bouclier à 4 points arretera 4 points de dégâts et cessera de fonctionner. Toutefois il pourra facilement être rechargé hors combat, pour faire simple. \n*Bien que séparés en Amateur, Professionnel et Brutasse pour differencier leur score (2, 4 ou 6), ils peuvent tous être portés "en amateur". La différence est dans le prix, voire le poids… \n*Seuls les grands méchants ou les seconds rôles ont des boucliers, les têtes à claques, jamais. \n|''Armure''|''Catégorie''|''Protection''|\n|Armure de combat|Professionnel|4|\n|Armure de combat corelienne|Professionnel|4|\n|Armure de combat lourde|Brutasse|7|\n|Armure de combat renforcée|Professionnel|5|\n|Armure de stormtrooper|Professionnel|5|\n|Combinaison de vol renforcée|Amateur|2|\n|Combinaison de vol blindée|Professionnel|4|\n|Combinaison renforcée|Amateur|3|\n|Exosquelette|Professionnel|3|\n|Scaphandre blindé|Brutasse|6|\n|Veste composite et casque|Amateur|2|\n|Bouclier léger|Amateur|2|\n|Bouclier moyen|Amateur|4|\n|Bouclier lourd|Amateur|6|\n!!!Engins\nPour ne pas trop s'écarter des statistiques officielles ni tout ré-écrire, les vaisseaux personnalisés ont un profil de base, des atouts mais 1 seul point de caractéristique par niveau seulement. \n|''Groupe''|''UZ atmo°''|''UZ spatiale°°''|''PV''|\n|Humanoïde|1|-|x1|\n|Les véhicules (moto-jet, landspeeder, etc.)|1 à 10|-|x2|\n|Les chasseurs et transports léger (Aile-X, Airspeeder, Chasseur TIE, Faucon Milleniumn, etc.)|27 à 40|5 à 12|x4|\n|Les vaisseaux (de ligne, de guerre ou cargo)|-|0 à 4|x4°°°|\n° L'UZ atmospherique est déterminée par la vitesse / 10 pour les véhicules et le nombre de cases +15 pour les chasseurs et vaisseaux\n°° L'UZ spatiale, découplée de la précédente, est égale au nombre de cases.\n°°° Chasseurs et vaisseaux sont à la même échelle mais les derniers disposent d'un blindage beaucoup plus épais\nL'échelle de points de vie n'a d'utilité que des dégâts d'une échelle différente sont infligés à un engin ou un personnage\n|''Tireur / Cible''|''Humanoïde''|''Véhicule''|''Chasseur / Vaisseau''|\n|''Humanoïde''|x1|/2|/4|\n|''Véhicule''|x2|x1|/2|\n|''Chasseur/ Vaisseau''|x4|x2|x1|\n
!!Evolution de personnage\nSelon l'option "classique" de dévoppement du dKrunch, les atouts //Compétences//, //Compteurs//, //Avantages// et un atout libre sont pris à chaque niveau.\nLe tableau suivant résume l'évolution normale d'un personnage et permet de créer PJs et PNJs à directement à un niveau donné :\n| ''Niveau'' | ''Caractéristiques'' | ''Avantages'' | ''Compteurs'' | ''Compétence'' | ''Atouts libres'' |\n|~| Points de base | Nb degrés || Nb degrés | Nombre |\n| 1 | 15 | 2 | (10+Con) PV/(10+Sag) PE | 6+Int | 8 |\n| 2 | 15 | 4 | +1 | (6+Int)x2 | 9 |\n| 3 | 15 | 6 | +2 | (6+Int)x3 | 10 |\n| 4 | 15 | 8 | +3 | (6+Int)x4 | 11 |\n| 5 | 15 | 10 | +4 | (6+Int)x5 | 12 |\n| 6 | 15 | 12 | +5 | (6+Int)x6 | 13 |\n| 7 | 15 | 14 | +6 | (6+Int)x7 | 14 |\n| 8 | 16 (+1) | 16 | +7 | (6+Int)x8 | 15 |\n| 9 | 16 | 18 | +8 | (6+Int)x9 | 16 |\n| 10 | 16 | 20 | +9 | (6+Int)x10 | 17 |\n| 11 | 16 | 22 | +10 | (6+Int)x11 | 18 |\n| 12 | 16 | 24 | +11 | (6+Int)x12 | 19 |\n| 13 | 16 | 26 | +12 | (6+Int)x13 | 20 |\n| 14 | 16 | 28 | +13 | (6+Int)x14 | 21 |\n| 15 | 16 | 30 | +14 | (6+Int)x15 | 22 |\n| 16 | 17 (+1) | 32 | +15 | (6+Int)x16 | 23 |\n| 17 | 17 | 34 | +16 | (6+Int)x17 | 24 |\n| 18 | 17 | 36 | +17 | (6+Int)x18 | 25 |\n| 19 | 17 | 38 | +18 | (6+Int)x19 | 26 |\n| 20 | 17 | 40 | +19 | (6+Int)x20 | 27 |
//Par ''Akhad''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>Cette adaptation tente de se rapprocher de la version officielle et de la prochaine annoncée (Saga edition) tout en appliquant les principes du dK. Ainsi, les personnages débutants ne profiterons pas immédiatement de l'énorme avantage d'additionner deux caractéristique par compétence.\nLe livre de base de Star Wars reste utile notamment pour l'équipement.>>\n!Création de personnage\n*Le peuple d'origine donne accès à des bonus de caractéristiques, de compétences, de sauvegarde particulière (Vigueur, Volonté ou Réflexes) et à certains atouts. \n*A la création, un atout "Avantage" est donné gratuitement ainsi que 8 autres libres. \n*Les atouts "Gars du coin" (pour sa planète d'origine), "Posture défensive", "Posture offensive", "Attaques multiples" et "Caractéristiques" sont considérées comme universels pour peu que les possibles pré-requis soient respectés.\n<<tiddler [[Star Wars : évolution du personnage]]>>\n<<tiddler [[Star Wars : peuples]]>>\n<<tiddler [[Star Wars : compétences]]>>\n<<tiddler [[Star Wars : atouts]]>>\n<<tiddler [[Star Wars : équipement]]>>\n<<tiddler [[Star Wars : la Force]]>>
/***\n!Personal preferences\n***/\n\n/*{{{*/\n/* make input fields in viewer (options) show up in correct size */\n.viewer input { font-size: 0.9em; }\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\nbody {\n background: #fff;\n color: #000;\n font-size: 6.2pt;\n font-family: "Lucida Grande", "Bitstream Vera Sans", Helvetica, Verdana, Arial, sans-serif;\n}\n\nimg {\n max-width: 2.2in;\n max-height: 4.3in;\n}\n\n#header, #side_container, #storeArea, #copyright, #floater, #messageArea, .save_accesskey, .site_description, #saveTest, .toolbar, .footer\n{\n display: none;\n}\n\n#tiddlerDisplay, #displayArea\n{\n display: inline;\n}\n\n.tiddler {\n margin: 0 0 2em 0;\n border-top: 1px solid #000;\n page-break-before: always;\n}\n\n.tiddler:first-child {\n page-break-before: avoid;\n}\n\n.title {\n font-size: 1.6em;\n font-weight: bold;\n margin-bottom: .3em;\n padding: .2em 0;\n border-bottom: 1px dotted #000;\n}\n\np, blockquote, ul, li, ol, dt, dd, dl, table\n{\n margin: 0 0 .3em 0;\n}\n\nh1, h2, h3, h4, h5, h6\n{\n margin: .2em 0;\n} \n\nh1\n{\n font-size: 1.5em;\n}\n\nh2\n{\n font-size: 1.3em;\n}\n\nh3\n{\n font-size: 1.25em;\n}\n\nh4\n{\n font-size: 1.15em;\n}\n\nh5\n{\n font-size: 1.1em;\n}\n\nblockquote\n{\n margin: .6em;\n padding-left: .6em;\n border-left: 1px solid #ccc;\n}\n\nul\n{\n list-style-type: circle;\n}\n\nli\n{\n margin: .1em 0 .1em 2em;\n line-height: 1.4em; \n}\n\ntable\n{\n border-collapse: collapse;\n font-size: 1em;\n}\n\ntd, th\n{\n border: 1px solid #999;\n padding: .2em;\n}\n\nhr {\n border: none;\n border-top: dotted 1px #777;\n height: 1px;\n color: #777;\n margin: .6em 0;\n}\n}\n/*}}}*/
|review|k\n|!Overdue actions|!All reminders for the next week|\n|<<showReminders leadtime:-365...-1 tag:"action !done" format:"DATE: @@color:red;TITLE@@ [ TIDDLER ]">>|<<showReminders leadtime:0...7 tag:"!done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>|\n|!Actions for today/tomorrow|~|\n|<<showReminders leadtime:0...1 tag:"action !done" format:"DIFF: @@color:red;TITLE@@ [ TIDDLER ]">>|~|\n|!Project Review|!Action Review|\n|<<tiddler "Project Review">>|<<tiddler "Action Review">>|\n
/***\n|''Name:''|TWUpdatePlugin|\n|''Description:''|Plugin to enable quick update of TW core|\n|''Version:''|1.0.2|\n|''Date:''|December 15, 2006|\n|''Source:''|http://www.dcubed.ca/|\n|''Author:''|Tom Otvos|\n|''~CoreVersion:''|2.0.7|\n|''Browser:''|Firefox 1.5+; InternetExplorer 6.0+|\n***/\n//{{{\n\nversion.extensions.twupdate = {major: 1, minor: 0, revision: 2, source: "http://www.dcubed.ca/"};\n\nconfig.macros.twupdate = { \n label: "update",\n sourceUrl: "http://www.tiddlywiki.com/empty.html", \n lingo: {\n prompt: "Update this TiddlyWiki from TiddlyWiki.com", \n warning: "Are you sure you want to update this document with the latest version of TiddlyWiki (and do you know that all your plugins are compatible)?\sn\snIf you want to continue, your document will first be saved with a backup.",\n success: "Update was successful. Click on 'OK' to reload the document",\n errNoHttp: "Unable to allocate an HTTP request object for the update",\n errIncompatible: "This version of TiddlyWiki cannot be updated by this plugin. Sorry.",\n errIncompatible2: "This version of TiddlyWiki is the last version that can be updated by this plugin. Sorry.",\n progressLoading: "Getting update from TiddlyWiki.com...",\n progressLoadSuccess: "File successfully loaded",\n progressLoadFailure: "File was not loaded successfully (%0)",\n progressMerging: "Merging with existing document..."\n }\n}\n\nconfig.macros.twupdate.handler = function(place,macroName,params)\n{\n if(!readOnly) {\n var label = params[0] ? params[0] : this.label;\n createTiddlyButton(place, label, this.lingo.prompt, this.onClick, null, null, null);\n }\n}\n\nconfig.macros.twupdate.onClick = function(e)\n{\n if (version.major != 2 || version.minor > 1 || (version.minor == 0 && version.revision < 7)) {\n alert(config.macros.twupdate.lingo.errIncompatible);\n return;\n }\n \n //if (version.major != 2 || version.minor != 0 || version.revision == 11) {\n // alert(config.macros.twupdate.lingo.errIncompatible2);\n // return;\n //}\n \n if (!confirm(config.macros.twupdate.lingo.warning)) return;\n\n try {\n // force a save with backup\n var saveBackups = config.options.chkSaveBackups;\n config.options.chkSaveBackups = true;\n saveChanges();\n config.options.chkSaveBackups = saveBackups;\n \n var ajax = new AjaxHelper();\n displayMessage(config.macros.twupdate.lingo.progressLoading);\n ajax.getText(config.macros.twupdate.sourceUrl, config.macros.twupdate.performUpdate); \n }\n catch (e) {\n alert(e);\n }\n\n return false;\n}\n\n// Courtesy of http://www.worldtimzone.com/res/encode/...\nfunction utf8(wide) {\n var c, s;\n var enc = "";\n var i = 0;\n while(i<wide.length) {\n c= wide.charCodeAt(i++);\n // handle UTF-16 surrogates\n if (c>=0xDC00 && c<0xE000) continue;\n if (c>=0xD800 && c<0xDC00) {\n if (i>=wide.length) continue;\n s= wide.charCodeAt(i++);\n if (s<0xDC00 || c>=0xDE00) continue;\n c= ((c-0xD800)<<10)+(s-0xDC00)+0x10000;\n }\n // output value\n if (c<0x80) enc += String.fromCharCode(c);\n else if (c<0x800) enc += String.fromCharCode(0xC0+(c>>6),0x80+(c&0x3F));\n else if (c<0x10000) enc += String.fromCharCode(0xE0+(c>>12),0x80+(c>>6&0x3F),0x80+(c&0x3F));\n else enc += String.fromCharCode(0xF0+(c>>18),0x80+(c>>12&0x3F),0x80+(c>>6&0x3F),0x80+(c&0x3F));\n }\n return enc;\n}\n\nconfig.macros.twupdate.performUpdate = function(emptyHtml, status, statusText)\n{\n // note that this is begin called from a callback from an event handler, so\n // "this" is most definitely not defined!\n \n if (status == 200)\n displayMessage(config.macros.twupdate.lingo.progressLoadSuccess);\n else {\n displayMessage(config.macros.twupdate.lingo.progressLoadFailure.format([statusText]));\n return;\n }\n displayMessage(config.macros.twupdate.lingo.progressMerging);\n \n // very important...convert the response to UTF-8 to be fully TW-compatible\n var re = /[^\su0000-\su007F]/g ;\n emptyHtml = emptyHtml.replace(re, function($0) {return(utf8($0));});\n \n // the bulk of this is cribbed from saveChanges()...\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);\n if (store.tiddlerExists(config.messages.saveInstructions))\n displayTiddler(null,config.messages.saveInstructions);\n return;\n }\n var localPath = getLocalPath(originalPath);\n\n // Locate the storeArea div's\n var posOpeningDiv = emptyHtml.indexOf(startSaveArea);\n var limitClosingDiv = emptyHtml.indexOf("<!--POST-BODY-START--"+">");\n var posClosingDiv = emptyHtml.lastIndexOf(endSaveArea,limitClosingDiv == -1 ? emptyHtml.length : limitClosingDiv);\n if ((posOpeningDiv == -1) || (posClosingDiv == -1)) {\n alert(config.messages.invalidFileError.format(['empty.html']));\n return;\n }\n\n // Save new file\n var revised = emptyHtml.substr(0,posOpeningDiv + startSaveArea.length) + \n convertUnicodeToUTF8(allTiddlersAsHtml()) + "\sn\st\st" +\n emptyHtml.substr(posClosingDiv);\n var newSiteTitle = convertUnicodeToUTF8((wikifyPlain("SiteTitle") + " - " + wikifyPlain("SiteSubtitle")).htmlEncode());\n revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");\n revised = revised.replaceChunk("<!--PRE-HEAD-START--"+">","<!--PRE-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPreHead","") + "\sn");\n revised = revised.replaceChunk("<!--POST-HEAD-START--"+">","<!--POST-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPostHead","") + "\sn");\n revised = revised.replaceChunk("<!--PRE-BODY-START--"+">","<!--PRE-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPreBody","") + "\sn");\n revised = revised.replaceChunk("<!--POST-BODY-START--"+">","<!--POST-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPostBody","") + "\sn");\n var save = saveFile(localPath, revised);\n if (save) {\n displayMessage(config.messages.mainSaved, "file://" + localPath);\n store.setDirty(false);\n alert(config.macros.twupdate.lingo.success);\n document.location.reload();\n }\n else\n alert(config.messages.mainFailed);\n}\n\nfunction AjaxHelper()\n{\n this.http = null;\n \n try\n {\n this.http = new XMLHttpRequest()\n }\n \n catch(e)\n {\n // if we don't get an internal object, try allocating it using ActiveX, with successive\n // fallbacks to earlier MSXML versions as necessary\n try\n {\n this.http = new ActiveXObject("Msxml2.XMLHTTP.4.0")\n } \n catch(e) \n {\n try\n {\n this.http = new ActiveXObject("MSXML2.XMLHTTP")\n } \n catch(e) \n {\n try\n {\n this.http = new ActiveXObject("Microsoft.XMLHTTP")\n } \n catch(e) \n {\n this.http = null\n }\n }\n }\n }\n \n if (!this.http) throw 'Unable to allocate an HTTP request object';\n}\n\nAjaxHelper.prototype.getText = function(url, callback, async, force)\n{\n if (!this.http) return;\n if (async == undefined) async = true;\n if (force == undefined) force = false;\n // ??? right now, we are not handling "forced" requests\n this._request("GET", url, callback, async, true, false);\n}\n\nAjaxHelper.prototype.getXML = function(url, callback, async, force)\n{\n if (!this.http) return;\n if (async == undefined) async = true;\n if (force == undefined) force = false;\n // ??? right now, we are not handling "forced" requests\n this._request("GET", url, callback, async, true, true);\n}\n\nAjaxHelper.prototype.getHead = function(url, callback, async, force)\n{\n if (!this.http) return;\n if (async == undefined) async = true;\n if (force == undefined) force = false;\n // ??? right now, we are not handling "forced" requests\n this._request("HEAD", url, callback, async, false, false);\n}\n\nAjaxHelper.prototype.abort = function()\n{\n if (this.http) this.http.abort();\n}\n\nAjaxHelper.prototype.setRequestHeader = function(name, value)\n{\n if (this.http) this.http.setRequestHeader(name, value);\n}\n\nAjaxHelper.prototype._request = function(method, url, callback, async, hasResponse, hasResponseXML)\n{\n if (!this.http) return;\n \n // get reference to request object so we can use it in closure\n var xmlHttp = this.http, helper = this;\n xmlHttp.onreadystatechange = function()\n {\n if (!async) return;\n if (xmlHttp.readyState == 4)\n callback((hasResponse ? (hasResponseXML ? xmlHttp.responseXML : xmlHttp.responseText) : null), xmlHttp.status, xmlHttp.statusText, helper._parsedResponseHeaders());\n }\n \n try {\n // need some cross-domain privileges for Firefox\n try {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n } \n catch (e) \n {\n }\n \n xmlHttp.open(method, url, async);\n xmlHttp.send(null);\n if (!async) callback((hasResponse ? (hasResponseXML ? xmlHttp.responseXML : xmlHttp.responseText) : null), xmlHttp.status, xmlHttp.statusText, this._parsedResponseHeaders());\n }\n \n catch (e)\n {\n alert(e);\n }\n}\n\nAjaxHelper.prototype._parsedResponseHeaders = function()\n{\n if (this.http) {\n var headersArray = new Array();\n var headers = this.http.getAllResponseHeaders().split("\sn");\n for (var i = 0; i < headers.length; i++) {\n var h = headers[i].trim();\n if (h.length == 0) continue;\n // value can have ':' so do not use split here!\n var sep = h.indexOf(':');\n headersArray[h.substring(0, sep).trim()] = h.substr(sep + 1).trim();\n }\n return headersArray;\n }\n else\n return null;\n}\n\n//}}}\n
Vous trouverez dans la fenêtre //Tagging//, à droite, la liste des catégories et des articles disponibles dans cette section.
If you are connected to the Internet, you can always get the latest version of this application. There are ''three'' ways you can do this:\n\nClick the following button if you simply want to get the latest changes to any of the core tiddlers that make up this application. These tiddlers are tagged "gtd", and updating in this way will not overwrite any of the core tiddlers that you may have changed unless the core tiddlers are even newer than your changes. This is the recommended way to get updates:\n**<<importUpdates "http://www.dcubed.ca/gtd-update.html">>\n\nClick the following button if you would like to get the latest changes to any of the core tiddlers, but to interactively approve each and every updated tiddler as it is loaded into your system. If there are no updated tiddlers, you will not be prompted and the update will exit quietly:\n**<<importUpdates "http://www.dcubed.ca/gtd-update.html" updates "Update interactively" "Click here to interactively update the application" confirm>>\n\nClick the following button if you want to download all of the core tiddlers, regardless of their modification date. Use this to absolutely ensure that you are running with the core application as it was originally written:\n**<<importUpdates "http://www.dcubed.ca/gtd-update.html" all "Update everything">>\n\n''For your safety, your file will be saved and a backup file will be automatically generated before any update is performed.''\n\n!!Update ~TiddlyWiki\nAs a convenience, you can easily update the ~TiddlyWiki core used by this application by clicking on the following button:\n**<<twupdate "Update TiddlyWiki">>\n\nNote that you do not //need// to use this to update ~TiddlyWiki; you can always use [[this technique|http://www.tiddlywiki.com/#HowToUpgrade]]. But a single click seems a whole lot easier!\n\n!!Import and export\nIf you want finer-grained control over moving tiddlers in and out of this system, the following tools will do the job:\n\n** +++[Import...|Import selected tiddlers from another wiki]<<importTiddlers inline>>===\n\n** +++[Export...|Export selected tiddlers from this wiki]<<exportTiddlers inline>>===\n
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |\n| 29/1/2007 16:21:52 | YourName | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 29/1/2007 16:33:45 | YourName | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 29/1/2007 16:36:5 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 29/1/2007 20:14:2 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 29/1/2007 20:17:58 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 29/1/2007 20:23:40 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 29/1/2007 21:30:6 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/#%5B%5BStar%20Wars%20dk%5D%5D]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 29/1/2007 21:48:12 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/#%5B%5BStar%20Wars%20dk%5D%5D]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 29/1/2007 21:54:6 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/#%5B%5BStar%20Wars%20dk%5D%5D]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 30/1/2007 9:18:49 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 30/1/2007 9:39:7 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 30/1/2007 11:25:50 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/#]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 30/1/2007 11:25:54 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/#]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 30/1/2007 14:40:34 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 30/1/2007 20:6:2 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 1/2/2007 0:4:55 | YourName | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 2/2/2007 13:2:58 | YourName | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 7/2/2007 23:44:32 | LeGrumph | [[/|http://matricedk.tiddlyspot.com/]] | [[store.cgi|http://matricedk.tiddlyspot.com/store.cgi]] | . | index.html | . |
/***\n|''Name:''|UploadPlugin|\n|''Description:''|Save to web a TiddlyWiki|\n|''Version:''|3.4.4|\n|''Date:''|Sep 30, 2006|\n|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|\n|''Documentation:''|http://tiddlywiki.bidix.info/#UploadDoc|\n|''Author:''|BidiX (BidiX (at) bidix (dot) info)|\n|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|\n|''~CoreVersion:''|2.0.0|\n|''Browser:''|Firefox 1.5; InternetExplorer 6.0; Safari|\n|''Include:''|config.lib.file; config.lib.log; config.lib.options; PasswordTweak|\n|''Require:''|[[UploadService|http://tiddlywiki.bidix.info/#UploadService]]|\n***/\n//{{{\nversion.extensions.UploadPlugin = {\n major: 3, minor: 4, revision: 4, \n date: new Date(2006,8,30),\n source: 'http://tiddlywiki.bidix.info/#UploadPlugin',\n documentation: 'http://tiddlywiki.bidix.info/#UploadDoc',\n author: 'BidiX (BidiX (at) bidix (dot) info',\n license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',\n coreVersion: '2.0.0',\n browser: 'Firefox 1.5; InternetExplorer 6.0; Safari'\n};\n//}}}\n\n////+++!![config.lib.file]\n\n//{{{\nif (!config.lib) config.lib = {};\nif (!config.lib.file) config.lib.file= {\n author: 'BidiX',\n version: {major: 0, minor: 1, revision: 0}, \n date: new Date(2006,3,9)\n};\nconfig.lib.file.dirname = function (filePath) {\n var lastpos;\n if ((lastpos = filePath.lastIndexOf("/")) != -1) {\n return filePath.substring(0, lastpos);\n } else {\n return filePath.substring(0, filePath.lastIndexOf("\s\s"));\n }\n};\nconfig.lib.file.basename = function (filePath) {\n var lastpos;\n if ((lastpos = filePath.lastIndexOf("#")) != -1) \n filePath = filePath.substring(0, lastpos);\n if ((lastpos = filePath.lastIndexOf("/")) != -1) {\n return filePath.substring(lastpos + 1);\n } else\n return filePath.substring(filePath.lastIndexOf("\s\s")+1);\n};\nwindow.basename = function() {return "@@deprecated@@";};\n//}}}\n////===\n\n////+++!![config.lib.log]\n\n//{{{\nif (!config.lib) config.lib = {};\nif (!config.lib.log) config.lib.log= {\n author: 'BidiX',\n version: {major: 0, minor: 1, revision: 1}, \n date: new Date(2006,8,19)\n};\nconfig.lib.Log = function(tiddlerTitle, logHeader) {\n if (version.major < 2)\n this.tiddler = store.tiddlers[tiddlerTitle];\n else\n this.tiddler = store.getTiddler(tiddlerTitle);\n if (!this.tiddler) {\n this.tiddler = new Tiddler();\n this.tiddler.title = tiddlerTitle;\n this.tiddler.text = "| !date | !user | !location |" + logHeader;\n this.tiddler.created = new Date();\n this.tiddler.modifier = config.options.txtUserName;\n this.tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers[tiddlerTitle] = this.tiddler;\n else\n store.addTiddler(this.tiddler);\n }\n return this;\n};\n\nconfig.lib.Log.prototype.newLine = function (line) {\n var now = new Date();\n var newText = "| ";\n newText += now.getDate()+"/"+(now.getMonth()+1)+"/"+now.getFullYear() + " ";\n newText += now.getHours()+":"+now.getMinutes()+":"+now.getSeconds()+" | ";\n newText += config.options.txtUserName + " | ";\n var location = document.location.toString();\n var filename = config.lib.file.basename(location);\n if (!filename) filename = '/';\n newText += "[["+filename+"|"+location + "]] |";\n this.tiddler.text = this.tiddler.text + "\sn" + newText;\n this.addToLine(line);\n};\n\nconfig.lib.Log.prototype.addToLine = function (text) {\n this.tiddler.text = this.tiddler.text + text;\n this.tiddler.modifier = config.options.txtUserName;\n this.tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers[this.tiddler.tittle] = this.tiddler;\n else {\n store.addTiddler(this.tiddler);\n story.refreshTiddler(this.tiddler.title);\n store.notify(this.tiddler.title, true);\n }\n if (version.major < 2)\n store.notifyAll(); \n};\n//}}}\n////===\n\n////+++!![config.lib.options]\n\n//{{{\nif (!config.lib) config.lib = {};\nif (!config.lib.options) config.lib.options = {\n author: 'BidiX',\n version: {major: 0, minor: 1, revision: 0}, \n date: new Date(2006,3,9)\n};\n\nconfig.lib.options.init = function (name, defaultValue) {\n if (!config.options[name]) {\n config.options[name] = defaultValue;\n saveOptionCookie(name);\n }\n};\n//}}}\n////===\n\n////+++!![PasswordTweak]\n\n//{{{\nversion.extensions.PasswordTweak = {\n major: 1, minor: 0, revision: 3, date: new Date(2006,8,30),\n type: 'tweak',\n source: 'http://tiddlywiki.bidix.info/#PasswordTweak'\n};\n//}}}\n/***\n!!config.macros.option\n***/\n//{{{\nconfig.macros.option.passwordCheckboxLabel = "Save this password on this computer";\nconfig.macros.option.passwordType = "password"; // password | text\n\nconfig.macros.option.onChangeOption = function(e)\n{\n var opt = this.getAttribute("option");\n var elementType,valueField;\n if(opt) {\n switch(opt.substr(0,3)) {\n case "txt":\n elementType = "input";\n valueField = "value";\n break;\n case "pas":\n elementType = "input";\n valueField = "value";\n break;\n case "chk":\n elementType = "input";\n valueField = "checked";\n break;\n }\n config.options[opt] = this[valueField];\n saveOptionCookie(opt);\n var nodes = document.getElementsByTagName(elementType);\n for(var t=0; t<nodes.length; t++) \n {\n var optNode = nodes[t].getAttribute("option");\n if (opt == optNode) \n nodes[t][valueField] = this[valueField];\n }\n }\n return(true);\n};\n\nconfig.macros.option.handler = function(place,macroName,params)\n{\n var opt = params[0];\n if(config.options[opt] === undefined) {\n return;}\n var c;\n switch(opt.substr(0,3)) {\n case "txt":\n c = document.createElement("input");\n c.onkeyup = this.onChangeOption;\n c.setAttribute ("option",opt);\n c.className = "txtOptionInput "+opt;\n place.appendChild(c);\n c.value = config.options[opt];\n break;\n case "pas":\n // input password\n c = document.createElement ("input");\n c.setAttribute("type",config.macros.option.passwordType);\n c.onkeyup = this.onChangeOption;\n c.setAttribute("option",opt);\n c.className = "pasOptionInput "+opt;\n place.appendChild(c);\n c.value = config.options[opt];\n // checkbox link with this password "save this password on this computer"\n c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick = this.onChangeOption;\n c.setAttribute("option","chk"+opt);\n c.className = "chkOptionInput "+opt;\n place.appendChild(c);\n c.checked = config.options["chk"+opt];\n // text savePasswordCheckboxLabel\n place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));\n break;\n case "chk":\n c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick = this.onChangeOption;\n c.setAttribute("option",opt);\n c.className = "chkOptionInput "+opt;\n place.appendChild(c);\n c.checked = config.options[opt];\n break;\n }\n};\n//}}}\n/***\n!! Option cookie stuff\n***/\n//{{{\nwindow.loadOptionsCookie_orig_PasswordTweak = window.loadOptionsCookie;\nwindow.loadOptionsCookie = function()\n{\n var cookies = document.cookie.split(";");\n for(var c=0; c<cookies.length; c++) {\n var p = cookies[c].indexOf("=");\n if(p != -1) {\n var name = cookies[c].substr(0,p).trim();\n var value = cookies[c].substr(p+1).trim();\n switch(name.substr(0,3)) {\n case "txt":\n config.options[name] = unescape(value);\n break;\n case "pas":\n config.options[name] = unescape(value);\n break;\n case "chk":\n config.options[name] = value == "true";\n break;\n }\n }\n }\n};\n\nwindow.saveOptionCookie_orig_PasswordTweak = window.saveOptionCookie;\nwindow.saveOptionCookie = function(name)\n{\n var c = name + "=";\n switch(name.substr(0,3)) {\n case "txt":\n c += escape(config.options[name].toString());\n break;\n case "chk":\n c += config.options[name] ? "true" : "false";\n // is there an option link with this chk ?\n if (config.options[name.substr(3)]) {\n saveOptionCookie(name.substr(3));\n }\n break;\n case "pas":\n if (config.options["chk"+name]) {\n c += escape(config.options[name].toString());\n } else {\n c += "";\n }\n break;\n }\n c += "; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";\n document.cookie = c;\n};\n//}}}\n/***\n!! Initializations\n***/\n//{{{\n// define config.options.pasPassword\nif (!config.options.pasPassword) {\n config.options.pasPassword = 'defaultPassword';\n window.saveOptionCookie('pasPassword');\n}\n// since loadCookies is first called befor password definition\n// we need to reload cookies\nwindow.loadOptionsCookie();\n//}}}\n////===\n\n////+++!![config.macros.upload]\n\n//{{{\nconfig.macros.upload = {\n accessKey: "U",\n formName: "UploadPlugin",\n contentType: "text/html;charset=UTF-8",\n defaultStoreScript: "store.php"\n};\n\n// only this two configs need to be translated\nconfig.macros.upload.messages = {\n aboutToUpload: "About to upload TiddlyWiki to %0",\n backupFileStored: "Previous file backuped in %0",\n crossDomain: "Certainly a cross-domain isue: access to an other site isn't allowed",\n errorDownloading: "Error downloading",\n errorUploadingContent: "Error uploading content",\n fileLocked: "Files is locked: You are not allowed to Upload",\n fileNotFound: "file to upload not found",\n fileNotUploaded: "File %0 NOT uploaded",\n mainFileUploaded: "Main TiddlyWiki file uploaded to %0",\n passwordEmpty: "Unable to upload, your password is empty",\n urlParamMissing: "url param missing",\n rssFileNotUploaded: "RssFile %0 NOT uploaded",\n rssFileUploaded: "Rss File uploaded to %0"\n};\n\nconfig.macros.upload.label = {\n promptOption: "Save and Upload this TiddlyWiki with UploadOptions",\n promptParamMacro: "Save and Upload this TiddlyWiki in %0",\n saveLabel: "save to web", \n saveToDisk: "save to disk",\n uploadLabel: "upload" \n};\n\nconfig.macros.upload.handler = function(place,macroName,params){\n // parameters initialization\n var storeUrl = params[0];\n var toFilename = params[1];\n var backupDir = params[2];\n var uploadDir = params[3];\n var username = params[4];\n var password; // for security reason no password as macro parameter\n var label;\n if (document.location.toString().substr(0,4) == "http")\n label = this.label.saveLabel;\n else\n label = this.label.uploadLabel;\n var prompt;\n if (storeUrl) {\n prompt = this.label.promptParamMacro.toString().format([this.toDirUrl(storeUrl, uploadDir, username)]);\n }\n else {\n prompt = this.label.promptOption;\n }\n createTiddlyButton(place, label, prompt, \n function () {\n config.macros.upload.upload(storeUrl, toFilename, uploadDir, backupDir, username, password); \n return false;}, \n null, null, this.accessKey);\n};\nconfig.macros.upload.UploadLog = function() {\n return new config.lib.Log('UploadLog', " !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |" );\n};\nconfig.macros.upload.UploadLog.prototype = config.lib.Log.prototype;\nconfig.macros.upload.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {\n var line = " [[" + config.lib.file.basename(storeUrl) + "|" + storeUrl + "]] | ";\n line += uploadDir + " | " + toFilename + " | " + backupDir + " |";\n this.newLine(line);\n};\nconfig.macros.upload.UploadLog.prototype.endUpload = function() {\n this.addToLine(" Ok |");\n};\nconfig.macros.upload.basename = config.lib.file.basename;\nconfig.macros.upload.dirname = config.lib.file.dirname;\nconfig.macros.upload.toRootUrl = function (storeUrl, username)\n{\n return root = (this.dirname(storeUrl)?this.dirname(storeUrl):this.dirname(document.location.toString()));\n}\nconfig.macros.upload.toDirUrl = function (storeUrl, uploadDir, username)\n{\n var root = this.toRootUrl(storeUrl, username);\n if (uploadDir && uploadDir != '.')\n root = root + '/' + uploadDir;\n return root;\n}\nconfig.macros.upload.toFileUrl = function (storeUrl, toFilename, uploadDir, username)\n{\n return this.toDirUrl(storeUrl, uploadDir, username) + '/' + toFilename;\n}\nconfig.macros.upload.upload = function(storeUrl, toFilename, uploadDir, backupDir, username, password)\n{\n // parameters initialization\n storeUrl = (storeUrl ? storeUrl : config.options.txtUploadStoreUrl);\n toFilename = (toFilename ? toFilename : config.options.txtUploadFilename);\n backupDir = (backupDir ? backupDir : config.options.txtUploadBackupDir);\n uploadDir = (uploadDir ? uploadDir : config.options.txtUploadDir);\n username = (username ? username : config.options.txtUploadUserName);\n password = config.options.pasUploadPassword; // for security reason no password as macro parameter\n if (!password || password === '') {\n alert(config.macros.upload.messages.passwordEmpty);\n return;\n }\n if (storeUrl === '') {\n storeUrl = config.macros.upload.defaultStoreScript;\n }\n if (config.lib.file.dirname(storeUrl) === '') {\n storeUrl = config.lib.file.dirname(document.location.toString())+'/'+storeUrl;\n }\n if (toFilename === '') {\n toFilename = config.lib.file.basename(document.location.toString());\n }\n\n clearMessage();\n // only for forcing the message to display\n if (version.major < 2)\n store.notifyAll();\n if (!storeUrl) {\n alert(config.macros.upload.messages.urlParamMissing);\n return;\n }\n // Check that file is not locked\n if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {\n if (BidiX.GroupAuthoring.lock.isLocked() && !BidiX.GroupAuthoring.lock.isMyLock()) {\n alert(config.macros.upload.messages.fileLocked);\n return;\n }\n }\n \n var log = new this.UploadLog();\n log.startUpload(storeUrl, toFilename, uploadDir, backupDir);\n if (document.location.toString().substr(0,5) == "file:") {\n saveChanges();\n }\n var toDir = config.macros.upload.toDirUrl(storeUrl, toFilename, uploadDir, username);\n displayMessage(config.macros.upload.messages.aboutToUpload.format([toDir]), toDir);\n this.uploadChanges(storeUrl, toFilename, uploadDir, backupDir, username, password);\n if(config.options.chkGenerateAnRssFeed) {\n //var rssContent = convertUnicodeToUTF8(generateRss());\n var rssContent = generateRss();\n var rssPath = toFilename.substr(0,toFilename.lastIndexOf(".")) + ".xml";\n this.uploadContent(rssContent, storeUrl, rssPath, uploadDir, '', username, password, \n function (responseText) {\n if (responseText.substring(0,1) != '0') {\n displayMessage(config.macros.upload.messages.rssFileNotUploaded.format([rssPath]));\n }\n else {\n var toFileUrl = config.macros.upload.toFileUrl(storeUrl, rssPath, uploadDir, username);\n displayMessage(config.macros.upload.messages.rssFileUploaded.format(\n [toFileUrl]), toFileUrl);\n }\n // for debugging store.php uncomment last line\n //DEBUG alert(responseText);\n });\n }\n return;\n};\n\nconfig.macros.upload.uploadChanges = function(storeUrl, toFilename, uploadDir, backupDir, \n username, password) {\n var original;\n if (document.location.toString().substr(0,4) == "http") {\n original = this.download(storeUrl, toFilename, uploadDir, backupDir, username, password);\n return;\n }\n else {\n // standard way : Local file\n \n original = loadFile(getLocalPath(document.location.toString()));\n if(window.Components) {\n // it's a mozilla browser\n try {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]\n .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);\n converter.charset = "UTF-8";\n original = converter.ConvertToUnicode(original);\n }\n catch(e) {\n }\n }\n }\n //DEBUG alert(original);\n this.uploadChangesFrom(original, storeUrl, toFilename, uploadDir, backupDir, \n username, password);\n};\n\nconfig.macros.upload.uploadChangesFrom = function(original, storeUrl, toFilename, uploadDir, backupDir, \n username, password) {\n var startSaveArea = '<div id="' + 'storeArea">'; // Split up into two so that indexOf() of this source doesn't find it\n var endSaveArea = '</d' + 'iv>';\n // Locate the storeArea div's\n var posOpeningDiv = original.indexOf(startSaveArea);\n var posClosingDiv = original.lastIndexOf(endSaveArea);\n if((posOpeningDiv == -1) || (posClosingDiv == -1))\n {\n alert(config.messages.invalidFileError.format([document.location.toString()]));\n return;\n }\n var revised = original.substr(0,posOpeningDiv + startSaveArea.length) + \n allTiddlersAsHtml() + "\sn\st\st" +\n original.substr(posClosingDiv);\n var newSiteTitle;\n if(version.major < 2){\n newSiteTitle = (getElementText("siteTitle") + " - " + getElementText("siteSubtitle")).htmlEncode();\n } else {\n newSiteTitle = (wikifyPlain ("SiteTitle") + " - " + wikifyPlain ("SiteSubtitle")).htmlEncode();\n }\n\n revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");\n revised = revised.replaceChunk("<!--PRE-HEAD-START--"+">","<!--PRE-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPreHead","") + "\sn");\n revised = revised.replaceChunk("<!--POST-HEAD-START--"+">","<!--POST-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPostHead","") + "\sn");\n revised = revised.replaceChunk("<!--PRE-BODY-START--"+">","<!--PRE-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPreBody","") + "\sn");\n revised = revised.replaceChunk("<!--POST-BODY-START--"+">","<!--POST-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPostBody","") + "\sn");\n\n var response = this.uploadContent(revised, storeUrl, toFilename, uploadDir, backupDir, \n username, password, function (responseText) {\n if (responseText.substring(0,1) != '0') {\n alert(responseText);\n displayMessage(config.macros.upload.messages.fileNotUploaded.format([getLocalPath(document.location.toString())]));\n }\n else {\n if (uploadDir !== '') {\n toFilename = uploadDir + "/" + config.macros.upload.basename(toFilename);\n } else {\n toFilename = config.macros.upload.basename(toFilename);\n }\n var toFileUrl = config.macros.upload.toFileUrl(storeUrl, toFilename, uploadDir, username);\n if (responseText.indexOf("destfile:") > 0) {\n var destfile = responseText.substring(responseText.indexOf("destfile:")+9, \n responseText.indexOf("\sn", responseText.indexOf("destfile:")));\n toFileUrl = config.macros.upload.toRootUrl(storeUrl, username) + '/' + destfile;\n }\n else {\n toFileUrl = config.macros.upload.toFileUrl(storeUrl, toFilename, uploadDir, username);\n }\n displayMessage(config.macros.upload.messages.mainFileUploaded.format(\n [toFileUrl]), toFileUrl);\n if (backupDir && responseText.indexOf("backupfile:") > 0) {\n var backupFile = responseText.substring(responseText.indexOf("backupfile:")+11, \n responseText.indexOf("\sn", responseText.indexOf("backupfile:")));\n toBackupUrl = config.macros.upload.toRootUrl(storeUrl, username) + '/' + backupFile;\n displayMessage(config.macros.upload.messages.backupFileStored.format(\n [toBackupUrl]), toBackupUrl);\n }\n var log = new config.macros.upload.UploadLog();\n log.endUpload();\n store.setDirty(false);\n // erase local lock\n if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {\n BidiX.GroupAuthoring.lock.eraseLock();\n // change mtime with new mtime after upload\n var mtime = responseText.substr(responseText.indexOf("mtime:")+6);\n BidiX.GroupAuthoring.lock.mtime = mtime;\n }\n \n \n }\n // for debugging store.php uncomment last line\n //DEBUG alert(responseText);\n }\n );\n};\n\nconfig.macros.upload.uploadContent = function(content, storeUrl, toFilename, uploadDir, backupDir, \n username, password, callbackFn) {\n var boundary = "---------------------------"+"AaB03x"; \n var request;\n try {\n request = new XMLHttpRequest();\n } \n catch (e) { \n request = new ActiveXObject("Msxml2.XMLHTTP"); \n }\n if (window.netscape){\n try {\n if (document.location.toString().substr(0,4) != "http") {\n netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');}\n }\n catch (e) {}\n } \n //DEBUG alert("user["+config.options.txtUploadUserName+"] password[" + config.options.pasUploadPassword + "]");\n // compose headers data\n var sheader = "";\n sheader += "--" + boundary + "\sr\snContent-disposition: form-data; name=\s"";\n sheader += config.macros.upload.formName +"\s"\sr\sn\sr\sn";\n sheader += "backupDir="+backupDir\n +";user=" + username \n +";password=" + password\n +";uploaddir=" + uploadDir;\n // add lock attributes to sheader\n if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {\n var l = BidiX.GroupAuthoring.lock.myLock;\n sheader += ";lockuser=" + l.user\n + ";mtime=" + l.mtime\n + ";locktime=" + l.locktime;\n }\n sheader += ";;\sr\sn"; \n sheader += "\sr\sn" + "--" + boundary + "\sr\sn";\n sheader += "Content-disposition: form-data; name=\s"userfile\s"; filename=\s""+toFilename+"\s"\sr\sn";\n sheader += "Content-Type: " + config.macros.upload.contentType + "\sr\sn";\n sheader += "Content-Length: " + content.length + "\sr\sn\sr\sn";\n // compose trailer data\n var strailer = new String();\n strailer = "\sr\sn--" + boundary + "--\sr\sn";\n //strailer = "--" + boundary + "--\sr\sn";\n var data;\n data = sheader + content + strailer;\n //request.open("POST", storeUrl, true, username, password);\n try {\n request.open("POST", storeUrl, true); \n }\n catch(e) {\n alert(config.macros.upload.messages.crossDomain + "\snError:" +e);\n exit;\n }\n request.onreadystatechange = function () {\n if (request.readyState == 4) {\n if (request.status == 200)\n callbackFn(request.responseText);\n else\n alert(config.macros.upload.messages.errorUploadingContent + "\snStatus: "+request.status.statusText);\n }\n };\n request.setRequestHeader("Content-Length",data.length);\n request.setRequestHeader("Content-Type","multipart/form-data; boundary="+boundary);\n request.send(data); \n};\n\n\nconfig.macros.upload.download = function(uploadUrl, uploadToFilename, uploadDir, uploadBackupDir, \n username, password) {\n var request;\n try {\n request = new XMLHttpRequest();\n } \n catch (e) { \n request = new ActiveXObject("Msxml2.XMLHTTP"); \n }\n try {\n if (uploadUrl.substr(0,4) == "http") {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n }\n else {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n }\n } catch (e) { }\n //request.open("GET", document.location.toString(), true, username, password);\n try {\n request.open("GET", document.location.toString(), true);\n }\n catch(e) {\n alert(config.macros.upload.messages.crossDomain + "\snError:" +e);\n exit;\n }\n \n request.onreadystatechange = function () {\n if (request.readyState == 4) {\n if(request.status == 200) {\n config.macros.upload.uploadChangesFrom(request.responseText, uploadUrl, \n uploadToFilename, uploadDir, uploadBackupDir, username, password);\n }\n else\n alert(config.macros.upload.messages.errorDownloading.format(\n [document.location.toString()]) + "\snStatus: "+request.status.statusText);\n }\n };\n request.send(null);\n};\n\n//}}}\n////===\n\n////+++!![Initializations]\n\n//{{{\nconfig.lib.options.init('txtUploadStoreUrl','store.php');\nconfig.lib.options.init('txtUploadFilename','');\nconfig.lib.options.init('txtUploadDir','');\nconfig.lib.options.init('txtUploadBackupDir','');\nconfig.lib.options.init('txtUploadUserName',config.options.txtUserName);\nconfig.lib.options.init('pasUploadPassword','');\nsetStylesheet(\n ".pasOptionInput {width: 11em;}\sn"+\n ".txtOptionInput.txtUploadStoreUrl {width: 25em;}\sn"+\n ".txtOptionInput.txtUploadFilename {width: 25em;}\sn"+\n ".txtOptionInput.txtUploadDir {width: 25em;}\sn"+\n ".txtOptionInput.txtUploadBackupDir {width: 25em;}\sn"+\n "",\n "UploadOptionsStyles");\nconfig.shadowTiddlers.UploadDoc = "[[Full Documentation|http://tiddlywiki.bidix.info/l#UploadDoc ]]\sn"; \nconfig.options.chkAutoSave = false; saveOptionCookie('chkAutoSave');\n\n//}}}\n////===\n\n////+++!![Core Hijacking]\n\n//{{{\nconfig.macros.saveChanges.label_orig_UploadPlugin = config.macros.saveChanges.label;\nconfig.macros.saveChanges.label = config.macros.upload.label.saveToDisk;\n\nconfig.macros.saveChanges.handler_orig_UploadPlugin = config.macros.saveChanges.handler;\n\nconfig.macros.saveChanges.handler = function(place)\n{\n if ((!readOnly) && (document.location.toString().substr(0,4) != "http"))\n createTiddlyButton(place,this.label,this.prompt,this.onClick,null,null,this.accessKey);\n};\n\n//}}}\n////===\n
This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.\n\n@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://matricedk.tiddlyspot.com/controlpanel]] (your control panel username is //matricedk//).\n<<tiddler tiddlyspotControls>>\n@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the "save to web" button in the column on the right.\n\n@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click "upload" and your ~TiddlyWiki will be saved back to tiddlyspot.com.\n\n@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki Guides|http://tiddlywikiguides.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].\n\n@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions.
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteAction'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><span macro='view gtd.project'></span></div>\n<div class='editor' macro='edit title'></div>\n<div class='editor' macro='edit text'></div>\n<div class='editor' macro='edit tags'></div>\n<div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<div class='toolbar' macro='toolbar changeContext projectify deleteAction closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><span macro='view gtd.project link'></span></div>\n<div class='subtitle'><span macro='view modified date [[DD MMM YYYY]]'></span> (created <span macro='view created date [[DD MMM YYYY]]'></span>)&nbsp;<span macro='gtdActionCompleted'></span>complete</div>\n<div class='tagging' macro='tagging'></div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div><br/>\n<div macro='newReminder'></div>\n
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteContext'></div>\n<div class='title' macro='view title'></div>\n<div class='editor' macro='edit title'></div>\n<div class='editor' macro='edit text'></div>\n<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<div class='toolbar' macro='toolbar newAction closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<div class='tagging'><span class='subtitle'><span macro='gtdToggleState chkGTDActionListReviewMode'></span>Review next actions only</span></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div>
Completed document conversion. Do not delete this tiddler unless you want to rebuild the action metadata.\n\nThis tiddler also contains document-specific preferences which, if deleted, will revert to default settings.
//Par ''Poulpy''//\n<<gradient horiz #bbbbbb #eeeeee #ffffff>>Voici un article visant à utiliser le dK system afin de jouer dans le cadre de la ville franche de Cadwallon. \nEn effet lorsque j'ai acheté ce jeu, j'ai adoré la partie background. Par contre, même si j'ai beaucoup apprécier le système de jeu (avec son coté tactique de gestion des actions/réactions très intéressant), je me voyait mal poussé les figs avec mes joueurs.\nJ'ai donc choisit a la place d'utiliser le dK afin de donner a Cadwallon un petit coté pulp qui lui va si bien.\nCette article n'a pas vocation a remplacé Cadwallon, d'ailleurs le Manuel des joueurs est indispensable pour jouer (j'y fait référence a plusieurs occasions), disons plutôt qu'il s'agit d'un joyeux fourre-tout visant a permettre de profiter d'un background très intéressant avec un système de jeu plus léger.>>\n!La création de personnage\nAvant toute chose, voici les points que je modifie ou les règles dKrunch que j'utilise:\n*Les atouts de peuples du dK sont remplacés par les peuples d'Aarklash décrit un peut plus loin et de nouveaux atouts font leur apparition pour simuler certains dons et signes particuliers qui n'avait pas d'équivalent dans le dK.\n*Les personnages francs-ligueurs commence au niveau 1 avec 5 atouts au lieu des 4 habituels afin de simuler le fameux "bagage de franc-ligueur" de la p.163.\n*On utilise les règles d'influence du dKrunch, les guildes, familles nobles, ambassades et autres églises étant autant de groupes auquel le personnage peut faire appel.\n*Les règles de maladies, poisons et véhicules (à vapeur ou naphte) sont appliqués.\n*La monnaie est de Ducat d'Or (DO), l'équipement du personnage est composé d'une arme d'amateur, de vêtements usés, d'une bourse, de 100DO et de une arme et armure de pro ou de brutasse OU d'une gemme mineur immortelle d'un élément au choix OU de deux pièces d'équipement de qualité donnant chacun +1 a une compétence au choix.\n!Les atouts de peuples\nUn certain nombre de peuples non humains parcourt la surface d’Aarklash et les rues de Cadwallon.\n!!!Les Elfes\nLes elfes d’Aarklash ce subdivise en trois grandes ethnies, ils partagent tous une taille élancée et des traits fins ainsi qu’une grâce qui semble parfois irréel.\n*Les elfes Daïkinees forme la souche originel, vivant en communion avec la nature, des plantes ainsi que des insectes vivent souvent en symbiose avec eux. Traits : Dextérité +1, Constitution -1, régénération, survie +2.\n*Les elfes Cynwäll ont choisit d’allé vivre dans les montagnes auprès des dragons. Ils sont généralement plus calme souvent distant et sont plus musclé que le reste de leur espèces. Traits : Dextérité +1, Concentration.\n*Enfin les elfes Akkyshans sont la branche ayant rejoint les méandres des ténèbres au coté de Lilith, ils présentent souvent quelques traits arachnéens. Traits : Dextérité +1, Constitution -1, Toxique, Vision Thermique.\n!!!Les Gobelins \nPetits et rusés, les gobelins sont capables de s’adapter à toutes les situations. On peut trouvé leur peaux vertes et leurs grandes oreilles sur tout le continent car tel le rat, le totem, ils ce sont déplacés partout, ce sont adaptés et sont particulièrement difficiles a éliminés complètement. \nTraits : Force -1, Intelligence +1, petit, sixième sens.\n!!!Les Nains.\nDe la même façon que les ethnies elfiques, il existe deux grand type de nains :\n*Les nains de Tir Na Bor sont la souche originels, endurante, travailleuse, solide. Ils sont plus petits que les humains mais aussi plus carrés, visuellement plus robuste. Traits : Constitution +1, dextérité -1, Chemise de fer, bonus de +4 dans un métier.\n*Les nains de Mid-Nor, eux sont des parodies de nains, torturé, défiguré, potentiellement immortel. Ceux interprétés par les joueurs feront parmi des rares a avoir réussit a ce soustraire a l’influence du Despote. Traits : Constitution +1, charisme -1, Possédé, vision thermique.\n!!!Les ogres.\nLes ogres d’Aarklash ont aujourd’hui presque disparut. Le seul lieu où une véritable communauté ogre existe est Cadwallon, mais même ici leur immense silhouette de plus de 2m provoque l’inquiétude et leurs habitudes carnassières provoquent la méfiance.\nTraits : Force +2, Constitution +1, Charisme -1, Sagesse -1, Grand.\n!!!Les orques.\nLa plus jeune race d’Aarklash, né des expérimentations Syhar sur des croisement d’humains et de gobelins, les orques sont désormais un peuples indépendant reconnaissable a leurs crocs proéminent, leur peau verte, leur musculature impressionnante et leur amour de la liberté.\nTraits : Force +1, Sagesse -1, un orque peut dépensé 1d6PE pour gagner un bonus de +1 en Force jusqu'à la fin de la scène, survie +2.\n!!!Les wolfens.\nLes hommes-loups, masse de muscle de 3m dont les accès de rage terrorisent même le plus vaillant des orques, parcours les rues de Cadwallon afin de chercher prestige, richesse et reconnaissance.\nTraits : Force +2, Charisme-1, Grand, rage destructrice, travers : violent.\n!Nouveaux atouts\nUn certain nombre de Signes particuliers de Cadwallon n’ont pas d’équivalent dans le dK système, j’ai donc essayé de les adapter sous la forme d’atouts.\n''Concentration'' (atout héroïque) : Le joueur choisit deux compétences et un avantage, lors d'un jet sur l'un de ses choix, le joueur peut dépenser un dK pour avoir un bonus de +4, il peut prendre cet atout plusieurs fois, choisissant 2 nouvelles compétences a chaque fois.\n''Mutagène'' (atout d’origine) : que ce soit parce que vous êtes un clone Syhar, un mutant gobelin ou un pauvre hère victime d'expériences innommables, vous avez désormais une grande capacité a vous adapté à votre environnement.\nUne fois par scène vous pouvez dépenser un dK pour gagner un bonus de +1 dans une caractéristique, évidemment ce bonus s'ajoute aussi aux avantages et compétences dépendantes de cette caractéristique. Ce bonus disparaît à la fin de la scène.\n''Possédé'' (atout d’origine) : Peut être êtes-vous un nain de Mid-Nor dont l’âme est emprisonné avec celle d’un démon dans un corps rafistolé ou peut vous pensé vous simplement investit d’une mission sacré. Toujours est-il que votre état vous permet d’ignoré la douleur et d’être incroyablement dur a tué. \nVous avez un bonus de +2 sur votre jet de sauvegarde pour ne pas mourir après une blessure.\n''Régénération'' (atout d’origine) : Comme les elfes Daïkinees, vous avez la capacité de soigner vos blessures d’un simple effort de concentration. Chaque tour, vous pouvez dépenser 2dK pour récupérer en échange 1d6 points de vie. Cet atout ne peut vous permettre de récupérer des points de vie quand vous êtes a 0PdV.\n''Toxique'' (atout d’origine) : À l’image des redoutables elfes Akkyshans ou de certaines création Syhars, vous avez la capacité de sécréter un poison au niveau de vos mains ou de votre bouche. Vous devez dépenser 1d6 PE pour sécréter une dose qui reste active pour la scène en cours. Le personnage est bien évidemment immunisé a son propre poison et les personnages qui sont affecté par la substance doivent réussir un jet en opposition de sauvegarde contre la sauvegarde du personnage toxique ou subir les effet du poison 1d6 tours plus tard (ou immédiatement si la victime fait un 1 sur son jet).\nLes effets du poison sont déterminés lors de l’acquisition de l’atout parmi la liste suivante : dégâts 2d6, sommeil pour 1d6 heures, perte de 1d6 dans une caractéristiques au choix (récupération d’un points par jour), paralysie pour 1d6 heures ou hallucination pour 1d6 heures.\n!Incantation et Divination\nLorsqu’un personnage choisit l’atout Magicien ou Adepte, il choisit l’un des styles ci-dessous.\n!!!Incantation (compétence : connaissance - Magie)\nLe magicien a apprit à manipuler les énergies élémentaires et c’est par ce moyen qu’il lance des sortilèges. Sa connaissance des courants élémentaire lui permet de puiser de l’énergie dans les gemmes de Mana afin de faciliter son art.\nQuand le joueur choisit ce style, il choisit aussi l’une des voies de magies cultuelles présentées dans les pages 263 à 277 du manuel des joueurs de Cadwallon. Cette voie donne le décorum par lequel le magicien manipule les éléments.\nEnsuite le joueur choisit le ou les domaines liés à ce style. Le(s) domaine(s) en question sont lié a l’élément primaire de la voie choisit précédemment (cf. tableau page 149), par la suite, si le joueur choisit l’atout Domaine, il pourra choisir de lié ses nouveaux domaines a l’élément primaire de sa voie ou aux autres éléments possibles de celle-ci.\n//Exemple : Thalion est un jeune nécromant élevé dans les limbes d’Achéron, son joueur choisit l’atout Magicien : Style Incantation avec la voie nécromancie (décrite p.271), il a automatiquement le domaine universel (ténèbres) et il décide de prendre comme domaines Mort et Malédiction tous deux aussi lié a l’élément Ténèbres. Si jamais lors d’un passage de niveau, il prend l’atout domaine, il pourra choisir Feu (feu) et Conjuration (Feu) lui permettant de manipuler le feu et de conjuré/exorciser en utilisant des gemmes de feu pour l’aider.//\nLe gros avantage de ce style est la capacité du mage a puisé de l’énergie dans les gemmes de Mana afin de l’aider à lancer un sort. Quand il tient dans sa main une gemme de Mana dont l’élément est le même que celui du domaine du sort qu’il tente de lancer, il peut dépenser des points de la Réserve (cf. p342) de la gemme pour lancer autant de dK sur ce jet.\n//Exemple : retrouvons Thalion alors qu’il essaie de survivre aux assauts d’un orque mal intentionné. Il décide de maudire la grosse brute d’un sort bien sentie de vision floue (-2 a l’attaque si l’orque rate sa sauvegarde). Il s’agit donc d’un sort du domaine Malédiction (Ténèbres), si jamais Thalion a à ce moment la une gemme mineur immortelle de ténèbres, il peut puiser dans la réserve de celle-ci jusqu'à 4 dK lancé au moment du test pour lancé le sort. Il augmente ainsi ses chances de réussite mais peut aussi réduire le coût en PE du sort.//\n!!!Divination (compétence : connaissance – Religion)\nLe personnage tire ses pouvoirs de sa relation avec un (ou plusieurs) dieu(x), que ce soit parce qu’il est un prêtre au service de ce dieu ou un simple croyant que le dieu a choisit de boosté un peu. Pour lancer un sort, le personnage ayant choisit ce style doit pouvoir récité une prière.\nL’avantage de ce Style est que la foi de ceux qui l’entoure peut aider le lanceur de sort dans sa magie. Lorsqu’il choisit ce style, le personnage choisit a quel litanie appartient son culte (Lumière, Ténèbres ou Destin si c’est un exilé ou Félicité, Destinée ou Souffrance si c’est un Cadwë.). Les bonus à la foi temporaire présenté dans la description des fiefs (pour la Lumière, les Ténèbres ou le Destin) ou dans le tableau page 296 (pour les fidèles Cadwës), deviennent ici autant de dK que le joueur lance lorsqu’il lance un sort dans l’un de ces zones.\n//Exemple : Asf’irion est un moine cynwäll, suivant la voie de la Noësis (un culte de la Lumière). Lorsqu’il lance un sort dans le fief de Drakaër, il gagne donc 2dK gratuit car de nombreux croyants de la lumière appuient inconsciemment sa magie. Par contre dans le Kraken, il ne devra compter que sur ses propres moyens.//\nDe la même façon, un chantre de la Destinée disposera de 2dK bonus pour tous sorts lancés dans Cadwallon, par contre, dés qu’il sortira des murs de la cité-franche, il devra se contenter de sa foi et de son énergie pour accomplir ses miracles.\n!!!Le Tarot (compétence : métier – cartomancien)\nCette magie exclusivement pratiquée à Cadwallon et dans ses environs est née de l’influence mystique d’un puissant artefact, le tarot de Vanius. Aujourd’hui, certains Cadwë sont capable de produire des effets magiques simplement en manipulant un jeu de carte reproduisant symboliquement celui de Vanius.\nDe plus, le tarot peut servir à la divination, une fois par séance de jeu, le personnage peut tenté une divination par l’intermédiaire de ses cartes, il passe alors une heure dans le jeu a tiré les cartes. Le joueur peut alors posé une question au Conteur portant sur le scénario auquel le Conteur répondra par oui ou non sans mentir. Après avoir posé sa question, le joueur peut dépenser 1 dK pour en posé une seconde, puis 2 DK supplémentaires pour une troisième et ainsi de suite.
Vous trouverez dans la fenêtre //Tagging//, à droite, la liste des catégories disponibles dans cette section.
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteProject deleteProjectAll'></div>\n<div class='title' macro='view title'></div>\n<div class='editor' macro='edit title'></div>\n<div class='editor' macro='edit text'></div>\n<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<div class='toolbar' macro='toolbar newProjectAction archiveProject deleteProject deleteProjectAll closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><!-- <span macro='view modifier link'></span>, --><span macro='view modified date [[DD MMM YYYY]]'></span> (created <span macro='view created date [[DD MMM YYYY]]'></span>)&nbsp;<span macro='gtdToggleTag important'></span>important&nbsp;<span macro='gtdToggleTag someday'></span>defer</div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div><br/><div macro='newReminder'></div>
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div><div class='subtitle' macro='today "DDD, MMM DD, YYYY hh:0mm"'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div>
| tiddlyspot password:|<<option pasUploadPassword>>|\n| site management:|<<upload http://matricedk.tiddlyspot.com/store.cgi index.html . . matricedk>>//(requires tiddlyspot password)//<<br>>[[control panel|http://matricedk.tiddlyspot.com/controlpanel]], [[download (go offline)|http://matricedk.tiddlyspot.com/download]]|\n| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[announcements|http://announce.tiddlyspot.com/]], [[blog|http://tiddlyspot.com/blog/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|